package com.ruoyi.logistics.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetActualFeeInfoV1.CommonActualFeeInfoDetailResponse;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetActualFeeInfoV1.CommonActualFeeResponse;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderByMonthSettleQRV1.CommonMonthSettleQRQueryResponse;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderByMonthSettleQRV1.WaybillQRVerifyInfo;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderInfoV1.addedProducts;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisIdGenerator;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.logistics.constant.RedisCacheConstants;
import com.ruoyi.logistics.domain.BizFinancialFeeItems;
import com.ruoyi.logistics.domain.BizMonthQrcodeRecord;
import com.ruoyi.logistics.domain.BizWaybillCostDetails;
import com.ruoyi.logistics.domain.BizWaybillOrder;
import com.ruoyi.logistics.dto.MonthQRCodeDTO;
import com.ruoyi.logistics.mapper.BizMonthQrcodeRecordMapper;
import com.ruoyi.logistics.mapper.BizWaybillCostDetailsMapper;
import com.ruoyi.logistics.mapper.BizWaybillOrderMapper;
import com.ruoyi.logistics.response.CommonOrderInfoResponse;
import com.ruoyi.logistics.service.FeeItemsCacheService;
import com.ruoyi.logistics.service.IMonthQRCodeTaskService;
import com.ruoyi.logistics.service.LogisticsOrderService;
import com.ruoyi.system.api.domain.SysDept;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MonthQRCodeTaskServiceImpl implements IMonthQRCodeTaskService {

    @Autowired
    private RedisService redisService;

    @Autowired
    private LogisticsOrderService logisticsOrderService;

    @Autowired
    private FeeItemsCacheService feeItemsCacheService;

    @Autowired
    private BizWaybillOrderMapper bizWaybillOrderMapper;

    @Autowired
    private BizWaybillCostDetailsMapper bizWaybillCostDetailsMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private RedisIdGenerator redisIdGenerator;

    @Autowired
    private BizMonthQrcodeRecordMapper bizMonthQrcodeRecordMapper;

    @Autowired
    private ISysConfigService sysConfigService;

    @Override
    public void consumeQRCode() {
        Collection<String> keys = redisService.keys(RedisCacheConstants.MONTH_QRCODE_CACHE_KEY + "*");
        if (keys == null || keys.size() == 0) {
            return;
        }

        for (String key : keys) {
            MonthQRCodeDTO monthQRCodeDTO = redisService.getCacheObject(key);

            // 判断二维码是否在5分钟内生成的，如果是则给第三方处理数据缓冲时间，避免数据处理
            if (DateUtils.differentMinutes(monthQRCodeDTO.getCreateTime(), DateUtils.getNowDate()) < 5) {
                continue;
            }

            SysUser sysUser = sysUserMapper.selectUserById(monthQRCodeDTO.getUserId());
            SysDept sysDept = sysDeptMapper.selectDeptById(monthQRCodeDTO.getDeptId());

            if (1 == monthQRCodeDTO.getSource()) {
                this.jdQRCodeConsume(monthQRCodeDTO, sysUser, sysDept, key);
            }
        }
    }

    private void jdQRCodeConsume(MonthQRCodeDTO monthQRCodeDTO, SysUser sysUser, SysDept sysDept, String key) {
        JSONObject waybillCode = logisticsOrderService.queryOrderByQRCode(1, monthQRCodeDTO.getQrCodeContent(), monthQRCodeDTO.getType());
        if(!waybillCode.getBooleanValue("success")){
            log.info("根据二维码查询运单号失败{}", waybillCode.getString("msg"));
            return;
        }

        CommonMonthSettleQRQueryResponse response = waybillCode.getObject("msg", CommonMonthSettleQRQueryResponse.class);

        if (response.getWaybillQRVerifyInfoList() != null && response.getWaybillQRVerifyInfoList().size() > 0) {

            for (WaybillQRVerifyInfo waybillQRVerifyInfo : response.getWaybillQRVerifyInfoList()) {
                if (CollectionUtils.isEmpty(monthQRCodeDTO.getProcessWaybillCodes())) {
                    monthQRCodeDTO.setProcessWaybillCodes(new ArrayList<>());
                }
                // 判断订单是否已经处理过
                if (monthQRCodeDTO.getProcessWaybillCodes().contains(waybillQRVerifyInfo.getWaybillCode())) {
                    continue;
                }
                monthQRCodeDTO.getProcessWaybillCodes().add(waybillQRVerifyInfo.getWaybillCode());

                JSONObject orderDetail = logisticsOrderService.queryOrderDetailByWaybillCode(1, waybillQRVerifyInfo.getWaybillCode());
                if(!waybillCode.getBooleanValue("success")){
                    log.info("根据运单号查询运单详情失败{}", waybillCode.getString("msg"));
                    continue;
                }
                JSONObject orderFeeInfo = logisticsOrderService.queryOrderFeeInfoByWaybillCode(1, waybillQRVerifyInfo.getWaybillCode());
                if(!waybillCode.getBooleanValue("success")){
                    log.info("根据运单号查询运单费用失败{}", waybillCode.getString("msg"));
                    continue;
                }

                CommonOrderInfoResponse orderInfo = orderDetail.getObject("msg", CommonOrderInfoResponse.class);
                CommonActualFeeResponse actualFee = orderFeeInfo.getObject("msg", CommonActualFeeResponse.class);

                BizWaybillOrder bizWaybillOrder = new BizWaybillOrder();
                bizWaybillOrder.setWaybillNo(redisIdGenerator.generateUniqueId("RJSD"));
                bizWaybillOrder.setExternalWaybillNo(orderInfo.getWaybillCode());
                bizWaybillOrder.setOrderType(1);
//                    bizWaybillOrder.setSenderName(orderInfo.gets());
//                    bizWaybillOrder.setSenderPhone(orderInfo.getSenderPhone());
                bizWaybillOrder.setSenderProvince(orderInfo.getSenderContact().getProvince());
                bizWaybillOrder.setSenderCity(orderInfo.getSenderContact().getCity());
                bizWaybillOrder.setSenderCounty(orderInfo.getSenderContact().getCounty());
                bizWaybillOrder.setSenderAddress(orderInfo.getSenderContact().getTown());
                bizWaybillOrder.setReceiverName(sysUser.getNickName());
                bizWaybillOrder.setReceiverPhone(sysUser.getPhonenumber());
                bizWaybillOrder.setReceiverProvince(orderInfo.getReceiverContact().getProvince());
                bizWaybillOrder.setReceiverCity(orderInfo.getReceiverContact().getCity());
                bizWaybillOrder.setReceiverCounty(orderInfo.getReceiverContact().getCounty());
                bizWaybillOrder.setReceiverAddress(orderInfo.getReceiverContact().getTown());
                bizWaybillOrder.setGoodsName(orderInfo.getCargoes().get(0).getName());
                bizWaybillOrder.setGoodsWeight(new BigDecimal(orderInfo.getCargoes().get(0).getWeight()));
                bizWaybillOrder.setGoodsVolume(new BigDecimal(orderInfo.getCargoes().get(0).getVolume()));
                bizWaybillOrder.setGoodsQty(orderInfo.getCargoes().get(0).getQuantity().longValue());
                bizWaybillOrder.setOrderStatus(6);
                bizWaybillOrder.setPickupType(orderInfo.getShipmentInfo().getPickupType());
                if (orderInfo.getShipmentInfo() != null) {
                    bizWaybillOrder.setSendStartTime(new Date(Long.parseLong(orderInfo.getShipmentInfo().getPickupStartTime())));
                    bizWaybillOrder.setSendEndTime(new Date(Long.parseLong(orderInfo.getShipmentInfo().getPickupEndTime())));
                }
//                    bizWaybillOrder.setPickupTime(new Date(orderInfo.getShipmentInfo().geta()));
//                    bizWaybillOrder.setDeliveryTime(waybillQRVerifyInfo.getDeliveryTime());
//                    bizWaybillOrder.setSignTime(waybillQRVerifyInfo.getSignTime());
                bizWaybillOrder.setProductCode(orderInfo.getProducts().getProductCode());
                bizWaybillOrder.setAddedService(assembleJDAddedService(orderInfo.getProducts().getAddedProducts()));
                bizWaybillOrder.setCreateTime(DateUtils.getNowDate());
                bizWaybillOrder.setUserId(monthQRCodeDTO.getUserId());
                bizWaybillOrder.setDeptId(monthQRCodeDTO.getDeptId());

                bizWaybillOrderMapper.insertBizWaybillOrder(bizWaybillOrder);

                List<BizWaybillCostDetails> details = assembleJDCostDetails(sysDept, bizWaybillOrder, actualFee.getCommonActualFeeInfoDetails());

                details.forEach(detail -> {
                    bizWaybillCostDetailsMapper.insertBizWaybillCostDetails(detail);
                });
            }

            // 记录二维码处理次数
            monthQRCodeDTO.setProcessNum(monthQRCodeDTO.getProcessNum() + 1);
            redisService.setCacheObject(key, monthQRCodeDTO);

            // 二维码处理次数大于等于5次，且已处理订单等于二维码包含订单数，则修改二维码状态为已处理
            if (monthQRCodeDTO.getProcessNum() >= 5 && monthQRCodeDTO.getProcessWaybillCodes().size() == response.getWaybillQRVerifyInfoList().size()) {
                BizMonthQrcodeRecord record = new BizMonthQrcodeRecord();
                record.setQrcodeId(monthQRCodeDTO.getQrcodeId());
                record.setIsVerify(1);
                record.setUpdateTime(DateUtils.getNowDate());
                bizMonthQrcodeRecordMapper.updateBizMonthQrcodeRecord(record);

                redisService.deleteObject(key);
            }
        }
    }

    private List<BizWaybillCostDetails> assembleJDCostDetails(SysDept sysDept, BizWaybillOrder bizWaybillOrder, List<CommonActualFeeInfoDetailResponse> commonActualFeeInfoDetails) {
        List<BizWaybillCostDetails> details = new ArrayList<>();

        String rate = sysConfigService.selectConfigByKey(bizWaybillOrder.getProductCode());

        commonActualFeeInfoDetails.forEach(item -> {
            BizWaybillCostDetails costDetail = new BizWaybillCostDetails();
            costDetail.setWaybillId(bizWaybillOrder.getWaybillId());
            costDetail.setExternalWaybillNo(bizWaybillOrder.getExternalWaybillNo());

            // 匹配费用类型项
            BizFinancialFeeItems feeItemByExtFeeCode = feeItemsCacheService.getFeeItemByExtFeeCode(item.getFeeType());
            if (feeItemByExtFeeCode != null) {
                costDetail.setFeeItemCode(feeItemByExtFeeCode.getFeeItemCode());
                costDetail.setFeeItemName(feeItemByExtFeeCode.getFeeItemName());
                costDetail.setFeeName(item.getFeeTypeName());
                costDetail.setAmount(item.getMoney());
                if (StringUtils.isNotBlank(rate) && "快递运费".equals(feeItemByExtFeeCode.getFeeItemName())) {
                    BigDecimal subtract = new BigDecimal("1").subtract(new BigDecimal(rate).divide(new BigDecimal("100")));
                    costDetail.setPurchaseAmount(subtract.multiply(item.getMoney()).setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                if (!feeItemByExtFeeCode.getFeeItemName().equals("快递运费")) {
                    costDetail.setRateAmount(item.getMoney());
                    costDetail.setPurchaseAmount(item.getMoney());
                }
                costDetail.setDeptId(bizWaybillOrder.getDeptId());
                costDetail.setUserId(bizWaybillOrder.getUserId());
            }

            details.add(costDetail);
        });
        return details;
    }

    private String assembleJDAddedService(List<addedProducts> addedProducts) {
        JSONObject addedService = new JSONObject();

        addedService.put("isPack", null);
        addedService.put("isGuaranteeMoney", null);
        addedService.put("isReceiptCollect", null);

        List<String> collect = addedProducts.stream().map(com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderInfoV1.addedProducts::getProductCode).collect(Collectors.toList());

        collect.forEach(item -> {
            switch (item) {
                case "ed-a-0011":
                case "fr-a-0005":
                    addedService.put("isPack", true);
                    break;
                case "ed-a-0002":
                case "fr-a-0002":
                    addedService.put("isGuaranteeMoney", true);
                    break;
                case "ed-a-0010":
                case "fr-a-0007":
                    addedService.put("isReceiptCollect", true);
            }
        });
        return addedService.toJSONString();
    }
}
