package com.hzs.sale.postage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hzs.common.core.enums.EChargeType;
import com.hzs.common.core.enums.EPostageDetailType;
import com.hzs.common.core.exception.base.BaseException;
import com.hzs.common.domain.sale.postage.BdPostage;
import com.hzs.common.domain.sale.postage.BdPostageDetail;
import com.hzs.common.domain.sale.postage.BdPostageDetailInfo;
import com.hzs.common.domain.sale.product.BdProduct;
import com.hzs.sale.postage.dto.PostageProductDTO;
import com.hzs.sale.postage.service.IBdPostageDetailInfoService;
import com.hzs.sale.postage.service.IBdPostageDetailService;
import com.hzs.sale.postage.service.IBdPostageService;
import com.hzs.sale.postage.service.IPostageBusinessService;
import com.hzs.sale.product.service.IBdProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 邮费业务服务
 * @Author: jiang chao
 * @Time: 2023/4/25 16:20
 * @Classname: PostageBusinessServiceImpl
 * @PackageName: com.hzs.sale.postage.service.impl
 */
@Service
public class PostageBusinessServiceImpl implements IPostageBusinessService {

    @Autowired
    private IBdPostageService iBdPostageService;
    @Autowired
    private IBdPostageDetailService iBdPostageDetailService;
    @Autowired
    private IBdPostageDetailInfoService iBdPostageDetailInfoService;
    @Autowired
    private IBdProductService iBdProductService;

    @Override
    public BigDecimal queryPostage(Integer pkId, List<PostageProductDTO> productDtoList, Integer province) {
        // 查询邮费模板主表
        BdPostage bdPostage = iBdPostageService.getById(pkId);
        if (null == bdPostage) {
            throw new BaseException("邮费模板不存在");
        }
        // 邮费模板明细
        QueryWrapper<BdPostageDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.eq("PK_POSTAGE", pkId);
        detailQueryWrapper.eq("TYPE", EPostageDetailType.DELIVERY_AREA.getValue());
        detailQueryWrapper.eq("PROVINCE", province);
        BdPostageDetail bdPostageDetail = iBdPostageDetailService.getOne(detailQueryWrapper);
        if (null == bdPostageDetail) {
            throw new BaseException("邮费模板不存在");
        }

        // 邮费计数（重量、体积重、件数）
        BigDecimal postageData;

        // 各计费方式处理
        if (EChargeType.WEIGHT.getValue() == bdPostage.getChargeType()) {
            // 重量
            postageData = this.weightHandle(productDtoList);
        } else if (EChargeType.VOLUME.getValue() == bdPostage.getChargeType()) {
            // 体积重
            postageData = this.volumeWeightHandle(productDtoList, bdPostageDetail);
        } else {
            // 件数
            postageData = new BigDecimal(this.quantityHandle(productDtoList));
        }

        return this.postageHandle(bdPostage, bdPostageDetail, postageData);
    }

    /**
     * 重量处理
     *
     * @param productDtoList
     * @return
     */
    private BigDecimal weightHandle(List<PostageProductDTO> productDtoList) {
        // 产品map（key:产品ID, value:产品数据）
        Map<Integer, BdProduct> productMap = this.getProductMap(productDtoList);

        // 重量
        BigDecimal weight = BigDecimal.ZERO;
        for (PostageProductDTO postageProductDTO : productDtoList) {
            // 产品信息
            BdProduct bdProduct = productMap.get(postageProductDTO.getProductId());
            // 累计重量（邮费重量 * 产品数量）
            weight = weight.add(bdProduct.getPostageWeight().multiply(new BigDecimal(postageProductDTO.getQuantity())));
        }

        return weight;
    }

