package com.hzs.bonus.bonus.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.hzs.activity.pick.IAcPickServiceApi;
import com.hzs.bonus.bonus.param.LeXueRangeParam;
import com.hzs.bonus.bonus.vo.BonusRecordDetailVO;
import com.hzs.common.core.constant.CountryConstants;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.msg.BonusMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.domain.activity.pick.AcPickMemberLog;
import com.hzs.common.domain.activity.pick.ext.AcPickExt;
import com.hzs.common.domain.bonus.BdBonusDeduct;
import com.hzs.common.domain.bonus.risk.CuMemberRiskControl;
import com.hzs.common.domain.member.base.CuAwardsControl;
import com.hzs.common.domain.member.bonus.*;
import com.hzs.common.domain.member.detail.CuMemberAssess;
import com.hzs.common.domain.member.ext.CuBonusExpandExt;
import com.hzs.common.domain.member.ext.CuMemberSettleExt;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.ext.SaOrderItemsExt;
import com.hzs.common.domain.sale.order.SaOrderItems;
import com.hzs.common.domain.system.config.BdAwards;
import com.hzs.common.domain.system.config.BdGrade;
import com.hzs.system.config.dto.BonusConfigDTO;
import com.hzs.system.config.dto.BonusExpandDTO;
import com.hzs.system.config.dto.BonusRepurchasePushDTO;
import com.hzs.system.config.dto.RangeDTO;
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.stream.Collectors;

/**
 * @Description: 计算复购的奖金处理类
 * @Classname: BonusSettlePurchaseHandle
 * @PackageName: com.hzs.member.bonus.service.impl
 */
@Slf4j
@Component
public class BonusSettlePurchaseHandle extends BonusSettleHandle {

    @Autowired
    private BonusSettleFirstPurchaseHandle bonusSettleFirstPurchaseHandle;

    @DubboReference
    IAcPickServiceApi iAcPickServiceApi;

