package com.sckw.order.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.LogisticsOrderV1Enum;
import com.sckw.core.utils.DateUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.response.BaseResult;
import com.sckw.order.api.model.TradeOrderDto;
import com.sckw.order.dao.KwoTradeOrderGoodsMapper;
import com.sckw.order.dao.KwoTradeOrderMapper;
import com.sckw.order.dao.KwoTradeOrderUnitMapper;
import com.sckw.order.enums.TradeOrderStatusEnum;
import com.sckw.order.model.KwoTradeOrder;
import com.sckw.order.model.KwoTradeOrderArchive;
import com.sckw.order.model.KwoTradeOrderGoods;
import com.sckw.order.model.KwoTradeOrderUnit;
import com.sckw.order.serivce.KwoTradeOrderArchiveService;
import com.sckw.order.serivce.KwoTradeOrderService;
import com.sckw.payment.api.dubbo.PaymentDubboService;
import com.sckw.payment.api.feign.PaymentFeignService;
import com.sckw.payment.api.model.feign.WalletPrepaidDto;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.product.api.model.KwpGoods;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.DictProduct;
import com.sckw.transport.api.dubbo.TransportRemoteService;
import com.sckw.transport.api.model.param.OrderFinishParam;
import com.sckw.transport.api.model.vo.KwtLogisticsOrderVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author xucaiqin
 * @date 2025-12-19 09:05:54
 */
@Slf4j
@Component
public class TradeOrderTask {
    @Resource
    private KwoTradeOrderMapper kwoTradeOrderMapper;
    @Resource
    private KwoTradeOrderArchiveService kwoTradeOrderArchiveService;
    @Resource
    private KwoTradeOrderUnitMapper kwoTradeOrderUnitMapper;
    @Resource
    private KwoTradeOrderGoodsMapper kwoTradeOrderGoodsMapper;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    private TransportRemoteService transportRemoteService;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    private PaymentDubboService paymentDubboService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private GoodsInfoService goodsInfoService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;

