package com.hzs.retail.sale.controller.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.domain.sale.ext.BdPostageFailAreaExt;
import com.hzs.common.domain.sale.order.SaOrderItems;
import com.hzs.common.domain.sale.postage.BdPostage;
import com.hzs.common.domain.sale.postage.BdPostageArea;
import com.hzs.common.domain.sale.postage.BdPostageDetail;
import com.hzs.common.domain.sale.product.BdProduct;
import com.hzs.common.domain.system.config.BdAreaFreePostage;
import com.hzs.retail.sale.controller.service.IRetailOrderPostageService;
import com.hzs.retail.sale.param.RetailOrderParam;
import com.hzs.sale.postage.service.IBdPostageAreaService;
import com.hzs.sale.postage.service.IBdPostageDetailService;
import com.hzs.sale.postage.service.IBdPostageFailAreaService;
import com.hzs.sale.postage.service.IBdPostageService;
import com.hzs.sale.product.service.IBdProductService;
import com.hzs.sale.wares.service.IBdWaresSpecialPostageService;
import com.hzs.system.base.ISystemConfigServiceApi;
import com.hzs.system.config.IAreaFreePostageServiceApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 新零售订单邮费处理服务
 * @Author: jiang chao
 * @Time: 2024/12/15 10:22
 * @Classname: RetailOrderPostageServiceImpl
 * @PackageName: com.hzs.retail.sale.controller.service.impl
 */
@Slf4j
@Service
public class RetailOrderPostageServiceImpl implements IRetailOrderPostageService {

    @Autowired
    private IBdPostageService iBdPostageService;
    @Autowired
    private IBdPostageDetailService iBdPostageDetailService;
    @Autowired
    private IBdPostageAreaService iBdPostageAreaService;
    @Autowired
    private IBdPostageFailAreaService iBdPostageFailAreaService;
    @Autowired
    private IBdWaresSpecialPostageService iBdWaresSpecialPostageService;
    @Autowired
    private IBdProductService iBdProductService;

    @DubboReference
    ISystemConfigServiceApi iSystemConfigServiceApi;
    @DubboReference
    IAreaFreePostageServiceApi iAreaFreePostageServiceApi;