    List<CuMemberBonusPush> calculateRepurchasePushBonusOne(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO,
                                                            Map<Long, CuMemberAssess> cuMemberAssessMap, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                            SaOrderExt saOrderExt) {
        CuMemberSettleExt sourceSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
        List<CuMemberBonusPush> cuMemberBonusPushList = new ArrayList<>();
        if (sourceSettleExt == null) {
            return cuMemberBonusPushList;
        }
        BigDecimal orderAchieve = saOrderExt.getOrderAchieve();
        int i = MagicNumberConstants.BLOOD_GENERATION_START;
        Long pkParent = sourceSettleExt.getPkParent();
        while (i <= MagicNumberConstants.BLOOD_GENERATION_END) {
            CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(pkParent);
            if (targetMemberSettleExt == null) {
                break;
            }
            // 死点没有奖金
            if (ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory() ||
                    EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()) {
                pkParent = targetMemberSettleExt.getPkParent();
                continue;
            }
            if (validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.HELP_EACH_INCOME.getValue())) {
                pkParent = targetMemberSettleExt.getPkParent();
                continue;
            }

            // TODO new 乐学没有复购考核校验，改为校验月新增小区业绩
//            // 正常状态的辅导奖需要判断复购考核，复购考核不通过的状态变为烧伤
//            if (EYesNo.NO.getIntValue() == targetMemberSettleExt.getPurchaseStatus()) {
//                // 需要复购考核的
//                CuMemberAssess cuMemberAssess = cuMemberAssessMap.get(targetMemberSettleExt.getPkMember());
//                if (cuMemberAssess == null) {
//                    pkParent = targetMemberSettleExt.getPkParent();
//                    continue;
//                }
//            }

            CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
            // 直推奖金明细
            int pkBonusItem = getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.HELP_EACH_INCOME.getValue());
            CuMemberBonusPush cuMemberBonusPush = bonusSettleFirstPurchaseHandle.getCuMemberBonusPush(saOrderExt, targetMemberSettleExt, cuMemberBonus, pkBonusItem);
            Map<Integer, BonusRepurchasePushDTO> repurchasePushMap = bonusConfigDTO.getBonusRepurchasePushMap().get(targetMemberSettleExt.getPkSettleCountry());
            if (!repurchasePushMap.containsKey(i)) {
                break;
            }
            // 复购直推需要修改
            BonusRepurchasePushDTO bonusRepurchasePushDTO = repurchasePushMap.get(i);
            cuMemberBonusPush.setCalType(bonusRepurchasePushDTO.getCalType());
            cuMemberBonusPush.setRound(0);
            cuMemberBonusPush.setSecond(0);
            // 比例
            if (ECalType.RATIO.getValue() == bonusRepurchasePushDTO.getCalType()) {
                cuMemberBonusPush.setCalValue(bonusRepurchasePushDTO.getPushValue());
                cuMemberBonusPush.setPretaxIncome(ComputeUtil.computeBonusMultiply(orderAchieve, bonusRepurchasePushDTO.getPushValue()));
            } else {
                cuMemberBonusPush.setCalValue(BigDecimal.ZERO);
                cuMemberBonusPush.setPretaxIncome(bonusRepurchasePushDTO.getPushValue());
            }
            BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusPush, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
            if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusPush.getIncomeStatus()) {
                cuMemberBonus.setRepurPushIncome(ComputeUtil.computeAdd(cuMemberBonus.getRepurPushIncome(), cuMemberBonusPush.getPretaxIncome()));
                setPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusPush);
            }
            repurchasePushRemark(saOrderExt, cuMemberBonusPush, sourceSettleExt, targetMemberSettleExt, BonusMsgConstants.REPURCHASE_PUSH);
            cuMemberBonusPushList.add(cuMemberBonusPush);
            pkParent = targetMemberSettleExt.getPkParent();
            i++;
        }
        return cuMemberBonusPushList;
    }

    /**
     * 计算复购拓展收益
     *
     * @param settleTableName   结算表
     * @param period            期间
     * @param bonusConfigDTO    参数
     * @param purchaseOrderList 首单
     * @param cuMemberBonusMap  所有计算出来的奖金汇总
     */
    List<CuMemberBonusExpand> calculateRepurchaseExpandBonus(Map<Long, CuMemberRiskControl> riskControlMap, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleDateStr,
                                                             BonusConfigDTO bonusConfigDTO, Map<String, String> systemConfigMap, List<SaOrderExt> purchaseOrderList, Integer period,
                                                             Map<Long, CuMemberBonus> weekMemberBonusMap, Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, CuBonusExpandExt> cuBonusExpandExtMap) {
        List<CuMemberBonusExpand> cuMemberBonusExpandList = new ArrayList<>();
        // 获取所有订单的上级，根据订单往上一步步计算
        // key：订单ID，value：订单向上找安置人列表（会查询出来延缓发放奖金数据）
        Map<Long, List<CuMemberSettleExt>> memberSettleMap = iCuMemberTreeService.batchQueryCuMemberSettlePlaceParent(settleTableName, period, purchaseOrderList);

        // 订单安置上找所有会员列表
        List<CuMemberSettleExt> memberSettleExtList = new ArrayList<>();
        for (List<CuMemberSettleExt> cuMemberSettleExt : memberSettleMap.values()) {
            memberSettleExtList.addAll(cuMemberSettleExt);
        }
        // 订单安置上所有会员List转成map
        getMemberSettle(cuMemberSettleExtMap, memberSettleExtList);

        for (SaOrderExt saOrderExt : purchaseOrderList) {
            // 所有需要计算的父节点，只计算新增（当前订单会员向上找的所有安置人）
            List<CuMemberSettleExt> cuMemberSettleExtList = memberSettleMap.get(saOrderExt.getPkId());
            if (CollectionUtil.isEmpty(cuMemberSettleExtList)) {
                // 会员上面没有人
                continue;
            }
            // 这三个参数是单独配置4-N的参数
            BigDecimal addTouch = BigDecimal.ZERO;
            BigDecimal expandRatio = BigDecimal.ZERO;
            int expandNumber = 0;
            for (int i = cuMemberSettleExtList.size() - 1; i >= 0; i--) {
                CuMemberSettleExt cuMemberSettleExt = cuMemberSettleExtList.get(i);
                if (cuBonusExpandExtMap.containsKey(cuMemberSettleExt.getPkMember())) {
                    addTouch = cuBonusExpandExtMap.get(cuMemberSettleExt.getPkMember()).getAddTouch();
                    expandRatio = cuBonusExpandExtMap.get(cuMemberSettleExt.getPkMember()).getExpandRatio();
                    expandNumber = cuBonusExpandExtMap.get(cuMemberSettleExt.getPkMember()).getExpandNumber();
                    break;
                }
            }
            // 计算量奖（拓展收益）
            List<CuMemberBonusExpand> expandList = calculateRepurchaseExpandBonusOne(riskControlMap, settleTableName, cuMemberSettleExtMap, bonusConfigDTO, systemConfigMap, period,
                    weekMemberBonusMap, cuMemberBonusMap, saOrderExt, cuMemberSettleExtList, addTouch, expandRatio, expandNumber);
            if (expandList.size() > 0) {
                cuMemberBonusExpandList.addAll(expandList);
            }
        }
        // 根据订单往上穿业绩，只计算新增
        return cuMemberBonusExpandList;
    }

    /**
     * @Description: 秒接复购量奖
     * @return: List<CuMemberBonusExpand>
     */
    protected List<CuMemberBonusExpand> calculateRepurchaseExpandSecondBonus(Map<Long, CuMemberRiskControl> riskControlMap, String settleTableName, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO,
                                                                             Map<String, String> systemConfigMap, Integer period, Map<Long, CuMemberBonus> weekMemberBonusMap,
                                                                             Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt,
                                                                             List<CuMemberSettleExt> cuMemberSettleExtList, String settleDateStr, BigDecimal addTouch, BigDecimal expandRatio, Integer expandNumber) {
        // 复购订单，计算复购极差，复购拓展
        return calculateRepurchaseExpandBonusOne(riskControlMap, settleTableName, cuMemberSettleExtMap, bonusConfigDTO, systemConfigMap, period, weekMemberBonusMap, cuMemberBonusMap,
                saOrderExt, cuMemberSettleExtList, addTouch, expandRatio, expandNumber);
    }

    /**
     * @Description: 秒接复购量奖
     * @return: List<CuMemberBonusExpand>
     */
    protected List<CuMemberBonusPush> calculateRepurchasePushSecondBonus(String settleTableName, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, Integer period,
                                                                         Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt,
                                                                         List<CuMemberSettleExt> cuMemberSettleExtList, String settleDateStr) {
        // 根据订单获取轮次，要回写
        // 乐学新制度没有没有复购考核了
//        Map<Long, CuMemberAssess> cuMemberAssessMap = getCuMemberAssessMap(cuMemberSettleExtMap, settleDateStr, cuMemberSettleExtList);
        return calculateRepurchasePushBonusOne(cuMemberSettleExtMap, bonusConfigDTO, null, period, cuMemberBonusMap, saOrderExt);
    }

    /**
     * 计算复购量奖（拓展收益）
     *
     * @return
     */
    private List<CuMemberBonusExpand> calculateRepurchaseExpandBonusOne(Map<Long, CuMemberRiskControl> riskControlMap, String settleName, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO,
                                                                        Map<String, String> systemConfigMap, Integer period, Map<Long, CuMemberBonus> weekMemberBonusMap, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                                        SaOrderExt saOrderExt, List<CuMemberSettleExt> cuMemberSettleExtList,
                                                                        BigDecimal addTouch, BigDecimal expandRatio, Integer expandNumber) {
        List<CuMemberBonusExpand> cuMemberBonusExpandList = new ArrayList<>();
        CuMemberSettleExt settleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
        if (settleExt == null) {
            return cuMemberBonusExpandList;
        }
//        settleExt.setRepurchaseAmount(ComputeUtil.computeAdd(settleExt.getRepurchaseAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
//        settleExt.setRepurchasePv(ComputeUtil.computeAdd(settleExt.getRepurchasePv(), saOrderExt.getOrderAchieve()));
//        settleExt.setRepurchaseNewAmount(ComputeUtil.computeAdd(settleExt.getRepurchaseNewAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
//        settleExt.setRepurchaseNewPv(ComputeUtil.computeAdd(settleExt.getRepurchaseNewPv(), saOrderExt.getOrderAchieve()));

        // 先计算新增，根据新增计算碰次
        // 先进行初始化所有的安置人，存储需要修改的值,cuMemberSettleExtMap最终修改的
//        getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);

        Map<Integer, BonusExpandDTO> bdBonusExpandMap = bonusConfigDTO.getBonusExpandMap();
        // 先准备值，准备好值后，开始计算，计算碰次
        int touchNum = calculateTouchNum(riskControlMap, cuMemberSettleExtMap, saOrderExt, cuMemberSettleExtList, bonusConfigDTO);
        // 有碰次，计算拓展奖
        if (touchNum > 0) {
            // 判断是否>3 是否需要启动4-N，4-N的参数按照伞上各安置人结算国家进行获取
            // 先计算前3碰
            int startTouch = touchNum;
            // 后面碰次
            int endTouch = 0;
            // 拓展次数（一般配置的为3，前3碰保持原来的处理逻辑，3次以后判断是否启动4-N，进行分摊收益）
            BonusExpandDTO bdBonusExpand = bdBonusExpandMap.get(saOrderExt.getPkCountry());
            int realExpandNumber = expandNumber > 0 ? expandNumber : bdBonusExpand.getExpandNumber();
            if (touchNum > realExpandNumber) {
                startTouch = realExpandNumber;
                endTouch = touchNum - startTouch;
            }

            // 正常的拓展奖计算
            // 计算拓展奖
            for (int i = 1; i <= startTouch; i++) {
                for (CuMemberSettleExt sourceMemberSettleExt : cuMemberSettleExtList) {
                    CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(sourceMemberSettleExt.getPkPlaceParent());
                    if (targetMemberSettleExt == null
                            || ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                            || EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()) {
                        continue;
                    }
                    // 验证是否有当前奖金项
                    if (validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.CONSUMPTION_EXPANSION_INCOME.getValue())) {
                        continue;
                    }
                    // 判断左右区是否有值，找到有值的就是有碰次，碰完左区或右区肯定有变为0的
                    if ((ComputeUtil.compareValue(targetMemberSettleExt.getABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getBBalance()))
                            || (ComputeUtil.compareValue(targetMemberSettleExt.getRepABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getRepBBalance()))) {
                        // 根据会员等级获取对应的配置
                        BdGrade bdGrade = getGradeExpand(bonusConfigDTO, targetMemberSettleExt);
                        BigDecimal countryExpandRatio = bdGrade.getRepurchaseRatio();
                        // 计算量碰
                        calculateRepurchaseExpandBonusByAchieve(period, weekMemberBonusMap, cuMemberBonusMap, bonusConfigDTO, systemConfigMap, cuMemberBonusExpandList,
                                saOrderExt, touchNum, i, sourceMemberSettleExt, targetMemberSettleExt, bdGrade, countryExpandRatio);
                        break;
                    }
                }
            }
            // 4-N计算
            if (endTouch > 0) {
                // 获得每一碰的比例, 找到剩下的碰次的国家
                for (int i = 1; i <= endTouch; i++) {
                    for (CuMemberSettleExt sourceMemberSettleExt : cuMemberSettleExtList) {
                        CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(sourceMemberSettleExt.getPkPlaceParent());
                        if (targetMemberSettleExt == null
                                || ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                                || EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()) {
                            continue;
                        }
                        // 验证是否有当前奖金项
                        if (validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.CONSUMPTION_EXPANSION_INCOME.getValue())) {
                            continue;
                        }
                        // 判断左右区是否有值，找到有值的就是有碰次，碰完左区或右区肯定有变为0的
                        if ((ComputeUtil.compareValue(targetMemberSettleExt.getABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getBBalance()))
                                || (ComputeUtil.compareValue(targetMemberSettleExt.getRepABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getRepBBalance()))) {
                            // 根据会员等级获取对应的配置
                            BdGrade bdGrade = getGradeExpand(bonusConfigDTO, targetMemberSettleExt);
                            // 获取国家4-n的配置
                            BigDecimal countryExpandRatio = getCountryRepurchaseExpand(bonusConfigDTO, targetMemberSettleExt, endTouch, bdGrade, addTouch, expandRatio);
                            // 计算量碰
                            calculateRepurchaseExpandBonusByAchieve(period, weekMemberBonusMap, cuMemberBonusMap, bonusConfigDTO, systemConfigMap, cuMemberBonusExpandList,
                                    saOrderExt, touchNum, i + startTouch, sourceMemberSettleExt, targetMemberSettleExt, bdGrade, countryExpandRatio);
                            break;
                        }
                    }
                }
            }
        }
        return cuMemberBonusExpandList;
    }

    private int calculateTouchNum(Map<Long, CuMemberRiskControl> riskControlMap, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap,
                                  SaOrderExt saOrderExt, List<CuMemberSettleExt> cuMemberSettleExtList, BonusConfigDTO bonusConfigDTO) {
        int touchNum = 0;
        for (CuMemberSettleExt cuMemberSettleExt : cuMemberSettleExtList) {
            // 数据已经准备好了，肯定有值，map中是实际的值，先计算新增，然后根据新增结算计算碰次，list是为了存储碰次的顺序
            CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(cuMemberSettleExt.getPkPlaceParent());
            if (targetMemberSettleExt == null
                    || ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                    || EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()
                    || EGrade.START_UP.getValue() == targetMemberSettleExt.getGradeValue()) {
                continue;
            }
            // 验证是否计算奖金
            BdGrade bdGrade = getGradeExpand(bonusConfigDTO, targetMemberSettleExt);
            if (bdGrade.getRepurchaseCalculate() != null && EYesNo.NO.getIntValue() == bdGrade.getRepurchaseCalculate()) {
                continue;
            }
            if (EPlaceDept.LEFT_DEPT.getValue() == cuMemberSettleExt.getPlaceDept()) {
                // 左区
                // K值设置
                if (riskControlMap.containsKey(targetMemberSettleExt.getPkMember())) {
                    CuMemberRiskControl cuMemberRiskControl = riskControlMap.get(targetMemberSettleExt.getPkMember());
                    targetMemberSettleExt.setANewAmount(ComputeUtil.computeAdd(targetMemberSettleExt.getANewAmount(), ComputeUtil.computeBonusMultiply(convertLocalCurrency(saOrderExt, bonusConfigDTO), cuMemberRiskControl.getAchieveRatio())));
                    targetMemberSettleExt.setANewPv(ComputeUtil.computeAdd(targetMemberSettleExt.getANewPv(), ComputeUtil.computeBonusMultiply(saOrderExt.getUploadAchieve(), cuMemberRiskControl.getAchieveRatio())));
                    targetMemberSettleExt.setABalance(ComputeUtil.computeAdd(targetMemberSettleExt.getABalance(), ComputeUtil.computeBonusMultiply(saOrderExt.getUploadAchieve(), cuMemberRiskControl.getAchieveRatio())));
                } else {
                    targetMemberSettleExt.setANewAmount(ComputeUtil.computeAdd(targetMemberSettleExt.getANewAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
                    targetMemberSettleExt.setANewPv(ComputeUtil.computeAdd(targetMemberSettleExt.getANewPv(), saOrderExt.getUploadAchieve()));
                    targetMemberSettleExt.setABalance(ComputeUtil.computeAdd(targetMemberSettleExt.getABalance(), saOrderExt.getUploadAchieve()));
                }
                targetMemberSettleExt.setRABalance(ComputeUtil.computeAdd(targetMemberSettleExt.getRABalance(), saOrderExt.getUploadAchieve()));
            } else {
                // 右区
                if (riskControlMap.containsKey(targetMemberSettleExt.getPkMember())) {
                    CuMemberRiskControl cuMemberRiskControl = riskControlMap.get(targetMemberSettleExt.getPkMember());
                    targetMemberSettleExt.setBNewAmount(ComputeUtil.computeAdd(targetMemberSettleExt.getBNewAmount(), ComputeUtil.computeBonusMultiply(convertLocalCurrency(saOrderExt, bonusConfigDTO), cuMemberRiskControl.getAchieveRatio())));
                    targetMemberSettleExt.setBNewPv(ComputeUtil.computeAdd(targetMemberSettleExt.getBNewPv(), ComputeUtil.computeBonusMultiply(saOrderExt.getUploadAchieve(), cuMemberRiskControl.getAchieveRatio())));
                    targetMemberSettleExt.setBBalance(ComputeUtil.computeAdd(targetMemberSettleExt.getBBalance(), ComputeUtil.computeBonusMultiply(saOrderExt.getUploadAchieve(), cuMemberRiskControl.getAchieveRatio())));
                } else {
                    targetMemberSettleExt.setBNewAmount(ComputeUtil.computeAdd(targetMemberSettleExt.getBNewAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
                    targetMemberSettleExt.setBNewPv(ComputeUtil.computeAdd(targetMemberSettleExt.getBNewPv(), saOrderExt.getUploadAchieve()));
                    targetMemberSettleExt.setBBalance(ComputeUtil.computeAdd(targetMemberSettleExt.getBBalance(), saOrderExt.getUploadAchieve()));
                }
                targetMemberSettleExt.setRBBalance(ComputeUtil.computeAdd(targetMemberSettleExt.getRBBalance(), saOrderExt.getUploadAchieve()));
            }
            // 判断左右区是否有值，左右区有值有碰次
            if (ComputeUtil.compareValue(targetMemberSettleExt.getABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getBBalance())) {
                // 国内量奖修改为考核不通过的不占用4-N，不算奖金
                // 验证是否验证考核
                touchNum++;
            }
            // 判断左右区是否有值，左右区有值有碰次
            if (ComputeUtil.compareValue(targetMemberSettleExt.getRABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getRBBalance())) {
                BigDecimal minAchieve = ComputeUtil.obtainMinAchieve(targetMemberSettleExt.getRABalance(), targetMemberSettleExt.getRBBalance());
                targetMemberSettleExt.setRABalance(ComputeUtil.computeSubtractAbs(targetMemberSettleExt.getRABalance(), minAchieve));
                targetMemberSettleExt.setRBBalance(ComputeUtil.computeSubtractAbs(targetMemberSettleExt.getRBBalance(), minAchieve));
            }
        }
        return touchNum;
    }

    private Map<Long, CuMemberAssess> getCuMemberAssessMap(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleDateStr, List<CuMemberSettleExt> memberSettleExtList) {
        List<CuMemberSettleExt> queryMemberList = getQueryMemberSettleExtList(cuMemberSettleExtMap, memberSettleExtList);
        return getLongCuMemberAssessMap(settleDateStr, queryMemberList);
    }

    /**
     * 计算复购极差
     *
     * @param period            期间
     * @param bonusConfigDTO    参数
     * @param purchaseOrderList 复购订单
     * @param cuMemberBonusMap  所有计算出来的奖金汇总
     */
    List<CuMemberBonusRange> calculateRepurchaseRangeBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleDate, Map<String, RangeDTO> rangeDtoMap, Map<String, BdAwards> awardsMap,
                                                           BonusConfigDTO bonusConfigDTO, List<SaOrderExt> purchaseOrderList, Integer period,
                                                           Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, CuAwardsControl> cuAwardsControlMap, LeXueRangeParam leXueRangeParam) {
        // 计算复购极差的订单
//        List<SaOrderExt> chinaRangeOrderList = new ArrayList<>();
        // 计算乐学易考特殊复购极差的订单
        List<SaOrderExt> specialOrderList = new ArrayList<>();
        purchaseOrderList.forEach(saOrderExt -> {
            /*if (Objects.equals(EOrderType.REPURCHASE_ORDER.getValue(), saOrderExt.getOrderType()) ||
                    Objects.equals(EOrderType.THIRD_ORDER.getValue(), saOrderExt.getOrderType())) {
                rangeOrderList.add(saOrderExt);
            } else */
            if (Objects.equals(EOrderType.SPECIAL_REPURCHASE_ORDER.getValue(), saOrderExt.getOrderType())) {
//                rangeOrderList.add(saOrderExt);
                specialOrderList.add(saOrderExt);
            }/* else if (Objects.equals(saOrderExt.getPkCountry(), CountryConstants.CHINA_COUNTRY)) {
                if (!Objects.equals(EOrderType.FANS_ORDER.getValue(), saOrderExt.getOrderType()) &&
                        !Objects.equals(EOrderType.HAI_FUN_UPGRADE_ORDER.getValue(), saOrderExt.getOrderType())) {
                    chinaRangeOrderList.add(saOrderExt);
                }
            } else {
                overseasRangeOrderList.add(saOrderExt);
            }*/
        });
        List<CuMemberBonusRange> cuMemberBonusRangeList = new ArrayList<>();
        // 处理血缘上网体信息
        getMemberParentBySaOrder(cuMemberSettleExtMap, settleTableName, purchaseOrderList);
        // TODO new 乐学不需要考核相关
//        List<CuMemberSettleExt> cuMemberSettleExtList = getMemberParentBySaOrder(cuMemberSettleExtMap, settleTableName, purchaseOrderList);
//        Map<Long, CuMemberAssess> cuMemberAssessMap = getCuMemberAssessMap(cuMemberSettleExtMap, settleDate, cuMemberSettleExtList);

        Map<Long, CuMemberAssess> cuMemberAssessMap = null;

//        if (chinaRangeOrderList.size() > 0) {
//            Map<String, List<SaOrderRangeDto>> saOrderRangeDtoMap = saOrderServiceApi.queryOrderRangeVO(chinaRangeOrderList).getData();
//            Map<String, RangeDTO> rangePkDtoMap = new HashMap<>(ComputeUtil.mapInitCapacity(rangeDtoMap.size()));
//            rangeDtoMap.forEach((key, rangeDto) ->
//                    rangePkDtoMap.put(rangeDto.getPkCountry().toString() + rangeDto.getPkRange(), rangeDto));
//            chinaRangeOrderList.forEach(saOrderExt -> {
//                List<SaOrderRangeDto> orderRangeVOList = saOrderRangeDtoMap.get(saOrderExt.getOrderCode());
//                if (orderRangeVOList == null || orderRangeVOList.size() == 0) {
//                    return;
//                }
//                if (!validateSecondOrderExistBonus(saOrderExt, EBonusItems.REPURCHASE_RANGE_INCOME.getValue())) {
//                    return;
//                }
//                Map<Long, List<SaOrderRangeDto>> orderRangeDtoMap = getRangeDtoMap(orderRangeVOList);
//                for(Long pkItem :orderRangeDtoMap.keySet()){
//                    List<SaOrderRangeDto> saOrderRangeDtoList = orderRangeDtoMap.get(pkItem);
//                    // 一定要发完，从推荐人开始发
//                    executeChinaOrderRange(cuMemberSettleExtMap, rangeDtoMap, awardsMap, bonusConfigDTO, period, cuMemberBonusMap,
//                            cuAwardsControlMap, cuMemberBonusRangeList, cuMemberAssessMap, rangePkDtoMap, saOrderExt, saOrderRangeDtoList);
//                }
//            });
//            List<SaOrderExt> saOrderExtList = new ArrayList<>();
//            for (SaOrderExt saOrderExt : chinaRangeOrderList) {
//                if(ComputeUtil.compareValue(saOrderExt.getOrderAmount(), BigDecimal.valueOf(170000))){
//                    for (SaOrderItemsExt saOrderItemsExt : saOrderExt.getOrderItemsExtList()) {
//                        if(Objects.equals(13825, saOrderItemsExt.getPkWares())){
//                            saOrderExt.setOrderAchieve(saOrderItemsExt.getAchievement());
//                            saOrderExtList.add(saOrderExt);
//                        }
//                    }
//                }
//            }
//            if(saOrderExtList.size() >0) {
//                for (SaOrderExt saOrderExt : saOrderExtList) {
//                    CuMemberSettleExt sourceMemberTree = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
//                    while (true) {
//                        if (sourceMemberTree == null) {
//                            break;
//                        }
//                        CuMemberSettleExt parentMemberTree = cuMemberSettleExtMap.get(sourceMemberTree.getPkParent());
//                        parentMemberTree = getRangeCuMemberTree(cuMemberSettleExtMap, rangeDtoMap, awardsMap, bonusConfigDTO, sourceMemberTree, parentMemberTree, cuAwardsControlMap, cuMemberAssessMap);
//                        if (parentMemberTree == null) {
//                            break;
//                        }
//                        RangeDTO parentRangeDto = getRangeDto(rangeDtoMap, awardsMap, parentMemberTree, cuAwardsControlMap);
//                        RangeDTO sourceRangeDto = getRangeDto(rangeDtoMap, awardsMap, sourceMemberTree, cuAwardsControlMap);
//                        BigDecimal achieveRatio = ComputeUtil.computeSubtract(parentRangeDto.getAchieveRatio(), sourceRangeDto.getAchieveRatio());
//                        // 发放奖金
//                        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, parentMemberTree);
//                        CuMemberBonusRange cuMemberBonusRange = getCuMemberBonusRange(bonusConfigDTO, saOrderExt, parentMemberTree, cuMemberBonus);
//                        cuMemberBonusRange.setCalAchieve(saOrderExt.getOrderAchieve());
////                        BigDecimal repurchaseRangeBonus = ComputeUtil.computeMultiply(ComputeUtil.computeSubtract(orderAchieve, saOrderRangeDto.getRangeAchieve()), saOrderRangeDto.getQuantity());
//                        if (ComputeUtil.compareValue(BigDecimal.ZERO, achieveRatio)) {
//                            sourceMemberTree = cuMemberSettleExtMap.get(parentMemberTree.getPkMember());
//                            continue;
//                        }
//                        cuMemberBonusRange.setCalValue(BigDecimal.ZERO);
//                        BigDecimal repurchaseRangeBonus = ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), achieveRatio);
//                        cuMemberBonusRange.setPretaxIncome(repurchaseRangeBonus);
//                        cuMemberBonusRange.setPkRange(parentRangeDto.getPkRange());
//                        cuMemberBonusRange.setPkBeforeRange(sourceRangeDto.getPkRange());
//                        cuMemberBonusRange.setPkOrderItems(0L);
//                        rangeRemark(saOrderExt, cuMemberBonusRange, sourceMemberTree, parentMemberTree, parentRangeDto, sourceRangeDto);
//                        packageRepurchaseRange(bonusConfigDTO, cuMemberBonusRangeList, saOrderExt, cuMemberBonus, cuMemberBonusRange, repurchaseRangeBonus);
//                        if (ERangeType.AWARDS.getValue() == parentRangeDto.getRangeType() && EAwards.GLOBAL_CHAIRMAN.getValue() == parentRangeDto.getRangeValue()) {
//                            break;
//                        }
//                        sourceMemberTree = cuMemberSettleExtMap.get(parentMemberTree.getPkMember());
//                    }
//                }
//            }
//        }
        // 乐学复购级差，商品4个等级购买差价300，这个位置进行拨出
        if (specialOrderList.size() > 0) {
            for (SaOrderExt saOrderExt : specialOrderList) {
                for (SaOrderItems saOrderItems : saOrderExt.getOrderItemsExtList()) {
                    if (EYesNo.YES.getIntValue() == saOrderItems.getIsGift() || ComputeUtil.compareGreaterThan(MagicNumberConstants.LXYK_V3, saOrderItems.getPrice())) {
                        // 赠品或者商品价格小于2680，不需要处理，2380已经是V4价格了，不存在往上拨出的极差
                        continue;
                    }

                    // 最大发放奖金
                    BigDecimal maxBonus;
                    if (ComputeUtil.compareValue(saOrderItems.getPrice(), MagicNumberConstants.LXYK_V1)) {
                        // 价格大于等于3280，最多拨900
                        // 2025.04.28 需求调整去掉 V1 等级，最低为2980，最多拨600
                        maxBonus = MagicNumberConstants.LXYK_BONUS_600;
                    } else if (ComputeUtil.compareValue(saOrderItems.getPrice(), MagicNumberConstants.LXYK_V2)) {
                        // 价格大于等于2980，最多拨600
                        maxBonus = MagicNumberConstants.LXYK_BONUS_600;
                    } else if (ComputeUtil.compareValue(saOrderItems.getPrice(), MagicNumberConstants.LXYK_V3)) {
                        // 价格大于等于2680，最多拨拨300
                        maxBonus = MagicNumberConstants.LXYK_BONUS_300;
                    } else {
                        maxBonus = BigDecimal.ZERO;
                    }

                    // 获取血缘伞上的推荐人 一定要发完，从推荐人开始发
                    // 当前会员
                    CuMemberSettleExt sourceMemberTree = cuMemberSettleExtMap.get(saOrderExt.getPkMember());

                    // 累计发放奖金
                    BigDecimal grantBonus = BigDecimal.ZERO;
                    while (ComputeUtil.compareGreaterThan(maxBonus, grantBonus)) {
                        // 最大发放奖金 大于 累计发放奖金，则继续处理
                        if (null == sourceMemberTree) {
                            break;
                        }
                        int pkGrade = sourceMemberTree.getPkGrade();
                        if (pkGrade == 3 || pkGrade == 4) {
                            // 如果是 V1 直接跳过，开始计算 V2
                            // 2025.04.28 需求调整去掉 V1 等级，V1 V2 就直接跳过，开始计算V3
                            pkGrade = 5;
                        }
                        // 推荐人
                        CuMemberSettleExt parentMemberTree = cuMemberSettleExtMap.get(sourceMemberTree.getPkParent());
                        // 找血缘线上高等级推荐人
                        parentMemberTree = getSpecialRangeCuMemberTree(cuMemberSettleExtMap, bonusConfigDTO, sourceMemberTree, parentMemberTree, cuMemberAssessMap, pkGrade);
                        if (null == parentMemberTree) {
                            break;
                        }
                        // 级差奖金
                        BigDecimal rangeOrder = BigDecimal.ZERO;
//                        if (parentMemberTree.getPkGrade() == 4) {
//                            // V2 拿 300
//                            // 2025.04.28 需求调整去掉 V1 等级，V2 不需要拿了
//                            rangeOrder = MagicNumberConstants.LXYK_BONUS_300;
//                        } else
                        if (parentMemberTree.getPkGrade() == 5) {
                            // V3前没有V2，拿600； V3前有V2，拿300
                            // 2025.04.28 需求调整去掉 V1 等级，V3 拿300
                            rangeOrder = MagicNumberConstants.LXYK_BONUS_300;
//                            if (ComputeUtil.computeSubtract(maxBonus, grantBonus).compareTo(new BigDecimal(900)) == 0) {
//                                rangeOrder = MagicNumberConstants.LXYK_BONUS_600;
//                            } else {
//                                rangeOrder = MagicNumberConstants.LXYK_BONUS_300;
//                            }
                        } else if (parentMemberTree.getPkGrade() == 6) {
                            // V4 拿剩下所有
                            rangeOrder = ComputeUtil.computeSubtract(maxBonus, grantBonus);
                        }
                        grantBonus = ComputeUtil.computeAdd(grantBonus, rangeOrder);
                        // 实际发放复购级差（多个商品情况下，需要乘商品数量）
                        BigDecimal repurchaseRangeBonus = ComputeUtil.computeMultiply(rangeOrder, saOrderItems.getWaresQuantity());

                        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, parentMemberTree);
                        CuMemberBonusRange cuMemberBonusRange = getCuMemberBonusRange(bonusConfigDTO, saOrderExt, parentMemberTree, cuMemberBonus);
                        cuMemberBonusRange.setCalAchieve(saOrderExt.getOrderAchieve());
                        cuMemberBonusRange.setCalValue(BigDecimal.ZERO);
                        cuMemberBonusRange.setPretaxIncome(repurchaseRangeBonus);
                        cuMemberBonusRange.setPkRange(0);
                        cuMemberBonusRange.setPkBeforeRange(0);
                        cuMemberBonusRange.setPkOrderItems(0L);
                        String remark = String.format(BonusMsgConstants.LE_SHARE_RANGE, saOrderExt.getOrderCode(),
                                sourceMemberTree.getMemberCode() + sourceMemberTree.getMemberName(),
                                parentMemberTree.getMemberCode() + parentMemberTree.getMemberName(), repurchaseRangeBonus);
                        cuMemberBonusRange.setRemark(remark);
                        // 封装复购级差，处理明细、扣项等
                        packageRepurchaseRange(bonusConfigDTO, cuMemberBonusRangeList, saOrderExt, cuMemberBonus, cuMemberBonusRange, repurchaseRangeBonus);
                        // 发放到最高级后跳出
                        if (parentMemberTree.getPkGrade() == 6) {
                            break;
                        }
                        sourceMemberTree = cuMemberSettleExtMap.get(parentMemberTree.getPkMember());
                    }
                }
            }
            // 学特殊级差
            calculateLeXueRangeBonus(settleTableName, rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, leXueRangeParam, specialOrderList, cuMemberBonusRangeList);
        }
        return cuMemberBonusRangeList;
    }

    /**
     * 封装复购级差
     *
     * @param bonusConfigDTO
     * @param cuMemberBonusRangeList
     * @param saOrderExt
     * @param cuMemberBonus
     * @param cuMemberBonusRange
     * @param repurchaseRangeBonus
     */
    private void packageRepurchaseRange(BonusConfigDTO bonusConfigDTO, List<CuMemberBonusRange> cuMemberBonusRangeList, SaOrderExt saOrderExt, CuMemberBonus cuMemberBonus, CuMemberBonusRange cuMemberBonusRange, BigDecimal repurchaseRangeBonus) {
        // 奖金扣项
        BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusRange, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusRange.getIncomeStatus()) {
            // 收益状态正常，扣除
            cuMemberBonus.setRepurRangeIncome(ComputeUtil.computeAdd(cuMemberBonus.getRepurRangeIncome(), repurchaseRangeBonus));
            setPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusRange);
        }
        cuMemberBonusRangeList.add(cuMemberBonusRange);
    }

    /**
     * 乐学特殊复购级差，根据法宝券进行计算奖金
     * 每个等级最多拨出一张法宝券，给200奖金，遇到V4为止
     * 如果购买时会员没有使用券，那么同等级也可以拨出一张
     *
     * @param settleTableName
     * @param rangeDtoMap
     * @param bonusConfigDTO
     * @param period
     * @param cuMemberBonusMap
     * @param leXueRangeParam
     * @param specialOrderList
     * @param cuMemberBonusRangeList
     */
    private void calculateLeXueRangeBonus(String settleTableName, Map<String, RangeDTO> rangeDtoMap, BonusConfigDTO bonusConfigDTO,
                                          Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, LeXueRangeParam leXueRangeParam,
                                          List<SaOrderExt> specialOrderList, List<CuMemberBonusRange> cuMemberBonusRangeList) {
        // 旧逻辑： 计算乐学易考特殊复购极差，找第一个vip，svip，找到有代金券，代金券-1，奖金给金额，第一个是svip后，就不给
        if (specialOrderList.size() > 0) {
            // 查找订单血缘上会员
            Set<Long> expandMemberSet = specialOrderList.stream().distinct().map(SaOrderExt::getPkMember).collect(Collectors.toSet());
            List<CuMemberSettleExt> specialMemberSettleExtList = iCuMemberTreeService.batchQueryCuMemberSettleParentForSpecial(settleTableName, expandMemberSet);

            // 重算的时候首先先把数量还回来，在重新计算，查询订单扣除的记录
            List<AcPickMemberLog> acPickMemberLogList = iAcPickServiceApi.queryPickMemberLog(specialOrderList).getData();
            // key: 会员ID + 提货专区ID
            Map<String, AcPickMemberLog> pickMemberLogMap = new HashMap<>(ComputeUtil.mapInitCapacity(acPickMemberLogList.size()));
            if (CollectionUtil.isNotEmpty(acPickMemberLogList)) {
                acPickMemberLogList.forEach(acPickMemberLog -> pickMemberLogMap.put(acPickMemberLog.getPkMember().toString() + acPickMemberLog.getPkPick(), acPickMemberLog));
                leXueRangeParam.setAcPickMemberLogList(acPickMemberLogList);
            }

            // 初始化父类网体的值
            Map<Long, CuMemberSettleExt> specialmeberSettleExtMap = new HashMap<>();
            getMemberSettle(specialmeberSettleExtMap, specialMemberSettleExtList);
            // 还原数量
            specialmeberSettleExtMap.forEach((pkMember, cumemberSettleExt) -> {
                String key = pkMember.toString() + cumemberSettleExt.getApPkId();
                if (pickMemberLogMap.containsKey(key)) {
                    cumemberSettleExt.setUsableQuantity(cumemberSettleExt.getUsableQuantity() + pickMemberLogMap.get(key).getPickQuantity());
                }
            });
            List<AcPickExt> acPickExtList = new ArrayList<>();
            for (SaOrderExt saOrderExt : specialOrderList) {
                // 商品使用法宝券数量（key: 商品ID，value： 法宝券数量）
                Map<Integer, Integer> productPickMap = new HashMap<>();
                for (SaOrderItemsExt saOrderItemsExt : saOrderExt.getOrderItemsExtList()) {
                    if (null != saOrderItemsExt.getUsePick() && saOrderItemsExt.getUsePick() != 0) {
                        productPickMap.put(saOrderItemsExt.getPkWares(), saOrderItemsExt.getUsePick());
                    }
                }

                for (SaOrderItemsExt saOrderItemsExt : saOrderExt.getOrderItemsExtList()) {
                    if (EYesNo.YES.getIntValue() == saOrderItemsExt.getIsGift()
                            || ComputeUtil.compareEqual(saOrderItemsExt.getPrice(), BigDecimal.ZERO)
                            || ComputeUtil.compareEqual(saOrderItemsExt.getAchievement(), BigDecimal.ZERO)) {
                        // 赠品 或者 金额为0 或者 业绩为0 则不进行处理
                        continue;
                    }
                    // 订单对应的会员
                    CuMemberSettleExt sourceMemberSettleExt = specialmeberSettleExtMap.get(saOrderExt.getPkMember());
                    if (null == sourceMemberSettleExt) {
                        break;
                    }
                    if (validatePkBonusItems(bonusConfigDTO, sourceMemberSettleExt.getPkSettleCountry(), EBonusItems.REPURCHASE_RANGE_INCOME.getValue())) {
                        // 没有这个奖项，直接退出
                        break;
                    }

                    // 当前订单明细使用了法宝券
                    Integer useNum = productPickMap.get(saOrderItemsExt.getPkWares());

                    if (null != useNum) {
                        // 订单使用了法宝券
                        if (useNum.equals(saOrderItemsExt.getWaresQuantity())) {
                            // 法宝券和商品数量一致
                            this.usePick(specialmeberSettleExtMap, rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                                    sourceMemberSettleExt, cuMemberBonusRangeList, acPickExtList);
                        } else {
                            // 法宝券和商品数量不一致，需要拆分处理
                            // 使用法宝券部分处理
                            SaOrderItemsExt tmpItems1 = BeanUtil.copyProperties(saOrderItemsExt, SaOrderItemsExt.class);
                            tmpItems1.setWaresQuantity(useNum);
                            tmpItems1.setUsePick(useNum);
                            this.usePick(specialmeberSettleExtMap, rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, tmpItems1,
                                    sourceMemberSettleExt, cuMemberBonusRangeList, acPickExtList);

                            // 未使用法宝券部分处理
                            SaOrderItemsExt tmpItems2 = BeanUtil.copyProperties(saOrderItemsExt, SaOrderItemsExt.class);
                            tmpItems2.setWaresQuantity(saOrderItemsExt.getWaresQuantity() - useNum);
                            tmpItems2.setUsePick(saOrderItemsExt.getWaresQuantity() - useNum);
                            this.notUsePick(specialmeberSettleExtMap, rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, tmpItems2,
                                    sourceMemberSettleExt, cuMemberBonusRangeList, acPickExtList);
                        }
                    } else {
                        // 没使用法宝券
                        this.notUsePick(specialmeberSettleExtMap, rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                                sourceMemberSettleExt, cuMemberBonusRangeList, acPickExtList);
                    }
                }
            }
            if (acPickExtList.size() > 0) {
                leXueRangeParam.setAcPickExtList(acPickExtList);
            }
        }
    }

    /**
     * 使用法宝券处理
     */
    private void usePick(Map<Long, CuMemberSettleExt> specialmeberSettleExtMap, Map<String, RangeDTO> rangeDtoMap, BonusConfigDTO bonusConfigDTO, Integer period,
                         Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt, SaOrderItemsExt saOrderItemsExt, CuMemberSettleExt sourceMemberSettleExt,
                         List<CuMemberBonusRange> cuMemberBonusRangeList, List<AcPickExt> acPickExtList) {
        // 订单会员推荐人
        Long pkParent = sourceMemberSettleExt.getPkParent();
        // 订单会员等级
        int gradeValue = sourceMemberSettleExt.getGradeValue();

        // 找不到父级了或者找到第一个svip直接跳出
        boolean V2Flag = Boolean.TRUE;
        boolean V3Flag = Boolean.TRUE;
        while (true) {
            CuMemberSettleExt targetMemberSettleExt = specialmeberSettleExtMap.get(pkParent);
            if (null == targetMemberSettleExt) {
                // 上面没有推荐人了，直接结束
                break;
            }

            // 法宝券和商品数量一致
            if (gradeValue < targetMemberSettleExt.getGradeValue() && EGrade.MAKER.getValue() == targetMemberSettleExt.getGradeValue() && V2Flag && V3Flag) {
                // 订单会员等级小于推荐人等级 并且 推荐人是 V2 并且 V2 V3 都没有算过
                if (this.handlePick(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                        sourceMemberSettleExt, targetMemberSettleExt, cuMemberBonusRangeList, acPickExtList)) {
                    V2Flag = Boolean.FALSE;
                }
            } else if (gradeValue < targetMemberSettleExt.getGradeValue() && EGrade.VIP.getValue() == targetMemberSettleExt.getGradeValue() && V3Flag) {
                // 订单会员等级小于推荐人等级 并且 推荐人是 V3 并且 V3没有算过
                if (this.handlePick(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                        sourceMemberSettleExt, targetMemberSettleExt, cuMemberBonusRangeList, acPickExtList)) {
                    V3Flag = Boolean.FALSE;
                }
            } else if (gradeValue < targetMemberSettleExt.getGradeValue() && EGrade.S_VIP.getValue() == targetMemberSettleExt.getGradeValue()) {
                // 订单会员等级小于推荐人等级 并且 推荐人是 V4
                if (this.handlePick(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                        sourceMemberSettleExt, targetMemberSettleExt, cuMemberBonusRangeList, acPickExtList)) {
                    break;
                }
            }
            pkParent = targetMemberSettleExt.getPkParent();
            sourceMemberSettleExt = targetMemberSettleExt;
        }
    }

    /**
     * 未使用法宝券处理
     */
    private void notUsePick(Map<Long, CuMemberSettleExt> specialmeberSettleExtMap, Map<String, RangeDTO> rangeDtoMap, BonusConfigDTO bonusConfigDTO, Integer period,
                            Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt, SaOrderItemsExt saOrderItemsExt, CuMemberSettleExt sourceMemberSettleExt,
                            List<CuMemberBonusRange> cuMemberBonusRangeList, List<AcPickExt> acPickExtList) {
        // 订单会员推荐人
        Long pkParent = sourceMemberSettleExt.getPkParent();
        // 订单会员等级
        int gradeValue = sourceMemberSettleExt.getGradeValue();

        // 找不到父级了或者找到第一个svip直接跳出
        boolean V1Flag = Boolean.TRUE;
        boolean V2Flag = Boolean.TRUE;
        boolean V3Flag = Boolean.TRUE;
        while (true) {
            CuMemberSettleExt targetMemberSettleExt = specialmeberSettleExtMap.get(pkParent);
            if (null == targetMemberSettleExt) {
                // 上面没有推荐人了，直接结束
                break;
            }

            // 法宝券和商品数量一致
            if (gradeValue <= targetMemberSettleExt.getGradeValue() && EGrade.YOU_KE.getValue() == targetMemberSettleExt.getGradeValue() && V1Flag && V2Flag && V3Flag) {
                // 订单会员等级小于推荐人等级 并且 推荐人是 V1 并且 V1 V2 V3 都没有算过
                if (this.handlePick(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                        sourceMemberSettleExt, targetMemberSettleExt, cuMemberBonusRangeList, acPickExtList)) {
                    V1Flag = Boolean.FALSE;
                }
            } else if (gradeValue <= targetMemberSettleExt.getGradeValue() && EGrade.MAKER.getValue() == targetMemberSettleExt.getGradeValue() && V2Flag && V3Flag) {
                // 订单会员等级小于推荐人等级 并且 推荐人是 V2 并且 V2 V3 都没有算过
                if (this.handlePick(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                        sourceMemberSettleExt, targetMemberSettleExt, cuMemberBonusRangeList, acPickExtList)) {
                    V2Flag = Boolean.FALSE;
                }
            } else if (gradeValue <= targetMemberSettleExt.getGradeValue() && EGrade.VIP.getValue() == targetMemberSettleExt.getGradeValue() && V3Flag) {
                // 订单会员等级小于推荐人等级 并且 推荐人是 V3 并且 V3没有算过
                if (this.handlePick(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                        sourceMemberSettleExt, targetMemberSettleExt, cuMemberBonusRangeList, acPickExtList)) {
                    V3Flag = Boolean.FALSE;
                }
            } else if (gradeValue <= targetMemberSettleExt.getGradeValue() && EGrade.S_VIP.getValue() == targetMemberSettleExt.getGradeValue()) {
                // 订单会员等级小于推荐人等级 并且 推荐人是 V4
                if (this.handlePick(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt,
                        sourceMemberSettleExt, targetMemberSettleExt, cuMemberBonusRangeList, acPickExtList)) {
                    break;
                }
            }
            pkParent = targetMemberSettleExt.getPkParent();
            sourceMemberSettleExt = targetMemberSettleExt;
        }
    }

    /**
     * 封装法宝券抵扣相关
     */
    private boolean handlePick(Map<String, RangeDTO> rangeDtoMap, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                               SaOrderExt saOrderExt, SaOrderItemsExt saOrderItemsExt, CuMemberSettleExt sourceMemberSettleExt, CuMemberSettleExt targetMemberSettleExt,
                               List<CuMemberBonusRange> cuMemberBonusRangeList, List<AcPickExt> acPickExtList) {
        AcPickExt acPickExt = calculateRangeBonus(rangeDtoMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, saOrderItemsExt, sourceMemberSettleExt,
                targetMemberSettleExt, cuMemberBonusRangeList);
        if (null != acPickExt) {
            acPickExtList.add(acPickExt);
            return true;
        }
        return false;
    }

    /**
     * 计算封装乐学复购特殊级差（法宝券）返回扣除提货法宝券
     *
     * @param rangeDtoMap
     * @param bonusConfigDTO
     * @param period
     * @param cuMemberBonusMap
     * @param saOrderExt
     * @param saOrderItemsExt
     * @param sourceMemberSettleExt
     * @param targetMemberSettleExt
     * @param cuMemberBonusRangeList
     * @return
     */
    private AcPickExt calculateRangeBonus(Map<String, RangeDTO> rangeDtoMap, BonusConfigDTO bonusConfigDTO, Integer period,
                                          Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt, SaOrderItemsExt saOrderItemsExt,
                                          CuMemberSettleExt sourceMemberSettleExt, CuMemberSettleExt targetMemberSettleExt,
                                          List<CuMemberBonusRange> cuMemberBonusRangeList) {
        if (targetMemberSettleExt.getUsableQuantity() != null && targetMemberSettleExt.getUsableQuantity() > 0) {
            // 扣减数量（如果剩余法宝券 大于等于 商品数量，则使用商品数量，否则使用法宝券数量）
            int waresQuantity = targetMemberSettleExt.getUsableQuantity() >= saOrderItemsExt.getWaresQuantity() ? saOrderItemsExt.getWaresQuantity() : targetMemberSettleExt.getUsableQuantity();

            CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
            CuMemberBonusRange cuMemberBonusRange = getCuMemberBonusRange(bonusConfigDTO, saOrderExt, targetMemberSettleExt, cuMemberBonus);
            cuMemberBonusRange.setCalAchieve(saOrderItemsExt.getAchievement());
            cuMemberBonusRange.setCalValue(BigDecimal.ZERO);
            cuMemberBonusRange.setPretaxIncome(ComputeUtil.computeMultiply(BigDecimal.valueOf(waresQuantity),
                    ComputeUtil.computeDivide(targetMemberSettleExt.getRetailPrice(), BigDecimal.valueOf(1))));
            String key = targetMemberSettleExt.getPkSettleCountry().toString() + ERangeType.GRADE.getValue() + targetMemberSettleExt.getPkGrade();
            cuMemberBonusRange.setPkRange(rangeDtoMap.get(key).getPkRange());
            String beforeKey = targetMemberSettleExt.getPkSettleCountry().toString() + ERangeType.GRADE.getValue() + targetMemberSettleExt.getPkGrade();
            cuMemberBonusRange.setPkBeforeRange(rangeDtoMap.get(beforeKey).getPkRange());
            cuMemberBonusRange.setIncomeRatio(ComputeUtil.computeDivide(ComputeUtil.computeMultiply(cuMemberBonusRange.getPretaxIncome(), BigDecimal.valueOf(1)), saOrderExt.getOrderAmount()));
            cuMemberBonusRange.setPkOrderItems(0L);
            // 计算比例
            cuMemberBonusRange.setPkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.REPURCHASE_RANGE_INCOME.getValue()));
            // 收益占比
            BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusRange, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
            xueRangeRemark(saOrderExt, cuMemberBonusRange, sourceMemberSettleExt, targetMemberSettleExt);
            if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusRange.getIncomeStatus()) {
                cuMemberBonus.setRepurRangeIncome(ComputeUtil.computeAdd(cuMemberBonus.getRepurRangeIncome(), cuMemberBonusRange.getPretaxIncome()));
                setPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusRange);
            }
            cuMemberBonusRangeList.add(cuMemberBonusRange);
            targetMemberSettleExt.setUsableQuantity(targetMemberSettleExt.getUsableQuantity() - waresQuantity);
            AcPickExt acPickExt = new AcPickExt();
            acPickExt.setPkId(targetMemberSettleExt.getApPkId());
            acPickExt.setPkMember(targetMemberSettleExt.getPkMember());
            acPickExt.setOrderCode(saOrderExt.getOrderCode());
            acPickExt.setPickType(EPickType.COUPON.getValue());
            acPickExt.setUsedQuantity(waresQuantity);
            acPickExt.setPkBaseConfig(0L);
            acPickExt.setPkDataId(targetMemberSettleExt.getPkDataId());
            return acPickExt;
        }
        return null;
    }

    /**
     * 乐学复购极差，找下一个等级的推荐人
     *
     * @param cuMemberTreeMap
     * @param bonusConfigDTO
     * @param sourceMemberTree
     * @param parentMemberTree
     * @param cuMemberAssessMap
     * @param pkGrade
     * @return
     */
    private CuMemberSettleExt getSpecialRangeCuMemberTree(Map<Long, CuMemberSettleExt> cuMemberTreeMap, BonusConfigDTO bonusConfigDTO,
                                                          CuMemberSettleExt sourceMemberTree, CuMemberSettleExt parentMemberTree,
                                                          Map<Long, CuMemberAssess> cuMemberAssessMap, int pkGrade) {
        if (null == parentMemberTree) {
            return null;
        }
        if (ECategory.NORMAL.getValue() != parentMemberTree.getCategory()
                || EAccountStatus.STOP_INCOME.getValue() == parentMemberTree.getAccountStatus()
                || validatePkBonusItems(bonusConfigDTO, parentMemberTree.getPkSettleCountry(), EBonusItems.REPURCHASE_RANGE_INCOME.getValue())
                || parentMemberTree.getPkGrade() < pkGrade
                || parentMemberTree.getPkGrade() <= sourceMemberTree.getPkGrade()) {
            // 推荐人非正常点位 或 停算收益 或 没有配置该奖项 或 等级小于计算等级 或 等级小于等于下级会员等级，则跳过该推荐人向上继续找
            parentMemberTree = cuMemberTreeMap.get(parentMemberTree.getPkParent());
            if (null == parentMemberTree) {
                return null;
            }
            parentMemberTree = getSpecialRangeCuMemberTree(cuMemberTreeMap, bonusConfigDTO, sourceMemberTree, parentMemberTree, cuMemberAssessMap, pkGrade);
        }
        return parentMemberTree;
    }

    /**
     * 计算复购量碰
     *
     * @param period                  期间
     * @param cuMemberBonusMap        奖金汇总
     * @param cuMemberBonusExpandList 拓展奖奖金明细
     * @param saOrderExt              订单
     * @param touchNum                碰次
     * @param i                       当前碰次
     * @param sourceMemberSettleExt   提供奖金的人
     * @param targetMemberSettleExt   获得奖金的人
     * @param bdGrade                 等级对应的参数
     * @param countryExpandRatio      4-n时计算国家对应的参数
     */
    private void calculateRepurchaseExpandBonusByAchieve(Integer period, Map<Long, CuMemberBonus> weekMemberBonusMap, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                         BonusConfigDTO bonusConfigDTO, Map<String, String> systemConfigMap, List<CuMemberBonusExpand> cuMemberBonusExpandList,
                                                         SaOrderExt saOrderExt, int touchNum, int i, CuMemberSettleExt sourceMemberSettleExt, CuMemberSettleExt targetMemberSettleExt,
                                                         BdGrade bdGrade, BigDecimal countryExpandRatio) {
        // 获取拓展收益奖项ID
        Integer pkBonusItems = getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.CONSUMPTION_EXPANSION_INCOME.getValue());

        // 验证封顶方式 1=日 2=周，若是周的话需要获取 周奖金（首购已经去掉周封顶逻辑，此处周封顶默认0，后续代码可以不需要修改）
        BigDecimal weekRepExpandIncome = BigDecimal.ZERO;
