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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.cart.facade.ICartFacade;
import com.ruoyi.web.modules.goods.domain.BizGoods;
import com.ruoyi.web.modules.goods.mapper.BizGoodsMapper;
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.IOrderPaySuccessService;
import com.ruoyi.web.modules.order.support.CheckoutSupport;
import com.ruoyi.web.modules.pay.constant.PayConstants;
import com.ruoyi.web.modules.pay.domain.BizPayRecord;
import com.ruoyi.web.modules.pay.mapper.BizPayRecordMapper;
import com.ruoyi.web.modules.stock.dto.OrderDeductOutboundCommand;
import com.ruoyi.web.modules.stock.dto.OrderDeductOutboundLine;
import com.ruoyi.web.modules.stock.service.IStockOutboundFacade;

/**
 * 支付成功落单
 */
@Service
public class OrderPaySuccessServiceImpl implements IOrderPaySuccessService
{
    @Autowired
    private BizOrderMapper orderMapper;

    @Autowired
    private BizOrderItemMapper orderItemMapper;

    @Autowired
    private BizGoodsMapper goodsMapper;

    @Autowired
    private ICartFacade cartFacade;

    @Autowired
    private CheckoutSupport checkoutSupport;

    @Autowired
    private BizPayRecordMapper payRecordMapper;

    @Autowired
    private IStockOutboundFacade stockOutboundFacade;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeWeChatPay(String outTradeNo, String transactionId, Date payTime)
    {
        BizPayRecord paidByTx = payRecordMapper.selectByWxTransactionId(transactionId);
        if (paidByTx != null && PayConstants.PAY_STATUS_SUCCESS.equals(paidByTx.getPayStatus()))
        {
            return;
        }
        BizPayRecord payRecord = payRecordMapper.selectByOutTradeNo(outTradeNo);
        if (payRecord == null)
        {
            throw new ServiceException(OrderConstants.MSG_NOT_FOUND);
        }
        if (PayConstants.PAY_STATUS_SUCCESS.equals(payRecord.getPayStatus()))
        {
            return;
        }
        BizOrder order = orderMapper.selectById(payRecord.getOrderId());
        if (order == null)
        {
            throw new ServiceException(OrderConstants.MSG_NOT_FOUND);
        }
        if (OrderConstants.STATUS_PENDING_SHIP.equals(order.getOrderStatus())
                || OrderConstants.STATUS_SHIPPED.equals(order.getOrderStatus())
                || OrderConstants.STATUS_COMPLETED.equals(order.getOrderStatus()))
        {
            payRecordMapper.updateForSuccess(payRecord.getPayId(), transactionId, payTime);
            return;
        }
        checkoutSupport.assertPendingPay(order);
        checkoutSupport.assertNotExpired(order, payTime);
        List<BizOrderItem> items = orderItemMapper.selectByOrderId(order.getOrderId());
        List<OrderDeductOutboundLine> outboundLines = new ArrayList<>();
        for (BizOrderItem item : items)
        {
            BizGoods goods = goodsMapper.selectById(item.getGoodsId());
            if (goods == null)
            {
                throw new ServiceException(OrderConstants.MSG_STOCK_DEDUCT_FAILED);
            }
            int stockBefore = goods.getStock() != null ? goods.getStock() : 0;
            int updated = goodsMapper.deductStock(item.getGoodsId(), item.getQuantity());
            if (updated == 0)
            {
                throw new ServiceException(OrderConstants.MSG_STOCK_DEDUCT_FAILED);
            }
            OrderDeductOutboundLine line = new OrderDeductOutboundLine();
            line.setGoodsId(item.getGoodsId());
            line.setGoodsName(item.getGoodsName());
            line.setMainPic(item.getGoodsImage());
            line.setSpecText(StringUtils.isNotEmpty(item.getGoodsSpec()) ? item.getGoodsSpec() : null);
            line.setQuantity(item.getQuantity());
            line.setStockBefore(stockBefore);
            line.setStockAfter(stockBefore - item.getQuantity());
            outboundLines.add(line);
        }
        order.setPayType(OrderConstants.PAY_TYPE_WECHAT);
        order.setPayTime(payTime);
        order.setTradeNo(transactionId);
        if (orderMapper.updateForPay(order) == 0)
        {
            throw new ServiceException(OrderConstants.MSG_PENDING_PAY_ONLY);
        }
        payRecordMapper.updateForSuccess(payRecord.getPayId(), transactionId, payTime);
        OrderDeductOutboundCommand outboundCmd = new OrderDeductOutboundCommand();
        outboundCmd.setShopId(order.getShopId());
        outboundCmd.setOrderId(order.getOrderId());
        outboundCmd.setOrderNo(order.getOrderNo());
        outboundCmd.setOutboundTime(payTime);
        outboundCmd.setLines(outboundLines);
        stockOutboundFacade.createOrderDeductOutbound(outboundCmd);
        List<Long> cartItemIds = new ArrayList<>();
        for (BizOrderItem item : items)
        {
            if (item.getCartItemId() != null)
            {
                cartItemIds.add(item.getCartItemId());
            }
        }
        if (!cartItemIds.isEmpty())
        {
            cartFacade.removeItems(order.getMemberId(), cartItemIds);
        }
    }
}
