package com.zbkj.service.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.exception.CrmebWalletException;
import com.zbkj.common.model.order.VirtualOrder;
import com.zbkj.common.model.order.VirtualOrderOperate;
import com.zbkj.common.model.user.User;
import com.zbkj.common.request.CreateOrderRequest;
import com.zbkj.common.response.OrderNoResponse;
import com.zbkj.common.response.VirtualOrderResponse;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.common.vo.MyRecord;
import com.zbkj.common.vo.PreMerchantOrderVo;
import com.zbkj.common.vo.PreOrderInfoDetailVo;
import com.zbkj.common.vo.PreOrderInfoVo;
import com.zbkj.service.config.PaymentChannel;
import com.zbkj.service.dao.VirtualOrderDao;
import com.zbkj.service.factory.PaymentFactory;
import com.zbkj.service.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <b> VirtualOrderServiceImpl </b>
 * @author ZXF
 * @create 2025/08/26 0026 14:27
 * @version
 * @注意事项 </b>
 */
@Service
public class VirtualOrderServiceImpl extends ServiceImpl<VirtualOrderDao, VirtualOrder> implements VirtualOrderService {

    private final Logger logger = LoggerFactory.getLogger(VirtualOrderServiceImpl.class);
    @Resource
    private VirtualOrderDao dao;
    @Resource
    private VirtualOrderOperateService virtualOrderOperateService;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private PaymentFactory paymentFactory;
    @Autowired
    CommonWalletService commonWalletService;

    /**
     * 根据虚拟单号获取详情
     * @param virtualOrderNo 虚拟单号
     * @return VirtualOrder
     */
    @Override
    public VirtualOrder getByVirtualOrderNo(String virtualOrderNo) {
        LambdaQueryWrapper<VirtualOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(VirtualOrder::getVirtualOrderNo, virtualOrderNo);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }
    @Override
    public VirtualOrderResponse getVirtualOrderByVirtualOrderNo(String virtualOrderNo) {
        return dao.getVirtualOrderByVirtualOrderNo(virtualOrderNo);
    }

    /**
     * <b> 查询虚拟订单列表 </b>
     * @author ZXF
     * @create 2025/08/26 0026 14:33
     * @version
     * @注意事项 </b>
     */
    @Override
    public List<VirtualOrderResponse> queryVirtualOrderList(Map<String, Object> queryParam) {
        return dao.queryVirtualOrderList(queryParam);
    }

    /**
     * 获取用户存在剩余可用数量的记录按id升序
     * @param uid 用户id
     * @return 虚拟订单列表
     */
    @Override
    public List<VirtualOrderResponse> queryExistAvailableNumByUid(Integer uid) {
        return dao.queryExistAvailableNumByUid(uid);
    }
    /**
     * 获取用户剩余可用数量
     * @param uid 用户id
     * @return 剩余可用数量
     */
    @Override
    public int countAvailableNumByUid(Integer uid) {
        return dao.countAvailableNumByUid(uid);
    }

