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

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
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.Calendar;
import java.util.Collections;
import java.util.Date;
import org.junit.jupiter.api.BeforeEach;
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 org.springframework.test.util.ReflectionTestUtils;
import com.ruoyi.web.modules.account.facade.IMemberFacade;
import com.ruoyi.web.modules.order.constant.OrderConstants;
import com.ruoyi.web.modules.order.domain.BizOrder;
import com.ruoyi.web.modules.order.domain.BizOrderItem;
import com.ruoyi.web.modules.order.mapper.BizOrderItemMapper;
import com.ruoyi.web.modules.order.mapper.BizOrderMapper;
import com.ruoyi.web.modules.order.service.impl.OrderAppServiceImpl;
import com.ruoyi.web.modules.order.service.impl.OrderPaySuccessServiceImpl;
import com.ruoyi.web.modules.order.support.CheckoutSupport;
import com.ruoyi.web.modules.pay.config.WeChatPayProperties;
import com.ruoyi.web.modules.pay.domain.BizPayRecord;
import com.ruoyi.web.modules.pay.mapper.BizPayRecordMapper;
import com.ruoyi.web.modules.pay.service.impl.WeChatPayServiceImpl;
import com.ruoyi.web.modules.pay.vo.WeChatPayParamsVO;

/**
 * 立即购买（BUY_NOW）· 支付 Mock 闭环
 */
@ExtendWith(MockitoExtension.class)
class BuyNowPayFlowTest
{
    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 com.ruoyi.web.modules.goods.mapper.BizGoodsMapper goodsMapper;

    @Mock
    private com.ruoyi.web.modules.cart.facade.ICartFacade cartFacade;

    @Mock
    private CheckoutSupport checkoutSupport;

    @Mock
    private BizPayRecordMapper payRecordMapper;

    @Mock
    private WeChatPayProperties payProperties;

    @InjectMocks
    private WeChatPayServiceImpl weChatPayService;

    @InjectMocks
    private OrderPaySuccessServiceImpl orderPaySuccessService;

    @InjectMocks
    private OrderAppServiceImpl orderAppService;

    private BizOrder order;

    @BeforeEach
    void setUp()
    {
        order = pendingOrder();
        ReflectionTestUtils.setField(weChatPayService, "checkoutSupport", checkoutSupport);
        ReflectionTestUtils.setField(orderPaySuccessService, "checkoutSupport", checkoutSupport);
        ReflectionTestUtils.setField(orderAppService, "weChatPayService", weChatPayService);
        ReflectionTestUtils.setField(orderAppService, "orderPaySuccessService", orderPaySuccessService);
    }

    @Test
    void buyNow_mockPay_completesWithoutOpenidAndSkipsCart()
    {
        when(memberFacade.isMemberEnabled(MEMBER_ID)).thenReturn(true);
        when(memberFacade.getWxOpenid(MEMBER_ID)).thenReturn(null);
        when(orderMapper.selectByIdAndMember(ORDER_ID, MEMBER_ID)).thenReturn(order);
        when(payProperties.isRealPayEnabled()).thenReturn(false);
        when(payRecordMapper.selectLatestByOrderId(ORDER_ID)).thenReturn(null);
        BizPayRecord record = new BizPayRecord();
        record.setPayId(1L);
        record.setOrderId(ORDER_ID);
        record.setPayStatus("0");
        when(payRecordMapper.selectByOutTradeNo(order.getOrderNo())).thenReturn(record);
        when(payRecordMapper.selectByWxTransactionId(any())).thenReturn(null);
        when(orderMapper.selectById(ORDER_ID)).thenReturn(order);
        BizOrderItem item = new BizOrderItem();
        item.setGoodsId(1L);
        item.setQuantity(2);
        item.setCartItemId(null);
        when(orderItemMapper.selectByOrderId(ORDER_ID)).thenReturn(Collections.singletonList(item));
        when(goodsMapper.deductStock(1L, 2)).thenReturn(1);
        when(orderMapper.updateForPay(any(BizOrder.class))).thenReturn(1);

        WeChatPayParamsVO result = orderAppService.createPay(MEMBER_ID, ORDER_ID);

        assertTrue(result.isMock());
        verify(payRecordMapper).insert(any(BizPayRecord.class));
        verify(orderMapper).updateForPay(any(BizOrder.class));
        verify(cartFacade, never()).removeItems(any(), any());
    }

    private BizOrder pendingOrder()
    {
        BizOrder row = new BizOrder();
        row.setOrderId(ORDER_ID);
        row.setMemberId(MEMBER_ID);
        row.setShopId(101L);
        row.setOrderStatus(OrderConstants.STATUS_PENDING_PAY);
        row.setPayAmount(new BigDecimal("25.00"));
        row.setOrderNo("O20260526000001");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR, 1);
        row.setPayExpireTime(calendar.getTime());
        return row;
    }
}
