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

import cn.hutool.core.collection.CollectionUtil;
import com.hzs.activity.base.service.IActivityService;
import com.hzs.common.core.constant.*;
import com.hzs.common.core.constant.msg.MemberMsgConstants;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.exception.ServiceException;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.CommonUtil;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.common.domain.member.ext.CuMemberAccountExt;
import com.hzs.common.domain.member.ext.CuMemberTeamExt;
import com.hzs.common.domain.sale.ext.BdPostageFailAreaExt;
import com.hzs.common.domain.sale.ext.BdWaresDetailExt;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.order.SaOrder;
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.sale.wares.BdWaresRange;
import com.hzs.common.domain.system.base.BdStorehouse;
import com.hzs.common.domain.system.config.BdAreaFreePostage;
import com.hzs.common.domain.system.config.BdAwards;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.common.util.TransactionUtils;
import com.hzs.member.base.IMemberTeamServiceApi;
import com.hzs.sale.order.param.OrderParam;
import com.hzs.sale.order.vo.SaOrderVO;
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.IBdWaresDetailService;
import com.hzs.sale.wares.service.IBdWaresRangeService;
import com.hzs.sale.wares.service.IBdWaresSpecialPostageService;
import com.hzs.system.base.ICurrencyServiceApi;
import com.hzs.system.base.ISystemConfigServiceApi;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.config.IAreaFreePostageServiceApi;
import com.hzs.system.config.IAwardsServiceApi;
import com.hzs.system.config.IGradeServiceApi;
import com.hzs.system.config.dto.AreaCurrencyDTO;
import com.hzs.system.config.dto.GradeDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 用于处理订单的处理逻辑
 */
@Component
@Slf4j
public class SaOrderHandle {

    @DubboReference
    IGradeServiceApi gradeServiceApi;
    @DubboReference
    ICurrencyServiceApi currencyServiceApi;
    @DubboReference
    IMemberTeamServiceApi memberTeamServiceApi;
    @DubboReference
    IAwardsServiceApi awardsServiceApi;
    @DubboReference
    ISystemConfigServiceApi systemConfigServiceApi;
    @DubboReference
    IAreaFreePostageServiceApi iAreaFreePostageServiceApi;

    @Autowired
    private IActivityService activityGiftService;

    private IBdWaresDetailService bdWaresDetailService;

    private IBdPostageService postageService;

    private IBdPostageDetailService postageDetailService;

    private IBdPostageAreaService postageAreaService;

    private IBdPostageFailAreaService bdPostageFailAreaService;

    private IBdProductService bdProductService;

    private IBdWaresRangeService bdWaresRangeService;

    private RedisService redisService;

    private IBdWaresSpecialPostageService bdWaresSpecialPostageService;

    @Autowired
    public void setPostageAreaService(IBdPostageAreaService postageAreaService) {
        this.postageAreaService = postageAreaService;
    }

    @Autowired
    public void setBdPostageFailAreaService(IBdPostageFailAreaService bdPostageFailAreaService) {
        this.bdPostageFailAreaService = bdPostageFailAreaService;
    }

    @Autowired
    public void setPostageService(IBdPostageService postageService) {
        this.postageService = postageService;
    }

    @Autowired
    public void setRedisService(RedisService redisService) {
        this.redisService = redisService;
    }

    @Autowired
    public void setBdWaresRangeService(IBdWaresRangeService bdWaresRangeService) {
        this.bdWaresRangeService = bdWaresRangeService;
    }

    @Autowired
    public void setBdProductService(IBdProductService bdProductService) {
        this.bdProductService = bdProductService;
    }

    @Autowired
    public void setPostageDetailService(IBdPostageDetailService postageDetailService) {
        this.postageDetailService = postageDetailService;
    }

    @Autowired
    public void setBdWaresDetailService(IBdWaresDetailService bdWaresDetailService) {
        this.bdWaresDetailService = bdWaresDetailService;
    }

    @Autowired
    public void setBdWaresSpecialPostageService(IBdWaresSpecialPostageService bdWaresSpecialPostageService) {
        this.bdWaresSpecialPostageService = bdWaresSpecialPostageService;
    }