    @Override
    public String calculatePostage(BigDecimal freePostage, Map<Integer, List<SaOrderItems>> postageMap, RetailOrderParam orderParam) {
        // 处理邮费
        if (ESpecialArea.RETAIL_REGISTER.getValue() == orderParam.getSpecialArea()
                || ESpecialArea.RETAIL_UPGRADE.getValue() == orderParam.getSpecialArea()) {
            // 会员专区（注册、升级）免邮费
            orderParam.setPostage(BigDecimal.ZERO);
        } else {
            // 其它专区计算邮费
            // 获取邮费配置
            String postageConfig = iSystemConfigServiceApi.getBonusSystemConfig(orderParam.getPkCountry(), ESystemConfig.POSTAGE_CONFIG.getKey()).getData();
            if (null == postageConfig) {
                log.error("邮费模板缓存为空，按取最大值处理");
                // 缓存值为空，按取最大值进行处理
                postageConfig = EPostageConfig.MAXIMUM.getValue();
            }

            // 特殊邮费模板
            List<Integer> specialPostageList = iBdWaresSpecialPostageService.querySpecialPostagePkWares(orderParam.getPkCountry());

            // 计算邮费
            for (Integer pkPostage : postageMap.keySet()) {
                // 获取专区设置的不能发货区域
                List<BdPostageFailAreaExt> failAreaList = iBdPostageFailAreaService.queryPostageFailAreaList(pkPostage);
                if (CollectionUtil.isNotEmpty(failAreaList)) {
                    for (BdPostageFailAreaExt postageFailArea : failAreaList) {
                        if (orderParam.getRecProvince().equals(postageFailArea.getProvince()) && orderParam.getRecCity().equals(postageFailArea.getCity())) {
                            // 指定省、市不配置
                            return postageFailArea.getProvinceVal() + postageFailArea.getCityVal() + "," + (StringUtils.isNotEmpty(postageFailArea.getWarnNotice()) ? postageFailArea.getWarnNotice() : "目前不能发货");
                        } else if (orderParam.getRecProvince().equals(postageFailArea.getProvince()) && null == postageFailArea.getCity()) {
                            // 指定省不配置
                            return postageFailArea.getProvinceVal() + "," + (StringUtils.isNotEmpty(postageFailArea.getWarnNotice()) ? postageFailArea.getWarnNotice() : "目前不能发货");
                        }
                    }
                }

                // 获取邮费模板主表
                BdPostage postage = iBdPostageService.getPostage(pkPostage);
                List<BdPostageDetail> postageDetailList = iBdPostageDetailService.getPostageDetail(orderParam.getTranType(), pkPostage);
                BdPostageDetail postageDetail = null;
                // 验证省、市
                for (BdPostageDetail bdPostageDetail : postageDetailList) {
                    // 验证省
                    if (orderParam.getRecProvince().equals(bdPostageDetail.getProvince())) {
                        if (orderParam.getRecCity().equals(bdPostageDetail.getCity()) ||
                                bdPostageDetail.getCity() == null) {
                            postageDetail = bdPostageDetail;
                            break;
                        }
                    }
                }
                if (null == postageDetail) {
                    return "没有找到运费模板，不能下单";
                }

                // 特殊邮费标记
                boolean specialFlag = specialPostageList.contains(pkPostage);

                // 获取专区设置的免邮金额
                List<BdPostageArea> postageAreaList = iBdPostageAreaService.getPostageArea(orderParam.getTranType(), pkPostage, orderParam.getSpecialArea(), orderParam.getPkCountry());
                BigDecimal freeAmount = null;
                if (CollectionUtil.isNotEmpty(postageAreaList)) {
                    BdPostageArea allPostageAres = null;
                    // 验证省、市
                    for (BdPostageArea postageArea : postageAreaList) {
                        // 验证省
                        if (orderParam.getRecProvince().equals(postageArea.getProvince())) {
                            if (orderParam.getRecCity().equals(postageArea.getCity()) ||
                                    postageArea.getCity() == null) {
                                freeAmount = postageArea.getFreeAmount();
                                break;
                            }
                        }
                        if (postageArea.getProvince() == null && postageArea.getCity() == null) {
                            allPostageAres = postageArea;
                        }
                    }
                    if (allPostageAres != null && freeAmount == null) {
                        freeAmount = allPostageAres.getFreeAmount();
                    }
                }

                // 获取系统参数，累计、取最大、取最小
                BigDecimal newPostage = getOrderPostage(postageMap.get(pkPostage), postage, postageDetail, freeAmount, orderParam, specialFlag);

                // 如果邮费为0元，则不进行赋值处理
                if (newPostage.compareTo(BigDecimal.ZERO) > 0) {
                    // 2023.10.27 指定特殊邮费模板不走写死的300包邮逻辑
                    if (specialFlag) {
                        // 特殊邮费模板，不走包邮逻辑
                        if (postageConfig.equals(EPostageConfig.CUMULATIVE.getValue())) {
                            orderParam.setSpecialPostage(orderParam.getSpecialPostage().add(newPostage));
                        } else if (postageConfig.equals(EPostageConfig.MAXIMUM.getValue())) {
                            if (ComputeUtil.compareValue(newPostage, orderParam.getSpecialPostage())) {
                                orderParam.setSpecialPostage(newPostage);
                            }
                        } else {
                            if (ComputeUtil.compareValue(orderParam.getSpecialPostage(), newPostage)) {
                                orderParam.setSpecialPostage(newPostage);
                            }
                        }
                    } else {
                        if (postageConfig.equals(EPostageConfig.CUMULATIVE.getValue())) {
                            orderParam.setPostage(orderParam.getPostage().add(newPostage));
                        } else if (postageConfig.equals(EPostageConfig.MAXIMUM.getValue())) {
                            if (ComputeUtil.compareValue(newPostage, orderParam.getPostage())) {
                                orderParam.setPostage(newPostage);
                            }
                        } else {
                            if (ComputeUtil.compareValue(orderParam.getPostage(), newPostage)) {
                                orderParam.setPostage(newPostage);
                            }
                        }
                    }
                }
            }

            // 计算包邮时，需要把特殊运费金额减掉
            freePostage = freePostage.subtract(orderParam.getSpecialPostageAmount());
            // 专区包邮配置
            BdAreaFreePostage bdAreaFreePostage = iAreaFreePostageServiceApi.queryAreaFreePostage(orderParam.getSpecialArea(), orderParam.getPkCountry()).getData();
            if (null != bdAreaFreePostage && null != bdAreaFreePostage.getFreeAmount()) {
                // 存在专区包邮配置 并且 包邮金额大于专区包邮金额，则进行包邮
                if (freePostage.compareTo(bdAreaFreePostage.getFreeAmount()) >= 0) {
                    orderParam.setPostage(BigDecimal.ZERO);
                }
            }
            // 最终邮费取值
            if (postageConfig.equals(EPostageConfig.CUMULATIVE.getValue())) {
                // 累计值
                orderParam.setPostage(orderParam.getPostage().add(orderParam.getSpecialPostage()));
            } else if (postageConfig.equals(EPostageConfig.MAXIMUM.getValue())) {
                // 最大值
                if (ComputeUtil.compareValue(orderParam.getSpecialPostage(), orderParam.getPostage())) {
                    orderParam.setPostage(orderParam.getSpecialPostage());
                }
            } else {
                // 最小值
                if (ComputeUtil.compareValue(orderParam.getSpecialPostage(), orderParam.getPostage())
                        && orderParam.getPostage().compareTo(BigDecimal.ZERO) == 0) {
                    // 特殊邮费大于邮费，并且邮费为0时，取特殊邮费
                    orderParam.setPostage(orderParam.getSpecialPostage());
                }
            }
        }
        return null;
    }