//        if (systemConfigMap.containsKey(targetMemberSettleExt.getPkSettleCountry() + ESystemConfig.EXPAND_CAP_METHOD.getKey())) {
//            String expandCapMethod = systemConfigMap.get(targetMemberSettleExt.getPkSettleCountry() + ESystemConfig.EXPAND_CAP_METHOD.getKey());
//            if (Objects.equals(expandCapMethod, EExpandCapMethod.WEEK_SETTLE.toString()) &&
//                    weekMemberBonusMap.containsKey(targetMemberSettleExt.getPkMember())) {
//                weekRepExpandIncome = weekMemberBonusMap.get(targetMemberSettleExt.getPkMember()).getRepurExpandIncome();
//            }
//        }

        // 国内使用首购比例封顶
        BigDecimal gradeExpandRatio = bdGrade.getRepurchaseRatio();

        if (targetMemberSettleExt.getPkSettleCountry().equals(CountryConstants.CHINA_COUNTRY)) {
            // 中国复购使用首购封顶
            gradeExpandRatio = bdGrade.getExpandRatio();
        }

        // 获取等级封顶值
        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
        // 左右区获取最小的
        BigDecimal calAchieve;
        if (targetMemberSettleExt.getPkSettleCountry().equals(CountryConstants.CHINA_COUNTRY)) {
            calAchieve = ComputeUtil.obtainMinAchieve(targetMemberSettleExt.getABalance(), targetMemberSettleExt.getBBalance());
        } else {
            calAchieve = ComputeUtil.obtainMinAchieve(targetMemberSettleExt.getRepABalance(), targetMemberSettleExt.getRepBBalance());
        }

        CuMemberBonusExpand cuMemberBonusExpand = getCuMemberBonusExpand(saOrderExt, touchNum, i, targetMemberSettleExt, countryExpandRatio, cuMemberBonus, calAchieve, pkBonusItems, BigDecimal.ZERO, bdGrade);
        if (targetMemberSettleExt.getPkSettleCountry().equals(CountryConstants.CHINA_COUNTRY)) {
            targetMemberSettleExt.setABalance(ComputeUtil.computeSubtract(targetMemberSettleExt.getABalance(), calAchieve));
            targetMemberSettleExt.setBBalance(ComputeUtil.computeSubtract(targetMemberSettleExt.getBBalance(), calAchieve));
        } else {
            // 扣减a、b区结余
            targetMemberSettleExt.setRepABalance(ComputeUtil.computeSubtractAbs(targetMemberSettleExt.getRepABalance(), calAchieve));
            targetMemberSettleExt.setRepBBalance(ComputeUtil.computeSubtractAbs(targetMemberSettleExt.getRepBBalance(), calAchieve));
        }

        // 计算收益 先计算出会员最大的收益 -- TODO new 目前看，下面这俩比例计算出来的值一样
        // maxIncome = 业绩 * 等级扩展比例
        BigDecimal maxIncome = ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getCalAchieve(), gradeExpandRatio);
        // actualIncome = 业绩 * 等级扩展比例
        BigDecimal actualIncome = ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getCalAchieve(), countryExpandRatio);