    /**
     * @param orderParam   需要保存的会员基本信息
     * @param centerMember 报单中心会员编号
     *                     生成用户
     */
    CuMember packageSaveUser(OrderParam orderParam, CuMember centerMember) {
        // 获取新的订单编号
        CuMember cuMember = CuMember.builder()
                .memberCode(orderParam.getMemberCode())
                .memberName(orderParam.getMemberName())
                .pkSettleCountry(orderParam.getPkSettleCountry())
                .phone(orderParam.getPhone())
                .idCard(orderParam.getIdCard())
                .email(orderParam.getEmail())
                .loginPwd(SecurityUtils.encryptPassword(SysConstants.LOGIN_PASSWORD))
                .loginPassword(SysConstants.LOGIN_PASSWORD)
                .payPwd(SecurityUtils.encryptPassword(SysConstants.PAY_PASSWORD))
                .payPassword(SysConstants.PAY_PASSWORD)
                .source(orderParam.getSource() == null ? EDataSource.PC.getValue() : orderParam.getSource())
                .pkParent(orderParam.getParentId())
                .accountStatus(EAccountStatus.NORMAL.getValue())
                .pkCenterCode(orderParam.getCenterCodeId())
                // 这个时候是待支付，等支付的时候变为支付，可以跟待支付公用
                .payStatus(EPayStatus.UNPAID.getValue())
                .category(ECategory.NORMAL.getValue())
                .orderSource(EOrderSource.SOLID.getValue())
                .consumeMoney(BigDecimal.ZERO)
                .consumeAchieve(BigDecimal.ZERO)
                .registerAuthority(ERegistrationAuthority.ORDINARY.getValue())
                .build();
        // 海粉没有安置人安置位置
        if (orderParam.getIsHaiFun()) {
            cuMember.setCustomerType(ECustomerType.FANS.getValue());
            if (null != orderParam.getPlaceParentId()) {
                cuMember.setPkPlaceParent(orderParam.getPlaceParentId());
            }
            if (null != orderParam.getPlaceDept()) {
                cuMember.setPlaceDept(orderParam.getPlaceDept());
            }
        } else {
            cuMember.setCustomerType(ECustomerType.NORMAL.getValue());
            cuMember.setPkPlaceParent(orderParam.getPlaceParentId());
            cuMember.setPlaceDept(orderParam.getPlaceDept());
        }
        cuMember.setPkCountry(orderParam.getPkCountry());
        cuMember.setCreationTime(DateUtils.currentDateTime());
        cuMember.setPkCreator(centerMember.getPkId());
        if (centerMember.getPkTeamCode() == null) {
            // 验证父级是不是团队
            CuMemberTeamExt memberTeamExt = memberTeamServiceApi.getCuMemberTeamById(centerMember.getPkId()).getData();
            if (memberTeamExt != null) {
                cuMember.setPkTeamCode(memberTeamExt.getPkId());
            }
        } else {
            cuMember.setPkTeamCode(centerMember.getPkTeamCode());
        }
        cuMember.setPkVertex(centerMember.getPkVertex());
        return cuMember;
    }