    /**
     * <b> 商城下单生成虚拟订单 </b>
     * @author ZXF
     * @create 2025/08/26 0026 15:30
     * @version
     * @注意事项 </b>
     */
    @Override
    public OrderNoResponse createOrder(CreateOrderRequest orderRequest, PreOrderInfoVo orderInfoVo,List<MyRecord> skuRecordList, User user) {
        PreMerchantOrderVo merchantOrderVo = orderInfoVo.getMerchantOrderVoList().get(0);
        PreOrderInfoDetailVo detailVo = merchantOrderVo.getOrderInfoList().get(0);
        VirtualOrder virtualOrder = new VirtualOrder();
        virtualOrder.setVirtualOrderNo(CrmebUtil.getOrderNo(OrderConstants.ORDER_ATTR_VIR_SIGN));
        virtualOrder.setMerId(orderInfoVo.getMerId());
        virtualOrder.setUid(user.getId());
        virtualOrder.setProductId(detailVo.getProductId());
        virtualOrder.setProductName(detailVo.getProductName());
        virtualOrder.setAttrValueId(detailVo.getAttrValueId());
        virtualOrder.setSku(detailVo.getSku());
        virtualOrder.setPrice(detailVo.getPrice());
        virtualOrder.setPayNum(detailVo.getPayNum());
        virtualOrder.setTotalPrice(detailVo.getPrice().multiply(new BigDecimal(detailVo.getPayNum())));
        virtualOrder.setDealNum(0);
        virtualOrder.setRefundNum(0);
        virtualOrder.setCreateOrderRequest(JSON.toJSONString(orderRequest));
        virtualOrder.setPreOrderInfoVo(JSON.toJSONString(orderInfoVo));
        virtualOrder.setCreateTime(new Date());
        virtualOrder.setUpdateTime(new Date());
        virtualOrder.setStatus(OrderConstants.ORDER_STATUS_WAIT_PAY);
        virtualOrder.setSourceId(detailVo.getSourceId());

        Boolean execute = transactionTemplate.execute(e -> {
            Boolean result = true;
            logger.info("虚拟订单-开始扣件商品库存:virtualOrder:{}", JSON.toJSONString(virtualOrder));
            if (orderInfoVo.getType().equals(OrderConstants.ORDER_TYPE_NORMAL)) { // 普通商品
                logger.info("虚拟订单-开始扣件商品库存 --> 普通商品:{}", JSON.toJSONString(skuRecordList));
                // 扣减库存
                for (MyRecord skuRecord : skuRecordList) {
                    // 普通商品口库存
                    result = productService.operationStock(skuRecord.getInt("productId"), skuRecord.getInt("num"), Constants.OPERATION_TYPE_SUBTRACT);
                    if (!result) {
                        e.setRollbackOnly();
                        logger.error("虚拟订单-生成订单扣减商品库存失败,预下单号：{},商品ID：{}", orderRequest.getPreOrderNo(), skuRecord.getInt("productId"));
                        return result;
                    }
                    // 普通商品规格扣库存
                    result = productAttrValueService.operationStock(skuRecord.getInt("attrValueId"), skuRecord.getInt("num"), Constants.OPERATION_TYPE_SUBTRACT, ProductConstants.PRODUCT_TYPE_NORMAL, skuRecord.getInt("attrValueVersion"));
                    if (!result) {
                        e.setRollbackOnly();
                        logger.error("虚拟订单-生成订单扣减商品sku库存失败,预下单号：{},商品skuID：{}", orderRequest.getPreOrderNo(), skuRecord.getInt("attrValueId"));
                        return result;
                    }
                }
            }
            // 保存虚拟订单
            save(virtualOrder);
            return Boolean.TRUE;
        });
        if (!execute) {
            throw new CrmebException("虚拟订单生成失败");
        }

        OrderNoResponse response = new OrderNoResponse();
        response.setOrderNo(virtualOrder.getVirtualOrderNo());
        response.setPayPrice(virtualOrder.getTotalPrice());
        return response;
    }