    /**
     * 获取订单邮费
     *
     * @param postageOrderItemsList 订单明细表，计算产品
     * @param postage               邮费模板
     * @param postageDetail         邮费模板明细
     * @param freeAmount            免邮金额
     * @param orderParam            邮费参数
     * @param specialFlag           是否特殊邮费处理
     * @return
     */
    private BigDecimal getOrderPostage(List<SaOrderItems> postageOrderItemsList, BdPostage postage,
                                       BdPostageDetail postageDetail, BigDecimal freeAmount, RetailOrderParam orderParam,
                                       boolean specialFlag) {
        // 计算邮费 判断价格
        // 获取重量 获取体积 获取价格
        BigDecimal amount = BigDecimal.ZERO;
        BigDecimal weight = BigDecimal.ZERO;
        BigDecimal volume = BigDecimal.ZERO;
        // 产品数量
        int number = 0;
        // 商品数量记录map
        Map<Integer, Integer> waresNumberMap = new HashMap<>();

        // 计算商品价格
        for (SaOrderItems saOrderItems : postageOrderItemsList) {
            // 根据产品获得产品
            BdProduct product = iBdProductService.getProduct(saOrderItems.getPkProduct());
            amount = amount.add(saOrderItems.getPrice().multiply(BigDecimal.valueOf(saOrderItems.getQuantity())));
            weight = weight.add(product.getPostageWeight().multiply(BigDecimal.valueOf(saOrderItems.getQuantity())));

            // 按产品计数量
            number += saOrderItems.getQuantity();

            // 每个商品ID只记录一次商品数量
            waresNumberMap.computeIfAbsent(saOrderItems.getPkWares(), k -> saOrderItems.getWaresQuantity());
        }

        // 按商品数量收取邮费
        if (null != postage.getQuantityMode() && EPostageMode.WARES.getValue() == postage.getQuantityMode()) {
            int waresNumber = 0;
            for (Integer key : waresNumberMap.keySet()) {
                waresNumber += waresNumberMap.get(key);
            }
            number = waresNumber;
        }

        if (specialFlag) {
            // 特殊邮费金额累加
            orderParam.setSpecialPostageAmount(orderParam.getSpecialPostageAmount().add(amount));
        }

        // 获取免邮金额 判断免邮金额 金额大于免邮金额，免邮
        if (freeAmount != null && ComputeUtil.compareValue(amount, freeAmount)) {
            return BigDecimal.ZERO;
        }
        // 按重量
        if (EChargeType.WEIGHT.getValue() == postage.getChargeType()) {
            return computePostage(postageDetail, weight);
        } else if (EChargeType.VOLUME.getValue() == postage.getChargeType()) {
            // 按体积
            volume = ComputeUtil.mathCeil(volume);
            BigDecimal weightPostage = computePostage(postageDetail, weight);
            BigDecimal volumePostage = computePostage(postageDetail, volume);
            if (weightPostage.compareTo(volumePostage) >= 0) {
                return weightPostage;
            } else {
                return volumePostage;
            }
        } else {
            // 按件数
            return computePostagePieces(postageDetail, number);
        }
    }


    /**
     * 计算邮费
     * 1) 重量计费
     * 首重重量 >= 实际重量 邮费 = 首重邮费
     * 反之 ：邮费 = 首重邮费 + ((实际重量 - 首重重量) / 续重重量) * 续重邮费
     * 2) 体积计费
     * 实际重量 = 长 * 宽 * 高 / 6000  利用重量计费公式计算实际邮费
     * 判断重量计费跟体积计费哪个大使用哪个计费方法
     *
     * @param postageDetail 邮费模板
     * @param weight        重量
     * @return
     */
    private BigDecimal computePostage(BdPostageDetail postageDetail, BigDecimal weight) {
        BigDecimal postage = postageDetail.getFirstPostage();
        if (weight.compareTo(postageDetail.getFirstWeight()) > 0) {
            postage = ComputeUtil.computeDivideRoundUp(weight.subtract(postageDetail.getFirstWeight()), postageDetail.getContinuedWeight())
                    .multiply(postageDetail.getContinuedPostage())
                    .add(postage);
        }
        return postage;
    }

    /**
     * 按件数处理邮费
     *
     * @param postageDetail 邮费模板
     * @param number        数量
     * @return
     */
    private BigDecimal computePostagePieces(BdPostageDetail postageDetail, int number) {
        // 首件邮费
        BigDecimal postage = postageDetail.getFirstPostage();
        if (number > postageDetail.getFirstWeight().intValue()) {
            // 如果数量大于首件，则需要处理续重
            postage = postage.add(postageDetail.getContinuedPostage().multiply(new BigDecimal(number - postageDetail.getFirstWeight().intValue())));
        }
        return postage;
    }

}