    /**
     * @param cuMember   会员
     * @param saOrder    订单主表
     * @param orderParam 订单商品信息
     */
    void packSaOrderItems(CuMember cuMember, SaOrderExt saOrder, OrderParam orderParam) {
        orderParam.setPostage(BigDecimal.ZERO);
        List<SaOrderItems> saOrderItemsList;
        try {
            saOrderItemsList = getSaOrderItems(cuMember, saOrder, orderParam);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        saOrder.setPostage(orderParam.getPostage());
        saOrder.setOrderItemsList(saOrderItemsList);
    }

    /**
     * @param cuMember   会员
     * @param orderParam 参数
     *                   查询邮费
     */
    List<SaOrderItems> queryPostage(CuMember cuMember, OrderParam orderParam) {
        return getSaOrderItems(cuMember, null, orderParam);
    }

    /**
     * @param cuMember   会员
     * @param saOrder    主表
     * @param orderParam 参数
     *                   计算邮费
     */
    private List<SaOrderItems> getSaOrderItems(CuMember cuMember, SaOrderExt saOrder, OrderParam orderParam) {
        // 当前国家
        Integer pkCountry = orderParam.getPkSettleCountry();

        // 获取汇率
        CurrencyDTO currency = currencyServiceApi.getCurrency(pkCountry).getData();
        // 商品编号 + sku主键 + 数量
        List<BdWaresDetailExt> bdWaresDetailExtList = getWaresDetailExtList(orderParam, cuMember);
        if (CollectionUtil.isEmpty(bdWaresDetailExtList)) {
            throw new RuntimeException("没有找到商品，请刷新重试！");
        }

        // 包邮邮费合计
        BigDecimal resultPostage = BigDecimal.ZERO;
        // 特殊邮费模板 -- 2023.10.27 指定特殊邮费模板不走写死的300包邮逻辑
        List<Integer> specialPostageList = bdWaresSpecialPostageService.querySpecialPostagePkWares(pkCountry);

        List<SaOrderItems> saOrderItemsList = new ArrayList<>();
        // 邮费map
        // 处理邮费 根据专区获得邮费模板 邮费 先进行分类，把邮费模板一样的放在一起
        Map<Integer, List<SaOrderItems>> postageMap = new HashMap<>(ComputeUtil.mapInitCapacity(bdWaresDetailExtList.size()));

        // 等级
        R<List<GradeDTO>> gradeDTO = gradeServiceApi.queryGradeList(pkCountry);
        List<GradeDTO> gradeList = gradeDTO.getData();
        Map<Integer, GradeDTO> gradeMap = gradeList.stream().collect(Collectors.toMap(GradeDTO::getGradeValue, Function.identity()));

        for (BdWaresDetailExt waresDetailExt : bdWaresDetailExtList) {
            SaOrderItems saOrderItems = getSaOrderItems(cuMember, saOrder, currency, saOrderItemsList, waresDetailExt);
            // 特殊会员产品处理
            if (null != saOrder
                    && EOrderType.SPECIAL_REPURCHASE_ORDER.getValue() == saOrder.getOrderType()
                    && EYesNo.NO.getIntValue() == saOrderItems.getIsGift()) {

                // 乐学复购，价格根据等级固定
                if (cuMember.getPkSettleGrade().equals(gradeMap.get(EGrade.S_VIP.getValue()).getPkId())) {
                    saOrderItems.setPrice(MagicNumberConstants.LXYK_V4);
                } else if (cuMember.getPkSettleGrade().equals(gradeMap.get(EGrade.VIP.getValue()).getPkId())) {
                    saOrderItems.setPrice(MagicNumberConstants.LXYK_V3);
                } else if (cuMember.getPkSettleGrade().equals(gradeMap.get(EGrade.MAKER.getValue()).getPkId())) {
                    saOrderItems.setPrice(MagicNumberConstants.LXYK_V2);
                } else {
                    saOrderItems.setPrice(MagicNumberConstants.LXYK_V1);
                }
                // TODO new 乐学复购商品业绩为600
                saOrderItems.setAchievement(MagicNumberConstants.LXYK_PV);
            }

            // 免邮的话不需要计算邮费
            if (EYesNo.YES.getIntValue() == waresDetailExt.getIsFreeMail()) {
                continue;
            }
            if (EDelivery.FAST_MAIL.getValue() == orderParam.getDeliveryWay()) {
                setPostageTmpMap(orderParam, postageMap, waresDetailExt, saOrderItems);
            }
            // 累积产品价格（计算包邮使用）
            resultPostage = resultPostage.add(saOrderItems.getPrice().multiply(new BigDecimal(saOrderItems.getQuantity())));
        }

        if (EDelivery.FAST_MAIL.getValue() == orderParam.getDeliveryWay()) {
            // 获取邮费配置
            String postageConfig = systemConfigServiceApi.getBonusSystemConfig(pkCountry, ESystemConfig.POSTAGE_CONFIG.getKey()).getData();
            if (null == postageConfig) {
                log.error("邮费模板缓存为空，按取最大值处理");
                // 缓存值为空，按取最大值进行处理
                postageConfig = EPostageConfig.MAXIMUM.getValue();
            }

            String tmpPostageConfig = postageConfig;
            // 开始计算邮费
            postageMap.forEach((pkPostage, postageOrderItemsList) -> {
                calculatePostageByPkId(orderParam, tmpPostageConfig, pkPostage, postageOrderItemsList, pkCountry, specialPostageList);
            });

            // 计算包邮时，需要把特殊运费金额减掉
            resultPostage = resultPostage.subtract(orderParam.getSpecialPostageAmount());

            // 专区包邮配置
            BdAreaFreePostage bdAreaFreePostage = iAreaFreePostageServiceApi.queryAreaFreePostage(orderParam.getSpecialArea(), pkCountry).getData();
            if (null != bdAreaFreePostage && null != bdAreaFreePostage.getFreeAmount()) {
                // 存在包邮配置，获取包邮金额
                BigDecimal freeAmount = bdAreaFreePostage.getFreeAmount();

                // 大于包邮金额，则进行包邮
                if (resultPostage.compareTo(freeAmount) >= 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())) {
                    if (orderParam.getPostage().compareTo(BigDecimal.ZERO) == 0) {
                        // 最小值如果等于0，则还是取大值
                        orderParam.setSpecialPostage(orderParam.getSpecialPostage());
                    }
                }
            }
        }
        return saOrderItemsList;
    }