    /**
     * 体积重处理
     *
     * @param productDtoList
     * @param bdPostageDetail
     * @return
     */
    private BigDecimal volumeWeightHandle(List<PostageProductDTO> productDtoList, BdPostageDetail bdPostageDetail) {
        // 产品map（key:产品ID, value:产品数据）
        Map<Integer, BdProduct> productMap = this.getProductMap(productDtoList);

        BigDecimal volumeWeight = BigDecimal.ZERO;
        // 系数
        BigDecimal volumeRatio = null == bdPostageDetail.getVolumeRatio() ? new BigDecimal("6000") : bdPostageDetail.getVolumeRatio();
        for (PostageProductDTO postageProductDTO : productDtoList) {
            // 产品信息
            BdProduct bdProduct = productMap.get(postageProductDTO.getProductId());
            // 累计体积重（长 * 宽 * 高 / 抛货值 * 产品数量）
            volumeWeight = volumeWeight.add(bdProduct.getLength().multiply(bdProduct.getWidth()).multiply(bdProduct.getHeight()).divide(volumeRatio, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(postageProductDTO.getQuantity())));
        }
        return volumeWeight;
    }

    /**
     * 件数处理
     *
     * @param productDtoList
     * @return
     */
    private int quantityHandle(List<PostageProductDTO> productDtoList) {
        int quantity = 0;
        for (PostageProductDTO postageProductDTO : productDtoList) {
            // 累计件数
            quantity += postageProductDTO.getQuantity();
        }
        return quantity;
    }

    /**
     * 获取产品map
     *
     * @param productDtoList 查询产品列表
     * @return
     */
    private Map<Integer, BdProduct> getProductMap(List<PostageProductDTO> productDtoList) {
        // 产品ID列表
        List<Integer> productIdList = productDtoList.stream().map(PostageProductDTO::getProductId).collect(Collectors.toList());
        // 产品列表
        List<BdProduct> productList = iBdProductService.listByIds(productIdList);
        // 产品map
        Map<Integer, BdProduct> productMap = new HashMap<>();
        for (BdProduct bdProduct : productList) {
            productMap.put(bdProduct.getPkId(), bdProduct);
        }
        return productMap;
    }

    /**
     * 邮费处理
     *
     * @param bdPostage       邮费
     * @param bdPostageDetail 邮费明细
     * @param postageData     邮费计数（重量、体积重、件数）
     * @return
     */
    private BigDecimal postageHandle(BdPostage bdPostage, BdPostageDetail bdPostageDetail, BigDecimal postageData) {
        // 首次计数
        BigDecimal firstWeight = bdPostageDetail.getFirstWeight();

        if (postageData.compareTo(firstWeight) <= 0) {
            // 邮费计数 小于等于 首次数据，则直接使用首次邮费
            return bdPostageDetail.getFirstPostage();
        } else {
            // 邮费初始 等于 首次费用
            BigDecimal postage = bdPostageDetail.getFirstPostage();
            // 减掉首次计数
            postageData = postageData.subtract(firstWeight);

            // 查询续重列表（升序）
            QueryWrapper<BdPostageDetailInfo> detailInfoQueryWrapper = new QueryWrapper<>();
            detailInfoQueryWrapper.eq("PK_POSTAGE", bdPostage.getPkId());
            detailInfoQueryWrapper.eq("PK_POSTAGE_DETAIL", bdPostageDetail.getPkId());
            detailInfoQueryWrapper.orderByAsc("CONTINUED_WEIGHT");
            List<BdPostageDetailInfo> detailInfoList = iBdPostageDetailInfoService.list(detailInfoQueryWrapper);

            for (BdPostageDetailInfo bdPostageDetailInfo : detailInfoList) {
                // 累加续处理邮费
                postage = postage.add(bdPostageDetailInfo.getContinuedPostage());

                if (postageData.compareTo(bdPostageDetailInfo.getContinuedWeight()) <= 0) {
                    // 邮费计数 小于等于 续处理数据，则继续递减
                    postageData = postageData.subtract(bdPostageDetailInfo.getContinuedWeight());
                }

                if (postageData.compareTo(BigDecimal.ZERO) <= 0) {
                    // 当邮费计数 小于等于 0，则结束
                    break;
                }
            }
            return postage;
        }
    }

}