//        log.info("复购. maxIncome: {}, gradeExpandRatio: {}; actualIncome: {}, countryExpandRatio: {}", maxIncome, gradeExpandRatio, actualIncome, countryExpandRatio);

        // 获取等级对应的封顶值（累计复购扩展 + 当前等级对应订单的最大收益）
        BigDecimal expandIncome = ComputeUtil.computeAdd(ComputeUtil.computeAdd(cuMemberBonus.getRepurExpandIncome(), actualIncome), weekRepExpandIncome);

        if (targetMemberSettleExt.getPkSettleCountry().equals(CountryConstants.CHINA_COUNTRY)) {
            // 获取等级对应的封顶值（中国重新赋值封顶值）（累计扩展 + 累计复购扩展 + 当前等级对应订单的最大收益）
            expandIncome = ComputeUtil.computeAdd(ComputeUtil.computeAdd(cuMemberBonus.getExpandIncome(), expandIncome), weekRepExpandIncome);
            // 判断收益 是否超过封顶值，超过的话变为封顶值
            // 判断是否烧伤，判断原奖金是否>=封顶值,奖金到了就是烧伤
            // 验证会员状态 封停状态跟冻结都正常计算奖金，封停的账号发放的时候奖金发放为0，冻结的账号正常发放，不能登录
            packageCuMemberBonusExpand(cuMemberBonusExpand, cuMemberBonus, bdGrade.getExpandCapping(), maxIncome, actualIncome);

            if (ComputeUtil.compareValue(ComputeUtil.computeAdd(cuMemberBonus.getExpandIncome(), cuMemberBonus.getRepurExpandIncome()), bdGrade.getExpandCapping())) {
                // 拓展收益 累加 复购收益 >= 等级封顶值
                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusExpand.getIncomeStatus()) {
                    // 状态为烧伤
                    // TODO new V3 V4 没有烧伤，改为延缓发放
                    if (EGrade.VIP.getValue() == bdGrade.getGradeValue()
                            || EGrade.S_VIP.getValue() == bdGrade.getGradeValue()) {
                        cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.DELAY_GRANT.getValue());
                    } else {
                        cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
                    }
                }
                expandIncome = ComputeUtil.computeSubtract(bdGrade.getExpandCapping(), ComputeUtil.computeAdd(cuMemberBonus.getExpandIncome(), cuMemberBonus.getRepurExpandIncome()));
            } else if (ComputeUtil.compareGreaterThan(expandIncome, bdGrade.getExpandCapping())) {
                BigDecimal realIncome = ComputeUtil.computeSubtract(ComputeUtil.computeSubtract(bdGrade.getExpandCapping(), weekRepExpandIncome), ComputeUtil.computeAdd(cuMemberBonus.getExpandIncome(), cuMemberBonus.getRepurExpandIncome()));
                // 存在一半烧伤一半正常的值，拆2条
                // 拓展明细表 进行修改
                packageCuMemberBonusExpand(cuMemberBonusExpand, cuMemberBonus, bdGrade.getExpandCapping(), realIncome, realIncome);

                CuMemberBonusExpand fireCuMemberBonusExpand = BeanUtil.copyProperties(cuMemberBonusExpand, CuMemberBonusExpand.class);
                BigDecimal fireIncome = ComputeUtil.computeSubtract(maxIncome, realIncome);
                if (EBonusIncomeStatus.NORMAL.getValue() == fireCuMemberBonusExpand.getIncomeStatus()) {
                    // TODO new V3 V4 没有烧伤，改为延缓发放
                    if (EGrade.VIP.getValue() == bdGrade.getGradeValue()
                            || EGrade.S_VIP.getValue() == bdGrade.getGradeValue()) {
                        fireCuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.DELAY_GRANT.getValue());
                    } else {
                        fireCuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
                    }
                }
                packageCuMemberBonusExpand(fireCuMemberBonusExpand, cuMemberBonus, bdGrade.getExpandCapping(), fireIncome, fireIncome);
                // 收益占比
                setBonusDetailDeduct(bonusConfigDTO, fireCuMemberBonusExpand, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                expandRemark(saOrderExt, fireCuMemberBonusExpand, sourceMemberSettleExt, targetMemberSettleExt);
                cuMemberBonusExpandList.add(fireCuMemberBonusExpand);
                // 拓展收益取封顶最大值
                expandIncome = ComputeUtil.computeSubtract(bdGrade.getExpandCapping(), weekRepExpandIncome);
            }
        }

        // 收益占比
        BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusExpand, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
        repurchaseExpandRemark(saOrderExt, cuMemberBonusExpand, sourceMemberSettleExt, targetMemberSettleExt);

        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusExpand.getIncomeStatus()) {
            cuMemberBonus.setRepurExpandIncome(ComputeUtil.computeSubtract(expandIncome, cuMemberBonus.getExpandIncome()));
            setPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusExpand);
        }
        cuMemberBonusExpandList.add(cuMemberBonusExpand);
    }


    private CuMemberBonusRange getCuMemberBonusRange(BonusConfigDTO bonusConfigDTO, SaOrderExt saOrderExt, CuMemberSettleExt cuMemberSettleExt, CuMemberBonus cuMemberBonus) {
        CuMemberBonusRange cuMemberBonusRange = CuMemberBonusRange.builder()
                .pkOrder(saOrderExt.getPkId())
                .pkBonus(cuMemberBonus.getPkId())
                .pkBonusItems(getPkBonusItems(bonusConfigDTO, cuMemberSettleExt.getPkSettleCountry(), EBonusItems.REPURCHASE_RANGE_INCOME.getValue()))
                // 正常还是烧伤
                .incomeStatus(cuMemberSettleExt.getIncomeStatus())
                .calType(ECalType.VALUE.getValue())
                .calAchieve(saOrderExt.getOrderAmount())
                .calValue(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .build();
        cuMemberBonusRange.setPkCountry(cuMemberSettleExt.getPkSettleCountry());
        cuMemberBonusRange.setPkCreator(MagicNumberConstants.PK_ADMIN);
        return cuMemberBonusRange;
    }

    /**
     * 处理复购延缓
     */
    public void handleRepExpandDelay(List<CuMemberBonusExpand> cuMemberBonusExpandList, Integer period, BonusRecordDetailVO bonusRecordDetailVO) {
        // key：会员ID，value：会员延缓发放明细
        Map<Long, CuMemberBonusDelayDetail> bonusDelayDetailMap;
        if (null == bonusRecordDetailVO.getBonusDelayDetailAddMap()) {
            bonusDelayDetailMap = new HashMap<>();
            bonusRecordDetailVO.setBonusDelayDetailAddMap(bonusDelayDetailMap);
        } else {
            bonusDelayDetailMap = bonusRecordDetailVO.getBonusDelayDetailAddMap();
        }

        cuMemberBonusExpandList.forEach(bonusExpand -> {
            if (EBonusIncomeStatus.DELAY_GRANT.getValue() == bonusExpand.getIncomeStatus()) {
                // 延缓发放的才处理
                CuMemberBonusDelayDetail bonusDelayDetail = bonusDelayDetailMap.get(bonusExpand.getPkMember());
                if (null == bonusDelayDetail) {
                    // 延缓发放不存在，创建新的计算比例等都是一样的
                    bonusDelayDetail = CuMemberBonusDelayDetail.builder()
                            .pkMember(bonusExpand.getPkMember())
                            .period(period)
                            .repCalType(bonusExpand.getCalType())
                            .repCalValue(bonusExpand.getCalValue())
                            .repCalAchieve(BigDecimal.ZERO)
                            .repPretaxIncome(BigDecimal.ZERO)
                            .firCalAchieve(BigDecimal.ZERO)
                            .firPretaxIncome(BigDecimal.ZERO)
                            .beforePretaxIncome(bonusExpand.getUnGrantIncome())
                            .type(EInfusingWaterType.ADD.getValue())
                            .pkBonus(bonusExpand.getPkMember())
                            .expandCapping(bonusExpand.getDelayExpandCapping())
                            .build();
                    bonusDelayDetail.setPkCountry(bonusExpand.getPkCountry());
                    bonusDelayDetail.setPkCreator(bonusExpand.getPkCreator());
                    bonusDelayDetailMap.put(bonusExpand.getPkMember(), bonusDelayDetail);
                }
                // 累加计算业绩、税前收益
                bonusDelayDetail.setRepCalAchieve(bonusDelayDetail.getRepCalAchieve().add(bonusExpand.getCalAchieve()));
                bonusDelayDetail.setRepPretaxIncome(bonusDelayDetail.getRepPretaxIncome().add(bonusExpand.getPretaxIncome()));
            }
        });
    }

    /**
     * 处理首购延缓
     */
    public void handleFirExpandDelay(List<CuMemberBonusExpand> cuMemberBonusExpandList, Integer period, BonusRecordDetailVO bonusRecordDetailVO) {
        // key：会员ID，value：会员延缓发放明细
        Map<Long, CuMemberBonusDelayDetail> bonusDelayDetailMap;
        if (null == bonusRecordDetailVO.getBonusDelayDetailAddMap()) {
            bonusDelayDetailMap = new HashMap<>();
            bonusRecordDetailVO.setBonusDelayDetailAddMap(bonusDelayDetailMap);
        } else {
            bonusDelayDetailMap = bonusRecordDetailVO.getBonusDelayDetailAddMap();
        }

        cuMemberBonusExpandList.forEach(bonusExpand -> {
            if (EBonusIncomeStatus.DELAY_GRANT.getValue() == bonusExpand.getIncomeStatus()) {
                // 延缓发放的才处理
                CuMemberBonusDelayDetail bonusDelayDetail = bonusDelayDetailMap.get(bonusExpand.getPkMember());
                if (null == bonusDelayDetail) {
                    // 延缓发放不存在，创建新的计算比例等都是一样的
                    bonusDelayDetail = CuMemberBonusDelayDetail.builder()
                            .pkMember(bonusExpand.getPkMember())
                            .period(period)
                            .firCalType(bonusExpand.getCalType())
                            .firCalValue(bonusExpand.getCalValue())
                            .firCalAchieve(BigDecimal.ZERO)
                            .firPretaxIncome(BigDecimal.ZERO)
                            .repCalAchieve(BigDecimal.ZERO)
                            .repPretaxIncome(BigDecimal.ZERO)
                            .beforePretaxIncome(bonusExpand.getUnGrantIncome())
                            .type(EInfusingWaterType.ADD.getValue())
                            .pkBonus(bonusExpand.getPkMember())
                            .expandCapping(bonusExpand.getDelayExpandCapping())
                            .build();
                    bonusDelayDetail.setPkCountry(bonusExpand.getPkCountry());
                    bonusDelayDetail.setPkCreator(bonusExpand.getPkCreator());
                    bonusDelayDetailMap.put(bonusExpand.getPkMember(), bonusDelayDetail);
                } else {
                    if (null == bonusDelayDetail.getFirCalType()) {
                        bonusDelayDetail.setFirCalType(bonusExpand.getCalType());
                        bonusDelayDetail.setFirCalValue(bonusExpand.getCalValue());
                    }
                }
                // 累加计算业绩、税前收益
                bonusDelayDetail.setFirCalAchieve(bonusDelayDetail.getFirCalAchieve().add(bonusExpand.getCalAchieve()));
                bonusDelayDetail.setFirPretaxIncome(bonusDelayDetail.getFirPretaxIncome().add(bonusExpand.getPretaxIncome()));
            }
        });
    }

}