    private void calculatePostageByPkId(OrderParam orderParam, String postageConfig, Integer pkPostage,
                                        List<SaOrderItems> postageOrderItemsList, Integer pkCountry,
                                        List<Integer> specialPostageList) {
        // 获取专区设置的不能发货区域
        List<BdPostageFailAreaExt> failAreaList = bdPostageFailAreaService.queryPostageFailAreaList(pkPostage);
        if (CollectionUtil.isNotEmpty(failAreaList)) {
            for (BdPostageFailAreaExt postageFailArea : failAreaList) {
                if (orderParam.getRecProvince().equals(postageFailArea.getProvince()) && orderParam.getRecCity().equals(postageFailArea.getCity())) {
                    // 指定省、市不配置
                    throw new ServiceException(postageFailArea.getProvinceVal() + postageFailArea.getCityVal() + "," + (StringUtils.isNotEmpty(postageFailArea.getWarnNotice()) ? postageFailArea.getWarnNotice() : "目前不能发货"));
                } else if (orderParam.getRecProvince().equals(postageFailArea.getProvince()) && null == postageFailArea.getCity()) {
                    // 指定省不配置
                    throw new ServiceException(postageFailArea.getProvinceVal() + "," + (StringUtils.isNotEmpty(postageFailArea.getWarnNotice()) ? postageFailArea.getWarnNotice() : "目前不能发货"));
                }
            }
        }

        // 获取邮费模板主表
        BdPostage postage = postageService.getPostage(pkPostage);
        List<BdPostageDetail> postageDetailList = postageDetailService.getPostageDetail(orderParam.getTransType(), 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 (postageDetail == null) {
            throw new RuntimeException("没有找到运费模板，不能下单");
        }

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

        // 获取专区设置的免邮金额
        List<BdPostageArea> postageAreaList = postageAreaService.getPostageArea(orderParam.getTransType(), pkPostage, orderParam.getSpecialArea(), pkCountry);
        BigDecimal freeAmount = null;
        if (CollectionUtil.isNotEmpty(postageAreaList)) {
            BdPostageArea allPostageAres = null;
            // 验证省、市
            for (BdPostageArea postageArea : postageAreaList) {
                // 验证省
                if (orderParam.getRecProvince().equals(postageArea.getProvince())) {
                    // 2023.11.29 临时需求，运费模板特殊地区不免邮
                    if (postage.getTempName().startsWith("御玖饮竹盐模板")) {
                        specialFlag = true;
                        break;
                    }
                    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 = getSaleOrderPostage(postageOrderItemsList, 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);
                    }
                }
            }
        }
    }

    /**
     * 计算订单价值（价格、业绩）
     *
     * @param orderParam 商品列表、专区
     */
    SaOrder computeSaOrderAchieve(OrderParam orderParam) {
        // 商品编号 + sku主键 + 数量
        List<BdWaresDetailExt> bdWaresDetailExtList = getWaresDetailExtList(orderParam, null);
        SaOrder saOrder = SaOrder.builder().orderAmount(BigDecimal.ZERO)
                .orderAchieve(BigDecimal.ZERO).build();
        bdWaresDetailExtList.forEach(waresDetailExt -> {
            Integer num = waresDetailExt.getQuantity() * waresDetailExt.getWaresQuantity();
            BigDecimal amount = ComputeUtil.computeMultiply(waresDetailExt.getPrice(), num);
            BigDecimal achievement = ComputeUtil.computeMultiply(waresDetailExt.getAchieve(), num);
            saOrder.setOrderAmount(saOrder.getOrderAmount().add(amount));
            saOrder.setOrderAchieve(saOrder.getOrderAchieve().add(achievement));
        });
        // 获取订单业绩,根据订单业绩计算用户等级
        return saOrder;
    }