    /**
     * <b> 虚拟订单支付 </b>
     * @author ZXF
     * @create 2025/08/26 0026 14:33
     * @version
     * @param uniId 账户id
     * @param virtualOrder 虚拟订单信息
     **/
    @Override
    public boolean virtualOrderPay(VirtualOrder virtualOrder, String uniId) {
        return transactionTemplate.execute(i -> {
            //账户金额冻结
            try {
                //标记为已支付
                virtualOrder.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
                virtualOrder.setUpdateTime(new Date());
                updateById(virtualOrder);
                if (virtualOrder.getTotalPrice().compareTo(BigDecimal.ZERO) != 0) {
                    return commonWalletService.modifyBalance(uniId, virtualOrder.getTotalPrice(),systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL));// 企业钱包余额冻结
                }
            } catch (Exception ex) {
                logger.error("virtualOrderPay.modifyBalance" + " | msg : " + ex.getMessage());
                return Boolean.FALSE;
            }
            return Boolean.TRUE;
        });
    }

    /**
     * <b> 根据操作类型调整相应使用数量 </b>
     * @param virtualOrderMap 要退虚拟订单和对应数量
     * @param user 操作用户
     * @author ZXF
     * @create 2025/08/26 0026 14:38
     * @version
     * @注意事项 </b>
     */
    @Override
    public boolean changeNumByVirtualOrderMap(Map<String, Long> virtualOrderMap, User user) {
        Boolean execute = transactionTemplate.execute(i -> {
            List<VirtualOrderOperate> olist = new ArrayList<>();
            AtomicReference<BigDecimal> amount = new AtomicReference<>(BigDecimal.ZERO);
            virtualOrderMap.forEach((key, value) -> {
                Integer num = Math.toIntExact(value);
                VirtualOrderResponse orderResponse = getVirtualOrderByVirtualOrderNo(key);
                if(orderResponse == null){
                    throw new CrmebException("订单不存在退款失败");
                }
                if(orderResponse.getAvailableNum() < num){
                    throw new CrmebException("用户剩余可用数量不足");
                }
                orderResponse.setRefundNum(orderResponse.getRefundNum()+num);
                dao.updateNumByType(orderResponse);
                olist.add(buildOperate(orderResponse,2,num));
                amount.set(amount.get().add(orderResponse.getPrice().multiply(new BigDecimal(num))));
            });
            //保存操作记录
            virtualOrderOperateService.saveBatch(olist);
            //账户金额冻结
            try {
                BigDecimal price = amount.get();
                if (price.compareTo(BigDecimal.ZERO) != 0) {
                    return commonWalletService.modifyBalance(user.getIdentityNo(), price.negate(),systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL));
                }
            } catch (Exception ex) {
                logger.error("changeNumByVirtualOrderMap.modifyBalance" + " | msg : " + ex.getMessage());
                return Boolean.FALSE;
            }
            return Boolean.TRUE;
        });

        if (!execute) throw new CrmebException("退款失败！");
        return true;
    }

    /**
     * <b> 根据操作类型调整相应使用数量 </b>
     * @param virtualOrderMap 要使用虚拟订单和对应数量
     * @author ZXF
     * @create 2025/08/26 0026 14:38
     * @version
     * @注意事项 </b>
     */
    @Override
    public boolean dealNumByVirtualOrderMap(Map<String, Long> virtualOrderMap, User user) {
        Boolean execute = transactionTemplate.execute(i -> {
            List<VirtualOrderOperate> olist = new ArrayList<>();
            AtomicReference<BigDecimal> amount = new AtomicReference<>(BigDecimal.ZERO);
            virtualOrderMap.forEach((key, value) -> {
                Integer num = Math.toIntExact(value);
                VirtualOrderResponse orderResponse = getVirtualOrderByVirtualOrderNo(key);
                if(orderResponse == null){
                    throw new CrmebException("订单不存在退款失败");
                }
                if(orderResponse.getAvailableNum() < num){
                    throw new CrmebException("用户剩余可用数量不足");
                }
                orderResponse.setDealNum(orderResponse.getDealNum()+num);
                //
                dao.updateNumByType(orderResponse);
                olist.add(buildOperate(orderResponse,1,num));
                amount.set(amount.get().add(orderResponse.getPrice().multiply(new BigDecimal(num))));
            });

            //保存操作记录
            virtualOrderOperateService.saveBatch(olist);
            //账户金额冻结
            try {
                BigDecimal price = amount.get();
                if (price.compareTo(BigDecimal.ZERO) != 0) {
                    return commonWalletService.modifyBalance(user.getIdentityNo(), price.negate(),systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL));
                }
            } catch (Exception ex) {
                logger.error("dealNumByVirtualOrderMap.modifyBalance" + " | msg : " + ex.getMessage());
                return Boolean.FALSE;
            }

            return Boolean.TRUE;
        });

        if (!execute) throw new CrmebException("虚单数量消耗失败！");
        return true;
    }

    private VirtualOrderOperate buildOperate(VirtualOrderResponse virtualOrder, Integer type, Integer num) {
        VirtualOrderOperate operate = new VirtualOrderOperate();
        //virtualOrder 参数一一对应设置到 operate
        operate.setOperateNo(CrmebUtil.getUuid());
        operate.setVirtualOrderNo(virtualOrder.getVirtualOrderNo());
        operate.setMerId(virtualOrder.getMerId());
        operate.setUid(virtualOrder.getUid());
        operate.setProductId(virtualOrder.getProductId());
        operate.setProductName(virtualOrder.getProductName());
        operate.setAttrValueId(virtualOrder.getAttrValueId());
        operate.setSku(virtualOrder.getSku());
        operate.setPrice(virtualOrder.getPrice());
        operate.setOperateNum(num);
        operate.setTotalPrice(virtualOrder.getPrice().multiply(new BigDecimal(num)));
        operate.setOperateType(type==1?"交易":"退款");
        operate.setCreateTime(new Date());
        operate.setUpdateTime(new Date());
        return operate;
    }
}