    @Autowired
    private PaymentFeignService paymentFeignService;
    @Autowired
    private KwoTradeOrderService kwoTradeOrderService;
    private final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(20));

    @Scheduled(cron = "0 0/10 * * * ?")
    public void task2() {
        List<TradeOrderDto> tradeOrderDtos = kwoTradeOrderMapper.joinSelect();
        if (CollUtil.isNotEmpty(tradeOrderDtos)) {
            Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.GOODS_SPEC.getType()));
            Map<String, String> goodsSpecMap = dict.get(DictTypeEnum.GOODS_SPEC.getType());

            Map<Long, KwpGoods> goodsByIds = goodsInfoService.getGoodsByIds(tradeOrderDtos.stream().map(TradeOrderDto::getGoodsId).toList());
            List<KwoTradeOrderArchive> list = tradeOrderDtos.stream().map(d -> {
                KwoTradeOrderArchive kwoTradeOrderArchive = new KwoTradeOrderArchive();
                kwoTradeOrderArchive.setTradeOrderId(d.getId());
                kwoTradeOrderArchive.setGoodsId(d.getGoodsId());
                KwpGoods kwpGoods = goodsByIds.get(d.getGoodsId());
                if (Objects.nonNull(kwpGoods)) {
                    DictProduct dictProduct = remoteSystemService.queryProductName(kwpGoods.getGoodsType());
                    if (Objects.nonNull(dictProduct)) {
                        kwoTradeOrderArchive.setProductName(dictProduct.getLabel());
                    }
                    kwoTradeOrderArchive.setProductSpec(goodsSpecMap.get(kwpGoods.getSpec()));
                }

                kwoTradeOrderArchive.setUnitPrice(d.getUnitPrice());
                if (Objects.equals(d.getChargeType(), 1)) {
                    kwoTradeOrderArchive.setAmount(d.getLoadAmount());
                } else {
                    kwoTradeOrderArchive.setAmount(d.getUnloadAmount());
                }
                return kwoTradeOrderArchive;

            }).toList();
            kwoTradeOrderArchiveService.saveBatch(list);
            for (TradeOrderDto tradeOrderDto : tradeOrderDtos) {
                KwoTradeOrder kwoTradeOrder = new KwoTradeOrder();
                kwoTradeOrder.setId(tradeOrderDto.getId());
                kwoTradeOrder.setArchiveFlag(1);
                kwoTradeOrderMapper.updateById(kwoTradeOrder);
            }
        }
    }

    @Scheduled(cron = "0 0/5 * * * ?")
    public void task() {
        log.info("定时任务");
        List<KwoTradeOrder> kwoTradeOrders = kwoTradeOrderMapper.selectList(new LambdaQueryWrapper<KwoTradeOrder>().eq(KwoTradeOrder::getStatus, TradeOrderStatusEnum.DEAL.getCode()).eq(KwoTradeOrder::getDelFlag, Global.UN_DELETED));
        if (CollUtil.isNotEmpty(kwoTradeOrders)) {
            for (KwoTradeOrder kwoTradeOrder : kwoTradeOrders) {
                List<KwtLogisticsOrderVO> logisticOrderList = transportRemoteService.getLogisticOrderList(new OrderFinishParam(kwoTradeOrder.getId()));
                //没有订单
                if (CollUtil.isEmpty(logisticOrderList)) {
                    threadPoolExecutor.execute(() -> {
                        log.info("没有物流订单结算");
                        try {
                            List<KwoTradeOrderUnit> orderUnits = kwoTradeOrderUnitMapper.selectList(new LambdaQueryWrapper<KwoTradeOrderUnit>().eq(KwoTradeOrderUnit::getTOrderId, kwoTradeOrder.getId()).eq(KwoTradeOrderUnit::getDelFlag, 0));
                            if (CollUtil.isEmpty(orderUnits) || orderUnits.size() < 2) {
                                log.error("订单异常，未找到关联企业。订单id {}", kwoTradeOrder.getId());
                                return;
                            }
                            Map<String, KwoTradeOrderUnit> unitMap = orderUnits.stream().collect(Collectors.toMap(KwoTradeOrderUnit::getUnitType, Function.identity(), (a, b) -> a));

                            KwoTradeOrderGoods kwoTradeOrderGoods = kwoTradeOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwoTradeOrderGoods>().eq(KwoTradeOrderGoods::getDelFlag, 0).eq(KwoTradeOrderGoods::getTOrderId, kwoTradeOrder.getId()).last("limit 1"));


                            kwoTradeOrder.setStatus(TradeOrderStatusEnum.SUCCESS.getCode());
                            kwoTradeOrderMapper.updateById(kwoTradeOrder);
                            try {
                                Boolean aBoolean = transportRemoteService.logisticOrderFinish(new OrderFinishParam(kwoTradeOrder.getId()));
                            } catch (Exception e) {
                                log.error("物流订单结算失败 {}", e.getMessage());
                            }
                            try {
                                kwoTradeOrderService.settleChargeStrategyAfterLogisticOrderFinish(kwoTradeOrder.getId());
                            } catch (Exception e) {
                                log.error("结算服务费失败 ==>", e);
                            }
                            calculatePrepaidBalance(kwoTradeOrder, unitMap, kwoTradeOrderGoods.getUnitPrice());
                        } catch (Exception ex) {
                            log.error("更新订单异常{}", ex.getMessage());
                        }
                    });
                } else {
                    if (logisticOrderList.stream().allMatch(d -> Objects.equals(LogisticsOrderV1Enum.COMPLETED.getCode(), d.getStatus()))) {
                        threadPoolExecutor.execute(() -> {
                            try {
                                List<KwoTradeOrderUnit> orderUnits = kwoTradeOrderUnitMapper.selectList(new LambdaQueryWrapper<KwoTradeOrderUnit>().eq(KwoTradeOrderUnit::getTOrderId, kwoTradeOrder.getId()).eq(KwoTradeOrderUnit::getDelFlag, 0));
                                if (CollUtil.isEmpty(orderUnits) || orderUnits.size() < 2) {
                                    log.error("订单异常，未找到关联企业。订单id {}", kwoTradeOrder.getId());
                                    return;
                                }
                                Map<String, KwoTradeOrderUnit> unitMap = orderUnits.stream().collect(Collectors.toMap(KwoTradeOrderUnit::getUnitType, Function.identity(), (a, b) -> a));
                                BigDecimal sum;
                                if (Objects.equals(kwoTradeOrder.getChargeType(), 1)) {
                                    //按装货量
                                    sum = logisticOrderList.stream().map(KwtLogisticsOrderVO::getLoadAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                } else {
                                    sum = logisticOrderList.stream().map(KwtLogisticsOrderVO::getUnloadAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                }
                                KwoTradeOrderGoods kwoTradeOrderGoods = kwoTradeOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwoTradeOrderGoods>().eq(KwoTradeOrderGoods::getDelFlag, 0).eq(KwoTradeOrderGoods::getTOrderId, kwoTradeOrder.getId()).last("limit 1"));


                                kwoTradeOrder.setStatus(TradeOrderStatusEnum.SUCCESS.getCode());
                                kwoTradeOrderMapper.updateById(kwoTradeOrder);
                                try {
                                    Boolean aBoolean = transportRemoteService.logisticOrderFinish(new OrderFinishParam(kwoTradeOrder.getId()));
                                } catch (Exception e) {
                                    log.error("物流订单结算失败 {}", e.getMessage());
                                }
                                try {
                                    kwoTradeOrderService.settleChargeStrategyAfterLogisticOrderFinish(kwoTradeOrder.getId());
                                } catch (Exception e) {
                                    log.error("结算服务费失败 ==>", e);
                                }
                                kwoTradeOrder.setPrice(NumberUtil.mul(sum, kwoTradeOrderGoods.getUnitPrice()));
                                calculatePrepaidBalance(kwoTradeOrder, unitMap, kwoTradeOrderGoods.getUnitPrice());
                            } catch (Exception ex) {
                                log.error("更新订单异常{}", ex.getMessage());
                            }
                        });
                    }
                }


            }

        }
        List<KwoTradeOrder> kwoTradeOrders2 = kwoTradeOrderMapper.selectList(new LambdaQueryWrapper<KwoTradeOrder>().in(KwoTradeOrder::getStatus, List.of(TradeOrderStatusEnum.AUDIT.getCode(), TradeOrderStatusEnum.ING.getCode())).lt(KwoTradeOrder::getEndTime, DateUtils.getEndOfDay(new Date())).eq(KwoTradeOrder::getDelFlag, Global.UN_DELETED));
        if (CollUtil.isNotEmpty(kwoTradeOrders2)) {
            threadPoolExecutor.execute(() -> {
                Map<Integer, List<KwoTradeOrder>> collect = kwoTradeOrders2.stream().collect(Collectors.groupingBy(KwoTradeOrder::getStatus));
                for (Map.Entry<Integer, List<KwoTradeOrder>> one : collect.entrySet()) {
                    List<KwoTradeOrder> value = one.getValue();
                    if (CollUtil.isEmpty(value)) {
                        continue;
                    }
                    if (Objects.equals(one.getKey(), TradeOrderStatusEnum.AUDIT.getCode())) {
                        for (KwoTradeOrder kwoTradeOrder : value) {
//                            WalletFreeze walletFreeze = new WalletFreeze();
//                            walletFreeze.setTTradeOrderId(kwoTradeOrder.getId());
//                            walletFreeze.setOrderNo(kwoTradeOrder.getTOrderNo());
//                            BaseResult<Boolean> booleanBaseResult = paymentDubboService.unfreezeMoney(walletFreeze);
//                            log.info("解冻结果：{}", JSONObject.toJSONString(booleanBaseResult));
                            kwoTradeOrder.setStatus(TradeOrderStatusEnum.SUCCESS.getCode());
                            kwoTradeOrderMapper.updateById(kwoTradeOrder);
                            List<KwoTradeOrderUnit> orderUnits = kwoTradeOrderUnitMapper.selectList(new LambdaQueryWrapper<KwoTradeOrderUnit>().eq(KwoTradeOrderUnit::getTOrderId, kwoTradeOrder.getId()).eq(KwoTradeOrderUnit::getDelFlag, 0));
                            if (CollUtil.isEmpty(orderUnits) || orderUnits.size() < 2) {
                                log.error("订单异常，未找到关联企业。订单id {}", kwoTradeOrder.getId());
                                return;
                            }
                            Map<String, KwoTradeOrderUnit> unitMap = orderUnits.stream().collect(Collectors.toMap(KwoTradeOrderUnit::getUnitType, Function.identity(), (a, b) -> a));
                        }
                    }
                    if (Objects.equals(one.getKey(), TradeOrderStatusEnum.ING.getCode())) {
                        for (KwoTradeOrder kwoTradeOrder : value) {
                            kwoTradeOrder.setStatus(TradeOrderStatusEnum.DEAL.getCode());
                            kwoTradeOrderMapper.updateById(kwoTradeOrder);
                            try {
                                Boolean aBoolean = transportRemoteService.logisticOrderFinish(new OrderFinishParam(kwoTradeOrder.getId()));
                            } catch (Exception e) {
                                log.error("物流订单结算失败 {}", e.getMessage());
                            }
                            try {
                                kwoTradeOrderService.settleChargeStrategyAfterLogisticOrderFinish(kwoTradeOrder.getId());
                            } catch (Exception e) {
                                log.error("结算服务费失败 ==>", e);
                            }
                        }
                    }
                }
            });
        }
    }

    private void calculatePrepaidBalance(KwoTradeOrder kwoTradeOrder, Map<String, KwoTradeOrderUnit> unitMap, BigDecimal unitPrice) {
        if (Objects.equals(kwoTradeOrder.getStatus(), TradeOrderStatusEnum.SUCCESS.getCode())) {
            //贸易订单已完结，计算预付余额
            if (Objects.equals(kwoTradeOrder.getSettlement(), 1)) {
                //todo 普通结算

            } else if (Objects.equals(kwoTradeOrder.getSettlement(), 2)) {
                //预付制模式
                //1解冻运费
                if (unitMap.keySet().size() < 2) {
                    throw new BusinessException("贸易订单企业信息缺失");
                }
                //钱包退回金额
                WalletPrepaidDto unFreezePrepaidDto = new WalletPrepaidDto();
                unFreezePrepaidDto.setOrderNo(kwoTradeOrder.getTOrderNo());
                unFreezePrepaidDto.setProEntId(unitMap.get(String.valueOf(1)).getEntId());
                unFreezePrepaidDto.setSupEntId(unitMap.get(String.valueOf(2)).getEntId());
                unFreezePrepaidDto.setOrderType(4);
                unFreezePrepaidDto.setTradeType(5);
                unFreezePrepaidDto.setRemark("贸易订单：" + unFreezePrepaidDto.getOrderNo() + ",");
                log.info("贸易订单号：{}，订单完结调用钱包服务解冻预付余额，参数：{}", unFreezePrepaidDto.getOrderNo(), JSON.toJSONString(unFreezePrepaidDto));
                BaseResult<Object> unFreezeResult = new BaseResult<>();
                try {
                    unFreezeResult = paymentFeignService.updatePrepaidBalance(unFreezePrepaidDto);
                } catch (Exception e) {
                    log.error("订单完结调用钱包服务解冻预付余额异常：{}", e.getMessage());
                }
                if (unFreezeResult.getCode() != HttpStatus.SUCCESS_CODE) {
                    log.error("贸易订单号：{}，订单完结解冻失败,异常信息为：{}", unFreezePrepaidDto.getOrderNo(), unFreezeResult.getMessage());
                    throw new BusinessException("贸易订单号：" + unFreezePrepaidDto.getOrderNo() + "，订单完结解冻失败");
                }
                //2计算订单金额
                WalletPrepaidDto consumePrepaidDto = new WalletPrepaidDto();
                consumePrepaidDto.setOrderNo(kwoTradeOrder.getTOrderNo());
                consumePrepaidDto.setProEntId(unitMap.get(String.valueOf(1)).getEntId());
                consumePrepaidDto.setSupEntId(unitMap.get(String.valueOf(2)).getEntId());
                consumePrepaidDto.setOrderType(4);
                consumePrepaidDto.setTradeType(6);
                if (Objects.equals(kwoTradeOrder.getChargeType(), 1)) {
                    consumePrepaidDto.setTradeAmount(NumberUtil.mul(kwoTradeOrder.getLoadAmount(), unitPrice));
                } else {
                    consumePrepaidDto.setTradeAmount(NumberUtil.mul(kwoTradeOrder.getUnloadAmount(), unitPrice));
                }
                consumePrepaidDto.setRemark("贸易订单号：" + consumePrepaidDto.getOrderNo() + "，订单完结消费");
                log.info("贸易订单号：{}，订单完结调用钱包服务消费预付余额，参数：{}", consumePrepaidDto.getOrderNo(), JSON.toJSONString(consumePrepaidDto));
                BaseResult<Object> consumeResult = new BaseResult<>();
                try {
                    consumeResult = paymentFeignService.updatePrepaidBalance(consumePrepaidDto);
                } catch (Exception e) {
                    log.error("订单完结调用钱包服务消费预付余额异常：{}", e.getMessage());
                }
                if (consumeResult.getCode() != HttpStatus.SUCCESS_CODE) {
                    log.error("贸易订单号：{}，订单完结消费失败,异常信息为：{}", consumePrepaidDto.getOrderNo(), consumeResult.getMessage());
                    throw new BusinessException("贸易订单号：" + consumePrepaidDto.getOrderNo() + "，订单完结消费失败");
                }
            }
        }

    }

}