    /**
     * 将购买的商品明细封装为数据库中的商品明细
     *
     * @param orderParam 会员端参数
     * @param cuMember   会员
     */
    private List<BdWaresDetailExt> getWaresDetailExtList(OrderParam orderParam, CuMember cuMember) {
        // 商品编号 + sku列表找到所有的商品信息
        // 查找所有商品
        List<BdWaresDetailExt> bdWaresDetailExtList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(orderParam.getOrderItemsParams())) {
            List<BdWaresDetailExt> waresDetailExtList = bdWaresDetailService.queryWaresDetailByCondition(orderParam.getSpecialArea(), orderParam.getTransType(), orderParam.getOrderItemsParams());
            setWaresRange(orderParam.getSpecialArea(), waresDetailExtList, cuMember);
            if (waresDetailExtList.size() > 0) {
                bdWaresDetailExtList.addAll(waresDetailExtList);
            }
        }
        // 活动赠品 赠送封装
        List<BdWaresDetailExt> newWaresDetailExtList = activityGiftService.generateActivityGiftWaresAchieve(orderParam.getSpecialArea(), orderParam.getPkSettleCountry(), bdWaresDetailExtList,
                orderParam.getParent(), cuMember);
        if (newWaresDetailExtList.size() > 0) {
            bdWaresDetailExtList.addAll(newWaresDetailExtList);
        }
        return bdWaresDetailExtList;
    }

    /**
     * 设置商品的极差
     *
     * @param specialArea          所属专区
     * @param cuMember             会员
     * @param bdWaresDetailExtList 商品明细
     */
    private void setWaresRange(Integer specialArea, List<BdWaresDetailExt> bdWaresDetailExtList, CuMember cuMember) {
        // 复购订单商品跟业绩需要单独处理
        if (EOrderType.REPURCHASE_ORDER.getValue() == specialArea || EOrderType.SPECIAL_REPURCHASE_ORDER.getValue() == specialArea) {
            Map<String, List<BdWaresDetailExt>> waresDetailExtMap = new HashMap<>();
            List<Integer> specsSkuList = new ArrayList<>();
            bdWaresDetailExtList.forEach(bdWaresDetailExt -> {
                String key = bdWaresDetailExt.getPkId().toString() + bdWaresDetailExt.getPkWaresSpecsSku();
                if (waresDetailExtMap.containsKey(key)) {
                    waresDetailExtMap.get(key).add(bdWaresDetailExt);
                } else {
                    List<BdWaresDetailExt> waresDetailExtList = new ArrayList<>();
                    waresDetailExtList.add(bdWaresDetailExt);
                    waresDetailExtMap.put(key, waresDetailExtList);
                }
                specsSkuList.add(bdWaresDetailExt.getPkWaresSpecsSku());
            });
            int level = cuMember.getPkSettleGrade();
            int rangeType = ERangeType.GRADE.getValue();
//            BdAwards bdAwards = awardsServiceApi.getAwardsOne(cuMember.getPkAwards()).getData();
//            if (bdAwards.getAwardsValue() > EAwards.MEMBER.getValue()) {
//                level = cuMember.getPkAwards();
//                rangeType = ERangeType.AWARDS.getValue();
//            }
            if (specsSkuList.size() == 0) {
                return;
            }
            List<BdWaresRange> bdWaresRangeList = bdWaresRangeService.querySkuWaresRangeByCondition(cuMember.getPkSettleCountry(), rangeType, level, specsSkuList);
            bdWaresRangeList.forEach(bdWaresRange -> {
                String key = bdWaresRange.getPkWaresDetail().toString() + bdWaresRange.getPkWaresSpecsSku();
                if (waresDetailExtMap.containsKey(key)) {
                    for (BdWaresDetailExt bdWaresDetailExt : waresDetailExtMap.get(key)) {
                        bdWaresDetailExt.setPrice(bdWaresRange.getPrice());
                        bdWaresDetailExt.setAchieve(bdWaresRange.getAchieve());
                        bdWaresDetailExt.setAssAchieve(bdWaresRange.getAssAchieve());
                    }
                }
            });
        }
    }

    /**
     * 设置订单邮费
     *
     * @param postageOrderItemsList 订单明细表，计算产品
     * @param postageDetail         邮费模板
     */
    private BigDecimal getSaleOrderPostage(List<SaOrderItems> postageOrderItemsList, BdPostage postage,
                                           BdPostageDetail postageDetail, BigDecimal freeAmount, OrderParam orderParam,
                                           boolean specialFlag) {
        // 计算邮费 判断价格
        // 获取重量 获取体积 获取价格
        BigDecimal weight = BigDecimal.ZERO;
        BigDecimal amount = BigDecimal.ZERO;
        BigDecimal volume = BigDecimal.ZERO;
        // 产品数量
        int number = 0;
        // 商品数量记录map
        Map<Integer, Integer> waresNumberMap = new HashMap<>();

        // 计算商品价格
        for (SaOrderItems saOrderItems : postageOrderItemsList) {
            // 根据产品获得产品
            BdProduct product = bdProductService.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());

            // TODO suiqing  抛货值 需要从邮费子表中获得
//            volume = volume.add(ComputeUtil.computeDivide(product.getLength().multiply(product.getWidth()).multiply(product.getHeight()),
//                    postage.getVolumeRatio()));
        }

        // 按商品数量收取邮费
        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);
        }
    }

    /**
     * 设置邮费模板主表
     *
     * @param orderParam     参数
     * @param postageMap     邮费模板
     * @param waresDetailExt 商品明细
     * @param saOrderItems   订单明细
     */
    private void setPostageTmpMap(OrderParam orderParam, Map<Integer, List<SaOrderItems>> postageMap, BdWaresDetailExt waresDetailExt, SaOrderItems saOrderItems) {
        Integer pkPostage;
        // 判断运输方式
        if (ETransportType.OCEAN.getValue() == orderParam.getTransType()) {
            pkPostage = waresDetailExt.getPkOceanPostage();
        } else if (ETransportType.AIR.getValue() == orderParam.getTransType()) {
            pkPostage = waresDetailExt.getPkAirPostage();
        } else {
            pkPostage = waresDetailExt.getPkLandPostage();
        }
        if (postageMap.containsKey(pkPostage)) {
            List<SaOrderItems> postageOrderItemsList = postageMap.get(pkPostage);
            postageOrderItemsList.add(saOrderItems);
        } else {
            List<SaOrderItems> postageOrderItemsList = new ArrayList<>();
            postageOrderItemsList.add(saOrderItems);
            postageMap.put(pkPostage, postageOrderItemsList);
        }
    }

    /**
     * @param postageDetail 邮费模板
     * @param weight        重量
     *                      1) 重量计费
     *                      首重重量>=实际重量 邮费 = 首重邮费
     *                      反之 ：邮费 = 首重邮费+((实际重量-首重重量)/续重重量)*续重邮费
     *                      2) 体积计费
     *                      实际重量 = 长*宽*高/6000  利用重量计费公式计算实际邮费
     *                      判断重量计费跟体积计费哪个大使用哪个计费方法
     *                      陆运、空运、海运（国内默认陆运）
     */
    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;
    }

    /**
     * 获取订单子表
     *
     * @param cuMember         会员
     * @param saOrder          订单主表
     * @param currency         币种
     * @param saOrderItemsList 订单明细
     * @param waresDetailExt   商品明细
     */
    private SaOrderItems getSaOrderItems(CuMember cuMember, SaOrderExt saOrder, CurrencyDTO currency, List<SaOrderItems> saOrderItemsList, BdWaresDetailExt waresDetailExt) {
        SaOrderItems saOrderItems = SaOrderItems.builder()
                .pkProduct(waresDetailExt.getPkProduct())
                .pkWares(waresDetailExt.getPkWares())
                .pkWaresDetail(waresDetailExt.getPkId())
                .pkWaresSpecsSku(waresDetailExt.getPkWaresSpecsSku().longValue())
                .price(waresDetailExt.getPrice())
                .achievement(waresDetailExt.getAchieve())
                .assAchievement(waresDetailExt.getAssAchieve())
                .quantity(waresDetailExt.getQuantity() * waresDetailExt.getWaresQuantity())
                .waresQuantity(waresDetailExt.getWaresQuantity())
                .pkRate(currency.getPkId())
                .isGift(waresDetailExt.getIsGift())
                .specsName(waresDetailExt.getSpecsName())
                .specsNameId(waresDetailExt.getSpecsNameId())
                .pkSpecialCurrency(waresDetailExt.getPkSpecialCurrency())
                .shippingChannel(waresDetailExt.getShippingChannel())
                .pkSupplier(waresDetailExt.getPkSupplier())
                .skuCode(CommonUtil.createSkuCode(waresDetailExt.getProductCode(), waresDetailExt.getSpecsNameId()))
                .wareCode(waresDetailExt.getWaresCode())
                .build();
        if (saOrderItems.getIsGift() != null && EYesNo.YES.getIntValue() == saOrderItems.getIsGift()) {
            saOrderItems.setPrice(BigDecimal.ZERO);
        }
        if (cuMember != null) {
            saOrderItems.setPkGrade(cuMember.getPkSettleGrade());
            saOrderItems.setPkAwards(cuMember.getPkAwards());
        }
        if (saOrder != null) {
            saOrderItems.setPkStorehouse(saOrder.getPkStorehouse());
            saOrderItems.setOrderStatus(saOrder.getOrderStatus());
            saOrderItems.setPkCreator(saOrder.getPkCreator());
            saOrderItems.setCreationTime(saOrderItems.getCreationTime());
            saOrderItems.setPkCountry(saOrder.getPkCountry());
        }
        saOrderItemsList.add(saOrderItems);
        return saOrderItems;
    }

    /**
     * 简单的封装订单基本信息
     *
     * @param orderParam 参数
     * @param cuMember   会员
     */
    SaOrderExt packageSaveSaOrder(OrderParam orderParam, CuMember cuMember, String orderCode) {
        SaOrderExt saOrderExt = new SaOrderExt();
        saOrderExt.setOrderCode(orderCode);
        saOrderExt.setOrderAmount(BigDecimal.ZERO);
        saOrderExt.setOrderAchieve(BigDecimal.ZERO);
        saOrderExt.setOrderAssAchieve(BigDecimal.ZERO);
        saOrderExt.setPkMember(cuMember.getPkId());
        saOrderExt.setOrderType(orderParam.getSpecialArea());
        saOrderExt.setPkReference(cuMember.getPkParent());
        saOrderExt.setPkPlacement(cuMember.getPkPlaceParent());
        saOrderExt.setRecName(orderParam.getRecName());
        saOrderExt.setRecPhone(orderParam.getRecPhone());
        saOrderExt.setRecProvince(orderParam.getRecProvince());
        if (CountryConstants.CHINA_COUNTRY.equals(cuMember.getPkSettleCountry()) || orderParam.getPkStorehouse() == null) {
            if (orderParam.getRecProvince() != null) {
                // 根据收货省获取仓库
                BdStorehouse bdStorehouse = currencyServiceApi.queryBdStorehouseByProvince(orderParam.getRecProvince()).getData();
                if (bdStorehouse != null) {
                    saOrderExt.setPkStorehouse(bdStorehouse.getPkId());
                }
            }
        } else {
            saOrderExt.setPkStorehouse(orderParam.getPkStorehouse());
        }
        saOrderExt.setRecCity(orderParam.getRecCity());
        saOrderExt.setRecCounty(orderParam.getRecCounty());
        saOrderExt.setRecAddress(orderParam.getRecAddress());
        saOrderExt.setRemark(orderParam.getRemark());
        saOrderExt.setTranType(orderParam.getTransType());
        saOrderExt.setDeliveryWay(orderParam.getDeliveryWay());
        // 如果发货方式为空，或者为0，则重置为快递发货
        if (null == saOrderExt.getDeliveryWay() || saOrderExt.getDeliveryWay().equals(0)) {
            saOrderExt.setDeliveryWay(EDelivery.FAST_MAIL.getValue());
        }
        // 订单状态先设置为待支付，支付的时候更新
        saOrderExt.setOrderStatus(EOrderStatus.WAIT_PAY.getValue());
        saOrderExt.setPkVertex(cuMember.getPkVertex());
        saOrderExt.setPkCreator(orderParam.getCenterCodeId());
        saOrderExt.setPkCountry(cuMember.getPkSettleCountry());
        saOrderExt.setPkMemberStore(orderParam.getPkMemberStore());
        if (EOrderType.REGISTER_ORDER.getValue() == orderParam.getSpecialArea()
                || EOrderType.SPECIAL_REGISTER_ORDER.getValue() == orderParam.getSpecialArea()
        ) {
            saOrderExt.setCreationTime(cuMember.getCreationTime());
        } else {
            saOrderExt.setCreationTime(DateUtils.currentDateTime());
        }
        orderParam.setOrderCode(orderCode);
        return saOrderExt;
    }

    /**
     * @param settleOrderAmount 订单金额
     * @param settleOrderPv     订单业绩
     * @param pkCountry         国家
     *                          orderType 1 = 注册，注册不用找累计 2 升级需要
     */
    GradeDTO getMemberGradeAndAwardByCountry(BigDecimal settleOrderAmount, BigDecimal settleOrderPv, Integer pkCountry, String upgradeWay) {
        List<GradeDTO> gradeList = gradeServiceApi.queryGradeConfigByCondition(pkCountry).getData();

        if (gradeList != null && gradeList.size() > 0) {
//            // TODO new V1、V2是购买直接给等级，V3以上不是
//            gradeList = gradeList.stream().filter(tmp -> tmp.getGradeValue() < EGrade.VIP.getValue()).collect(Collectors.toList());

            for (GradeDTO gradeDTO : gradeList) {
                if (validateGradeByAchieve(settleOrderAmount, settleOrderPv, gradeDTO)) {
                    if (EUpgradeWay.COVER.getValue() != Integer.parseInt(upgradeWay)) {
                        gradeDTO.setStartValue(settleOrderPv);
                    }
                    return gradeDTO;
                }
            }
        }
        return null;
    }

    private Boolean validateGradeByAchieve(BigDecimal settleOrderAmount, BigDecimal settleOrderPv, GradeDTO gradeDTO) {
        BigDecimal compareValue;
        if (null == gradeDTO.getCensusValue() || EStatisticalValue.ACHIEVEMENT.getValue() == gradeDTO.getCensusValue()) {
            compareValue = settleOrderPv;
        } else {
            compareValue = settleOrderAmount;
        }
        BigDecimal startValue = gradeDTO.getStartValue();
        if (compareValue.compareTo(startValue) >= 0) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 订单支付按币种扣款
     *
     * @param payMoney        待支付金额
     * @param cuMemberAccount 会员账户
     * @param areaCurrencyDTO 支付配置DTO
     */
    public BigDecimal subtract(BigDecimal payMoney, CuMemberAccountExt cuMemberAccount, AreaCurrencyDTO areaCurrencyDTO) {
        Integer key = areaCurrencyDTO.getFieldValue();

        // 扣款最大比例金额
        BigDecimal deductMaxRatioAmount = areaCurrencyDTO.getDeductMaxRatioAmount();

        if (payMoney.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal accountValue = getAccountByKey(cuMemberAccount, key);
            if (!ComputeUtil.compareValue(accountValue)) {
                return payMoney;
            }
            BigDecimal value = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.PAY_ACCOUNT + key);
            if (value == null) {
                value = BigDecimal.ZERO;
            }
            if (null != deductMaxRatioAmount
                    && payMoney.compareTo(deductMaxRatioAmount) >= 0) {
                // 待支付金额 大于等于 最大比例金额大，按最大比例金额处理
                if (deductMaxRatioAmount.compareTo(accountValue) > 0) {
                    value = value.add(accountValue);
                    payMoney = payMoney.subtract(accountValue);
                } else {
                    value = value.add(deductMaxRatioAmount);
                    payMoney = payMoney.subtract(deductMaxRatioAmount);
                }
            } else {
                if (payMoney.compareTo(accountValue) > 0) {
                    value = value.add(accountValue);
                    payMoney = payMoney.subtract(accountValue);
                } else {
                    value = value.add(payMoney);
                    payMoney = payMoney.subtract(payMoney);
                }
            }
            ReflectUtils.invokeSetter(cuMemberAccount, MemberFieldConstants.PAY_ACCOUNT + key, value);
        }
        return payMoney;
    }

    /**
     * 通过反射获取账户余额
     *
     * @param cuMemberAccount 账户
     * @param key             键
     * @return 余额
     */
    public BigDecimal getAccountByKey(CuMemberAccountExt cuMemberAccount, Integer key) {
        BigDecimal accountValue = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.ACCOUNT + key);
        BigDecimal lockAccountValue = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.LOCK_ACCOUNT + key);
        BigDecimal payAccountValue = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.PAY_ACCOUNT + key);
        accountValue = accountValue.add(lockAccountValue.negate());
        if (payAccountValue != null && ComputeUtil.compareValue(accountValue, payAccountValue)) {
            accountValue = accountValue.subtract(payAccountValue);
        }
        return accountValue;
    }

    /**
     * 转换，将销售订单转换为传到前台的销售订单VO
     *
     * @param saOrderVO 销售订单
     */
    void transformSaOrderToVO(SaOrderVO saOrderVO) {
        // 处理会员编号，汇率，顶点
        CurrencyDTO currencyDTO = currencyServiceApi.getCurrencyByPkId(saOrderVO.getPkRate()).getData();
        saOrderVO.setRate(currencyDTO.getOutExchangeRate());
    }

    /**
     * @param orderPrefix 订单前缀
     * @return 订单号
     */
    public String createOrderCode(String orderPrefix) {
        for (int i = 0; i < MagicNumberConstants.RETRY_COUNT; i++) {
            String orderCode = CommonUtil.createSerialNumber(orderPrefix);
            if (redisService.lockKeyOnce(orderCode)) {
                return orderCode;
            }
        }
        throw new RuntimeException(TransactionUtils.getContent(MemberMsgConstants.MEMBER_IS_OPERATION));
    }

    /**
     * 根据等级主键查询等级
     *
     * @param pkCountry 国家
     * @param pkGrade   等级
     */
    GradeDTO queryGradeConfigByCondition(Integer pkCountry, Integer pkGrade) {
        return gradeServiceApi.queryGradeConfigByCondition(pkCountry, pkGrade).getData();
    }

}
