package com.ruoyi.web.modules.order.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.account.domain.BizMember;
import com.ruoyi.web.modules.account.facade.IMemberFacade;
import com.ruoyi.web.modules.order.constant.OrderAppConstants;
import com.ruoyi.web.modules.order.constant.OrderConstants;
import com.ruoyi.web.modules.order.domain.BizGoodsReview;
import com.ruoyi.web.modules.order.domain.BizOrder;
import com.ruoyi.web.modules.order.domain.BizOrderItem;
import com.ruoyi.web.modules.order.dto.OrderReviewSubmitDTO;
import com.ruoyi.web.modules.order.mapper.BizGoodsReviewMapper;
import com.ruoyi.web.modules.order.mapper.BizOrderItemMapper;
import com.ruoyi.web.modules.order.mapper.BizOrderMapper;
import com.ruoyi.web.modules.order.service.impl.OrderReviewAppServiceImpl;
import com.ruoyi.web.modules.order.support.OrderAppSupport;
import com.ruoyi.web.modules.order.vo.OrderAppItemSummaryVO;
import com.ruoyi.web.modules.order.vo.OrderReviewListRowVO;

@ExtendWith(MockitoExtension.class)
class OrderReviewAppServiceImplTest
{
    private static final Long MEMBER_ID = 200L;

    private static final Long ORDER_ID = 900L;

    @Mock
    private IMemberFacade memberFacade;

    @Mock
    private BizOrderMapper orderMapper;

    @Mock
    private BizOrderItemMapper orderItemMapper;

    @Mock
    private BizGoodsReviewMapper reviewMapper;

    @Mock
    private OrderAppSupport orderAppSupport;

    @InjectMocks
    private OrderReviewAppServiceImpl reviewAppService;

    @Test
    void list_done_usesOrderItemSnapshot()
    {
        when(memberFacade.isMemberEnabled(MEMBER_ID)).thenReturn(true);
        BizGoodsReview review = new BizGoodsReview();
        review.setReviewId(1L);
        review.setOrderId(ORDER_ID);
        review.setOrderItemId(11L);
        review.setGoodsId(2L);
        review.setScore(5);
        review.setContent("很好");
        review.setCreateTime(new Date());
        review.setGoodsMainPic("review-pic.jpg");
        review.setGoodsSpec("review-spec");
        when(reviewMapper.selectMemberList(MEMBER_ID)).thenReturn(Collections.singletonList(review));

        BizOrder order = new BizOrder();
        order.setOrderId(ORDER_ID);
        order.setOrderNo("NO001");
        order.setOrderStatus(OrderConstants.STATUS_COMPLETED);
        order.setShopId(10L);
        order.setShopName("牛牛店铺");
        order.setPayAmount(new BigDecimal("99.00"));
        when(orderMapper.selectByIdAndMember(ORDER_ID, MEMBER_ID)).thenReturn(order);
        when(orderAppSupport.toStatusText(OrderConstants.STATUS_COMPLETED)).thenReturn("交易成功");

        BizOrderItem item = new BizOrderItem();
        item.setItemId(11L);
        item.setOrderId(ORDER_ID);
        item.setGoodsId(2L);
        item.setGoodsName("测试商品");
        item.setGoodsSpec("批次：2024春季");
        item.setGoodsImage("order-pic.jpg");
        item.setUnitPrice(new BigDecimal("99.00"));
        item.setQuantity(1);
        when(orderItemMapper.selectByOrderIds(Collections.singletonList(ORDER_ID)))
                .thenReturn(Collections.singletonList(item));

        OrderAppItemSummaryVO summary = new OrderAppItemSummaryVO();
        summary.setGoodsName("测试商品");
        summary.setUnitPrice(new BigDecimal("99.00"));
        summary.setQuantity(1);
        when(orderAppSupport.toItemSummary(item)).thenReturn(summary);

        OrderReviewListRowVO row = reviewAppService.list(MEMBER_ID, OrderAppConstants.REVIEW_TAB_DONE).get(0);
        assertNotNull(row.getFirstItem());
        assertEquals("测试商品", row.getFirstItem().getGoodsName());
        assertEquals(new BigDecimal("99.00"), row.getFirstItem().getUnitPrice());
        verify(orderAppSupport).toItemSummary(item);
    }

    @Test
    void submit_success()
    {
        when(memberFacade.isMemberEnabled(MEMBER_ID)).thenReturn(true);
        BizOrder order = new BizOrder();
        order.setOrderId(ORDER_ID);
        order.setOrderStatus(OrderConstants.STATUS_COMPLETED);
        order.setShopId(10L);
        when(orderMapper.selectByIdAndMember(ORDER_ID, MEMBER_ID)).thenReturn(order);
        when(reviewMapper.selectByOrderItemId(1L)).thenReturn(null);
        BizOrderItem item = new BizOrderItem();
        item.setItemId(1L);
        item.setGoodsId(2L);
        item.setGoodsImage("pic.jpg");
        when(orderItemMapper.selectByOrderId(ORDER_ID)).thenReturn(Collections.singletonList(item));
        BizMember member = new BizMember();
        member.setNickName("买家");
        when(memberFacade.getMember(MEMBER_ID)).thenReturn(member);
        when(reviewMapper.insert(any())).thenReturn(1);

        OrderReviewSubmitDTO dto = new OrderReviewSubmitDTO();
        dto.setScore(5);
        dto.setContent("很好");
        dto.setOrderItemId(1L);
        reviewAppService.submit(MEMBER_ID, ORDER_ID, dto);

        verify(reviewMapper).insert(any());
    }

    @Test
    void submit_alreadyReviewed_throws()
    {
        when(memberFacade.isMemberEnabled(MEMBER_ID)).thenReturn(true);
        BizOrder order = new BizOrder();
        order.setOrderStatus(OrderConstants.STATUS_COMPLETED);
        when(orderMapper.selectByIdAndMember(ORDER_ID, MEMBER_ID)).thenReturn(order);
        BizOrderItem item = new BizOrderItem();
        item.setItemId(1L);
        when(orderItemMapper.selectByOrderId(ORDER_ID)).thenReturn(Collections.singletonList(item));
        when(reviewMapper.selectByOrderItemId(1L)).thenReturn(new BizGoodsReview());

        OrderReviewSubmitDTO dto = new OrderReviewSubmitDTO();
        dto.setScore(5);
        dto.setOrderItemId(1L);
        ServiceException ex = assertThrows(ServiceException.class,
                () -> reviewAppService.submit(MEMBER_ID, ORDER_ID, dto));
        assertEquals(OrderAppConstants.MSG_ALREADY_REVIEWED, ex.getMessage());
        verify(reviewMapper, never()).insert(any());
    }
}
