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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.hzs.bonus.bonus.service.ICuMemberBonusDelayService;
import com.hzs.bonus.bonus.vo.BonusRecordDetailVO;
import com.hzs.common.core.config.BdConfig;
import com.hzs.common.core.constant.*;
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.core.utils.DateUtils;
import com.hzs.common.domain.bonus.BdBonusDeduct;
import com.hzs.common.domain.bonus.BdBonusService;
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.order.SaOrder;
import com.hzs.common.domain.system.config.BdAwards;
import com.hzs.common.domain.system.config.BdGrade;
import com.hzs.system.config.IGradeServiceApi;
import com.hzs.system.config.dto.*;
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.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 计算首购的奖金处理类
 */
@Slf4j
@Component
public class BonusSettleFirstPurchaseHandle extends BonusSettleHandle {

    @DubboReference
    IGradeServiceApi iGradeServiceApi;

    @Autowired
    private ICuMemberBonusDelayService iCuMemberBonusDelayService;

    /**
     * @param settleTableName      结算表
     * @param bonusConfigDTO       参数
     * @param systemConfigMap      系统参数
     * @param firPurchaseOrderList 首单
     * @Description: 计算直推奖
     * @return: void
     */
    List<CuMemberBonusPush> calculateRecommendBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, BonusConfigDTO bonusConfigDTO,
                                                    Map<String, String> systemConfigMap, List<SaOrderExt> firPurchaseOrderList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, Map<String, BdAwards> awardsMap) {
        // 查询 各个国家 3单循环 4单循环的配置值
        // 获得会员的轮、次，按照订单时间进行
        // 根据订单获取轮次，要回写
        List<CuMemberSettleExt> cuMemberSettleExtList = iCuMemberTreeService.batchQueryMemberSettleBySaOrder(settleTableName, firPurchaseOrderList);
        getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
        // 推荐奖明细
        List<CuMemberBonusPush> cuMemberBonusPushList = new ArrayList<>();
        Set<Integer> pkCountrySet = firPurchaseOrderList.stream().distinct().map(SaOrderExt::getPkCountry).collect(Collectors.toSet());
        // 根据国家拿出对应的等级
        Map<Integer, List<GradeDTO>> gradeDtoMap = iGradeServiceApi.queryCountryGradeConfigByCondition(pkCountrySet).getData();
        // 等级对应的业绩
        for (SaOrderExt saOrderExt : firPurchaseOrderList) {
            List<GradeDTO> gradeList = gradeDtoMap.get(saOrderExt.getPkCountry());
            CuMemberBonusPush cuMemberBonusPush = calculatePushBonusOne(cuMemberSettleExtMap, bonusConfigDTO, systemConfigMap, period, cuMemberBonusMap, saOrderExt, awardsMap, gradeList);
            if (cuMemberBonusPush != null) {
                cuMemberBonusPushList.add(cuMemberBonusPush);
            }
        }

        // TODO new 乐学直推级差收益，需要按新逻辑修改（级差等级4个，封顶上限修改）
        // V2订单6000，最多发3000，V1拿400，V4最多拿3000，前面等级没拿，后面等级就多拿一份
        List<SaOrderExt> specialOrderList = new ArrayList<>();
        firPurchaseOrderList.forEach(saOrderExt -> {
            if (EOrderType.SPECIAL_REGISTER_ORDER.getValue() == saOrderExt.getOrderType() ||
                    EOrderType.SPECIAL_UPGRADE_ORDER.getValue() == saOrderExt.getOrderType()) {
                specialOrderList.add(saOrderExt);
            }
        });
        if (specialOrderList.size() > 0) {
            Set<Long> memberSet = new HashSet<>();
            specialOrderList.forEach(saOrderExt -> memberSet.add(saOrderExt.getPkMember()));
            cuMemberSettleExtList = iCuMemberTreeService.batchQuerySpecialCuMemberSettleParent(settleTableName, memberSet);
            getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
            // 计算奖金
            for (SaOrderExt saOrderExt : specialOrderList) {
                // 订单能发放总奖金
                BigDecimal maxBonus;
                // 根据金额验证最大金额
                if (ComputeUtil.compareValue(saOrderExt.getOrderAmount(), MagicNumberConstants.V4_AMOUNT)) {
                    // 订单金额大于 128000，封顶奖金 43000
                    maxBonus = MagicNumberConstants.V4_V4_BONUS;
                } else if (ComputeUtil.compareValue(saOrderExt.getOrderAmount(), MagicNumberConstants.V3_AMOUNT)) {
                    // 订单金额大于 36000，封顶奖金 18000
                    maxBonus = MagicNumberConstants.V4_V3_BONUS;
                } else if (ComputeUtil.compareValue(saOrderExt.getOrderAmount(), MagicNumberConstants.V2_AMOUNT)) {
                    // 订单金额大于 6000，封顶奖金 3000
                    maxBonus = MagicNumberConstants.V4_V2_BONUS;
                } else if (ComputeUtil.compareValue(saOrderExt.getOrderAmount(), MagicNumberConstants.V1_AMOUNT)) {
                    // 订单金额大于 2000，封顶奖金 1000
                    maxBonus = MagicNumberConstants.V4_V1_BONUS;
                } else {
                    // 订单金额小于 2000，没有奖金
                    maxBonus = BigDecimal.ZERO;
                }

                CuMemberSettleExt sourceSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
                Long pkParent = sourceSettleExt.getPkParent();
                // 已发放奖金
                BigDecimal grantBonus = BigDecimal.ZERO;
                while (ComputeUtil.compareGreaterThan(maxBonus, grantBonus)) {
                    CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(pkParent);
                    if (targetMemberSettleExt == null) {
                        break;
                    }
                    // 死点没有奖金
                    if (ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                            || EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()
                            || validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.DIRECT_INCOME.getValue())) {
                        // 非正常点位 或 停算收益 或 没有这个奖项，则直接跳过当前人
                        pkParent = targetMemberSettleExt.getPkParent();
                        continue;
                    }
                    // 初始化会员奖金汇总
                    CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
                    // 直推奖金明细
                    int pkBonusItem = getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.DIRECT_INCOME.getValue());
                    CuMemberBonusPush cuMemberBonusPush = getCuMemberBonusPush(saOrderExt, targetMemberSettleExt, cuMemberBonus, pkBonusItem);
                    // 不算轮次
                    cuMemberBonusPush.setCalType(ECalType.VALUE.getValue());
                    cuMemberBonusPush.setRound(-1);
                    cuMemberBonusPush.setSecond(0);
                    // 值
                    cuMemberBonusPush.setCalValue(BigDecimal.ZERO);
                    BigDecimal pretaxIncome;
                    // 验证等级，根据等级给奖金
                    if (ComputeUtil.compareValue(saOrderExt.getOrderAmount(), MagicNumberConstants.V4_AMOUNT)) {
                        // 订单金额 128000，V4推拿43000，V3推拿10800，V2推拿1800，V1推拿400
                        pretaxIncome = computePushRangeBonus(targetMemberSettleExt, MagicNumberConstants.V4_V4_BONUS, MagicNumberConstants.V3_V4_BONUS, MagicNumberConstants.V2_V4_BONUS, MagicNumberConstants.V1_V_BONUS);
                    } else if (ComputeUtil.compareValue(saOrderExt.getOrderAmount(), MagicNumberConstants.V3_AMOUNT)) {
                        // 订单金额 36000，V4推拿18000，V3推拿10800，V2推拿1800，V1推拿400
                        pretaxIncome = computePushRangeBonus(targetMemberSettleExt, MagicNumberConstants.V4_V3_BONUS, MagicNumberConstants.V3_V3_BONUS, MagicNumberConstants.V2_V3_BONUS, MagicNumberConstants.V1_V_BONUS);
                    } else if (ComputeUtil.compareValue(saOrderExt.getOrderAmount(), MagicNumberConstants.V2_AMOUNT)) {
                        // 订单金额 6000，V4推拿3000，V3推拿2400，V2推拿1800，V1推拿400
                        pretaxIncome = computePushRangeBonus(targetMemberSettleExt, MagicNumberConstants.V4_V2_BONUS, MagicNumberConstants.V3_V2_BONUS, MagicNumberConstants.V2_V2_BONUS, MagicNumberConstants.V1_V_BONUS);
                    } else {
                        // 订单金额 2000，V4推拿1000，V3推拿800，V2推拿600，V1推拿400
                        pretaxIncome = computePushRangeBonus(targetMemberSettleExt, MagicNumberConstants.V4_V1_BONUS, MagicNumberConstants.V3_V1_BONUS, MagicNumberConstants.V2_V1_BONUS, MagicNumberConstants.V1_V_BONUS);
                    }
                    pretaxIncome = ComputeUtil.computeSubtract(pretaxIncome, grantBonus);
                    if (!ComputeUtil.compareValue(pretaxIncome)) {
                        pkParent = targetMemberSettleExt.getPkParent();
                        continue;
                    }
                    grantBonus = ComputeUtil.computeAdd(grantBonus, pretaxIncome);
                    cuMemberBonusPush.setPretaxIncome(pretaxIncome);
                    cuMemberBonusPush.setRealIncome(pretaxIncome);
                    cuMemberBonusPush.setIncomeTax(BigDecimal.ZERO);

                    // TODO new 需要扣除20%
                    BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusPush, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                    if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusPush.getIncomeStatus()) {
                        cuMemberBonus.setGlobalPoints(ComputeUtil.computeAdd(cuMemberBonus.getGlobalPoints(), cuMemberBonusPush.getPretaxIncome()));

                        // 实发收益总计
//                        BigDecimal realIncome = ReflectUtils.invokeGetter(cuMemberBonusPush, BonusFieldConstants.REAL_INCOME);
//                        cuMemberBonus.setRealIncomeTotal(ComputeUtil.computeAdd(cuMemberBonus.getRealIncomeTotal(), realIncome));

                        // TODO new 首购实发小计、实发收益总计，比原来多累计到首购实发小计
                        setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusPush);
                    }
                    cuMemberBonusPush.setRemark(String.format(BonusMsgConstants.RECOMMEND_SPECIAL_DIRECT, saOrderExt.getOrderCode(),
                            sourceSettleExt.getMemberCode() + sourceSettleExt.getMemberName(),
                            targetMemberSettleExt.getMemberCode() + targetMemberSettleExt.getMemberName(),
                            cuMemberBonusPush.getRealIncome()));

                    cuMemberBonusPushList.add(cuMemberBonusPush);
                    pkParent = targetMemberSettleExt.getPkParent();
                }
            }
        }
        return cuMemberBonusPushList;
    }

    /**
     * 计算直推奖金
     */
    private BigDecimal computePushRangeBonus(CuMemberSettleExt targetMemberSettleExt,
                                             BigDecimal V4Bonus, BigDecimal V3Bonus,
                                             BigDecimal V2Bonus, BigDecimal V1Bonus) {
        BigDecimal pretaxIncome;
        if (targetMemberSettleExt.getGradeValue() == EGrade.S_VIP.getValue()) {
            pretaxIncome = V4Bonus;
        } else if (targetMemberSettleExt.getGradeValue() == EGrade.VIP.getValue()) {
            pretaxIncome = V3Bonus;
        } else if (targetMemberSettleExt.getGradeValue() == EGrade.MAKER.getValue()) {
            pretaxIncome = V2Bonus;
        } else {
            pretaxIncome = V1Bonus;
        }
        return pretaxIncome;
    }


    /**
     * 计算某条订单的推荐奖金
     *
     * @return: void
     */
    CuMemberBonusPush calculatePushBonusOne(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, Map<String, String> systemConfigMap, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt, Map<String, BdAwards> awardsMap, List<GradeDTO> gradeList) {
        CuMemberSettleExt sourceSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
        if (sourceSettleExt == null) {
            return null;
        }
        // 统计注册、升级金额和业绩
        setCuMemberAchieve(saOrderExt, cuMemberSettleExtMap, bonusConfigDTO);
        // 验证订单类型，订单类型是 三方订单的 直推从分享种获取
        // 获取轮次
        CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkReference());
        if (targetMemberSettleExt == null) {
            return null;
        }
        // 死点 或 停算收益 没有奖金
        if (ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                || EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()) {
            return null;
        }
        // 当前国家是否有该奖项
        if (validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.DIRECT_INCOME.getValue())) {
            return null;
        }

        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);

        // 直推奖金明细
        int pkBonusItem = getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.DIRECT_INCOME.getValue());
        CuMemberBonusPush cuMemberBonusPush = getCuMemberBonusPush(saOrderExt, targetMemberSettleExt, cuMemberBonus, pkBonusItem);
        // 扣项
        if (Objects.equals(EOrderType.UPGRADE_ORDER.getValue(), saOrderExt.getOrderType())
                || Objects.equals(EOrderType.SPECIAL_UPGRADE_ORDER.getValue(), saOrderExt.getOrderType())) {
            String value = systemConfigMap.get(targetMemberSettleExt.getPkSettleCountry() + EnumsKeyConstants.BONUS_UPGRADE_TYPE);
            // 只计算固定值，不进入三单（系统参数 -> 直推配置，不纳入循环下处理
            if (Objects.equals(EUpgradeIncomeType.FIXED_VALUE.getValue(), value)) {
                // 分比例跟固定值
                BonusDifferenceDTO bonusDifferenceDTO = bonusConfigDTO.getBonusDifferenceDtoMap().get(targetMemberSettleExt.getPkSettleCountry());
                // 不算轮次
                cuMemberBonusPush.setCalType(bonusDifferenceDTO.getCalType());
                cuMemberBonusPush.setRound(-1);
                cuMemberBonusPush.setSecond(0);
                // 值
                if (ECalType.VALUE.getValue() == bonusDifferenceDTO.getCalType()) {
                    cuMemberBonusPush.setCalValue(BigDecimal.ZERO);
                    cuMemberBonusPush.setPretaxIncome(bonusDifferenceDTO.getRewardValue());
                } else {
                    cuMemberBonusPush.setCalValue(bonusDifferenceDTO.getRewardValue());
                    cuMemberBonusPush.setPretaxIncome(ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), bonusDifferenceDTO.getRewardValue()));
                }
                setBonusPushIncome(cuMemberSettleExtMap, bonusConfigDTO, saOrderExt, cuMemberBonus, cuMemberBonusPush);
                return cuMemberBonusPush;
            }
        }

        // 直推循环配置（第几单 给多少 比例）
        Map<String, BonusDirectLoopDTO> bonusDirectLoopDtoMap = bonusConfigDTO.getBonusDirectLoopDtoMap();
        // TODO new 直推奖励配置（目前应该不需要，之前配置的是区代、市代）
        Map<String, BonusDirectDTO> bonusDirectDtoMap = bonusConfigDTO.getBonusDirectDtoMap();
        // 根据会员等级获取，等级对应的参数
        // 判断轮次是否满足循环最后一个，最后一个需要重置，增加轮次，获取循环方式
        // 直推方式（1=三单循环 2=四单循环）
        String recommendType = systemConfigMap.get(targetMemberSettleExt.getPkSettleCountry() + EnumsKeyConstants.BONUS_RECOMMEND_TYPE);
        // 固定值 验证是否推荐的是固定值
        String memberCountryKey = getMemberCountryKey(awardsMap, sourceSettleExt, new HashMap<>());
        BonusDirectDTO bonusDirectDTO = bonusDirectDtoMap.get(memberCountryKey);
        // 现在已经是第三单，取三单最小
        // 验证是不是固定值，固定值直接取比例或者值
        if (bonusDirectDTO != null && ECalType.VALUE.getValue() == bonusDirectDTO.getCalType()) {
            cuMemberBonusPush.setCalType(bonusDirectDTO.getCalType());
            // 值
            cuMemberBonusPush.setCalValue(BigDecimal.ZERO);
            cuMemberBonusPush.setPretaxIncome(bonusDirectDTO.getBonusValue());
        } else {
            // 三单循环
            BonusDirectLoopDTO bonusDirectLoopDTO = bonusDirectLoopDtoMap.get(targetMemberSettleExt.getPkSettleCountry().toString() + recommendType + targetMemberSettleExt.getPkGrade());
            if (bonusDirectLoopDTO == null) {
                if (bonusDirectDTO != null) {
                    cuMemberBonusPush.setCalValue(bonusDirectDTO.getBonusValue());
                } else {
                    return null;
                }
            } else if (targetMemberSettleExt.getSecond() == 1) {
                cuMemberBonusPush.setCalValue(bonusDirectLoopDTO.getFirstOrder());
            } else if (targetMemberSettleExt.getSecond() == 2) {
                cuMemberBonusPush.setCalValue(bonusDirectLoopDTO.getSecondOrder());
            } else if (targetMemberSettleExt.getSecond() == 3) {
                cuMemberBonusPush.setCalValue(bonusDirectLoopDTO.getThirdOrder());
            } else {
                cuMemberBonusPush.setCalValue(bonusDirectLoopDTO.getFourthOrder());
            }
            // 直接计算奖金 业绩 * 计算值，判断是否有扣项
            // 获取等级对应的业绩
            BigDecimal orderAchieve = saOrderExt.getOrderAchieve();
            // TODO new 乐学处理直接使用订单业绩，不跟等级业绩走
//            // 获得升级方式
//            String value = systemConfigMap.get(targetMemberSettleExt.getPkSettleCountry() + ESystemConfig.UPGRADE_WAY.getKey());
//            if (Objects.equals(Integer.toString(EUpgradeWay.COVER.getValue()), value) && CollectionUtil.isNotEmpty(gradeList)) {
//                for (GradeDTO gradeDTO : gradeList) {
//                    if (validateGradeByAchieve(saOrderExt.getOrderAmount(), saOrderExt.getOrderAchieve(), gradeDTO)) {
//                        orderAchieve = gradeDTO.getStartValue();
//                        break;
//                    }
//                }
//            }
            cuMemberBonusPush.setCalAchieve(orderAchieve);
            cuMemberBonusPush.setPretaxIncome(ComputeUtil.computeBonusMultiply(orderAchieve, cuMemberBonusPush.getCalValue()));
        }
        boolean roundEnd = Objects.equals(ERecommendType.THREE_LOOP.getValue(), recommendType) && targetMemberSettleExt.getSecond() == 3;
        if (!roundEnd) {
            roundEnd = Objects.equals(ERecommendType.FOUR_LOOP.getValue(), recommendType) && targetMemberSettleExt.getSecond() == 4;
        }
        // 记录最小值，前面的值 > 后面的值
        if (ComputeUtil.compareValue(targetMemberSettleExt.getMinAchieve(), cuMemberBonusPush.getCalAchieve()) ||
                ComputeUtil.compareEqual(targetMemberSettleExt.getMinAchieve(), BigDecimal.ZERO)) {
            targetMemberSettleExt.setMinAchieve(cuMemberBonusPush.getCalAchieve());
        }
        if (roundEnd) {
            cuMemberBonusPush.setCalAchieve(targetMemberSettleExt.getMinAchieve());
            cuMemberBonusPush.setPretaxIncome(ComputeUtil.computeBonusMultiply(targetMemberSettleExt.getMinAchieve(), cuMemberBonusPush.getCalValue()));
            reductionMemberSettle(targetMemberSettleExt);
        }
        setBonusPushIncome(cuMemberSettleExtMap, bonusConfigDTO, saOrderExt, cuMemberBonus, cuMemberBonusPush);
        targetMemberSettleExt.setSecond(targetMemberSettleExt.getSecond() + 1);
        return cuMemberBonusPush;
    }

    /**
     * 设置奖金扣项以及直推备注
     */
    void setBonusPushIncome(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, SaOrderExt saOrderExt, CuMemberBonus cuMemberBonus, CuMemberBonusPush cuMemberBonusPush) {
        // 奖金扣项
        BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusPush, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
        recommendRemark(saOrderExt, cuMemberBonusPush, cuMemberSettleExtMap);
        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusPush.getIncomeStatus()) {
            cuMemberBonus.setDirectIncome(ComputeUtil.computeAdd(cuMemberBonus.getDirectIncome(), cuMemberBonusPush.getPretaxIncome()));
            setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusPush);
        }
    }

    CuMemberBonusPush getCuMemberBonusPush(SaOrderExt saOrderExt, CuMemberSettleExt cuMemberSettleExt, CuMemberBonus cuMemberBonus, Integer pkBonusItems) {
        CuMemberBonusPush cuMemberBonusPush = CuMemberBonusPush.builder()
                .pkOrder(saOrderExt.getPkId())
                .pkBonus(cuMemberBonus.getPkId())
                .pkBonusItems(pkBonusItems)
                // 正常还是烧伤
                .incomeStatus(cuMemberSettleExt.getIncomeStatus())
                .calType(ECalType.RATIO.getValue())
                .calAchieve(saOrderExt.getOrderAchieve())
                .pretaxIncome(BigDecimal.ZERO)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .round(cuMemberSettleExt.getRound())
                .second(cuMemberSettleExt.getSecond())
                .build();
        cuMemberBonusPush.setPkCountry(cuMemberSettleExt.getPkSettleCountry());
        cuMemberBonusPush.setPkCreator(MagicNumberConstants.PK_ADMIN);
        if (EExpireStatus.TERMINATED.getValue() == cuMemberSettleExt.getExpireStatus()) {
            cuMemberBonusPush.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
        }
        return cuMemberBonusPush;
    }

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

        // 获取复购考核结果
        List<CuMemberSettleExt> queryMemberList = new ArrayList<>();
        memberSettleMap.forEach((key, value) -> queryMemberList.addAll(value));
        Map<Long, CuMemberAssess> cuMemberAssessMap = getLongCuMemberAssessMap(settleDate, queryMemberList);

        for (SaOrderExt saOrderExt : firPurchaseOrderList) {
            // 所有需要计算的父节点，只计算新增
            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 = calculateExpandBonusOne(riskControlMap, cuMemberAssessMap, settleTableName, cuMemberSettleExtMap, bonusConfigDTO,
                    systemConfigMap, period, weekMemberBonusMap, cuMemberBonusMap, cuMemberSettleExtList, saOrderExt, true, addTouch, expandRatio, expandNumber);
            if (expandList.size() > 0) {
                cuMemberBonusExpandList.addAll(expandList);
            }
        }
        // 根据订单往上穿业绩，只计算新增
        return cuMemberBonusExpandList;
    }

    /**
     * 计算首购量奖（拓展收益）
     *
     * @return
     */
    List<CuMemberBonusExpand> calculateExpandBonusOne(Map<Long, CuMemberRiskControl> riskControlMap, Map<Long, CuMemberAssess> cuMemberAssessMap, String settleTableName,
                                                      Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, Map<String, String> systemConfigMap,
                                                      Integer period, Map<Long, CuMemberBonus> weekMemberBonusMap, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                      List<CuMemberSettleExt> cuMemberSettleExtList, SaOrderExt saOrderExt, boolean flag,
                                                      BigDecimal addTouch, BigDecimal expandRatio, Integer expandNumber) {
        List<CuMemberBonusExpand> cuMemberBonusExpandList = new ArrayList<>();
        if (CollectionUtil.isEmpty(cuMemberSettleExtList)) {
            return cuMemberBonusExpandList;
        }

        // 先计算新增，根据新增计算碰次
        // 先进行初始化所有的安置人，存储需要修改的值,cuMemberSettleExtMap最终修改的
        if (flag) {
            // 日结传入的true，秒结传入的false
            getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
        }

        Map<Integer, BonusExpandDTO> bdBonusExpandMap = bonusConfigDTO.getBonusExpandMap();
        // 先准备值，准备好值后，开始计算，计算碰次
        int touchNum = calculateTouchNum(riskControlMap, cuMemberAssessMap, cuMemberSettleExtMap, saOrderExt, cuMemberSettleExtList, bonusConfigDTO);
        // 有碰次，计算拓展奖
        if (touchNum > 0) {
            // 判断是否>3 是否需要启动4-N，4-N的参数按照伞上各安置人结算国家进行获取
            // 先计算前3碰
            int startTouch = touchNum;
            // 后面碰次
            int endTouch = 0;
            // 获取拓展配置（一般情况，拓展次数 = 3，拓展比例 = 26%
            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.EXPANSION_INCOME.getValue())) {
                        continue;
                    }
                    // 判断左右区是否有值，找到有值的就是有碰次，碰完左区或右区肯定有变为0的
                    if (ComputeUtil.compareValue(targetMemberSettleExt.getABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getBBalance())) {
                        // 根据会员等级获取对应的配置
                        BdGrade bdGrade = getGradeExpand(bonusConfigDTO, targetMemberSettleExt);
                        BigDecimal countryExpandRatio = bdGrade.getExpandRatio();
                        // 计算量碰
                        calculateExpandBonusByAchieve(riskControlMap, period, weekMemberBonusMap, cuMemberBonusMap, bonusConfigDTO, systemConfigMap, cuMemberBonusExpandList,
                                saOrderExt, touchNum, i, sourceMemberSettleExt, targetMemberSettleExt, bdGrade, countryExpandRatio, BigDecimal.ZERO, cuMemberAssessMap);
                        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.EXPANSION_INCOME.getValue())) {
                            continue;
                        }
                        // 判断左右区是否有值，找到有值的就是有碰次，碰完左区或右区肯定有变为0的
                        if (ComputeUtil.compareValue(targetMemberSettleExt.getABalance()) && ComputeUtil.compareValue(targetMemberSettleExt.getBBalance())) {
                            // 根据会员等级获取对应的拓展配置
                            BdGrade bdGrade = getGradeExpand(bonusConfigDTO, targetMemberSettleExt);
                            // 获取实际拓展比例（拓展配置计算出来的单个碰次 和 等级配置上限，哪个小取哪个）
                            BigDecimal countryExpandRatio = getCountryExpand(bonusConfigDTO, targetMemberSettleExt, endTouch, bdGrade, addTouch, expandRatio);
                            // 计算量碰
                            calculateExpandBonusByAchieve(riskControlMap, period, weekMemberBonusMap, cuMemberBonusMap, bonusConfigDTO, systemConfigMap, cuMemberBonusExpandList,
                                    saOrderExt, touchNum, i + startTouch, sourceMemberSettleExt, targetMemberSettleExt, bdGrade, countryExpandRatio, addTouch, cuMemberAssessMap);
                            break;
                        }
                    }
                }

                // 将增加的碰次放入烧伤
                if (ComputeUtil.compareValue(addTouch)) {
                    CuMemberSettleExt sourceMemberSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
                    CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(2L);
                    // 根据会员等级获取对应的拓展配置
                    BdGrade bdGrade = getGradeExpand(bonusConfigDTO, targetMemberSettleExt);
                    // 获取实际拓展比例（拓展配置计算出来的单个碰次 和 等级配置上限，哪个小取哪个）
                    BigDecimal countryExpandRatio = getCountryExpand(bonusConfigDTO, targetMemberSettleExt, endTouch, bdGrade, addTouch, expandRatio);
                    countryExpandRatio = ComputeUtil.computeMultiply(countryExpandRatio, addTouch);
                    CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
                    Integer pkBonusItems = getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.EXPANSION_INCOME.getValue());
                    CuMemberBonusExpand cuMemberBonusExpand = getCuMemberBonusExpand(saOrderExt, touchNum, touchNum, targetMemberSettleExt, countryExpandRatio, cuMemberBonus, saOrderExt.getOrderAchieve(), pkBonusItems, addTouch, bdGrade);
                    expandRemark(saOrderExt, cuMemberBonusExpand, sourceMemberSettleExt, targetMemberSettleExt);
                    cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
                    BigDecimal maxIncome = ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getCalAchieve(), bdGrade.getExpandRatio());
                    BigDecimal actualIncome = ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getCalAchieve(), countryExpandRatio);
                    packageCuMemberBonusExpand(cuMemberBonusExpand, cuMemberBonus, bdGrade.getExpandCapping(), maxIncome, actualIncome);
                    setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusExpand, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                    if (ComputeUtil.compareValue(addTouch)) {
                        cuMemberBonusExpand.setRemark(cuMemberBonusExpand.getRemark() + "增加碰次：" + addTouch + "。");
                    }
                    cuMemberBonusExpandList.add(cuMemberBonusExpand);
                }
            }
        }
        return cuMemberBonusExpandList;
    }


    private int calculateTouchNum(Map<Long, CuMemberRiskControl> riskControlMap, Map<Long, CuMemberAssess> cuMemberAssessMap, 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.getFirstCalculate() != null && EYesNo.NO.getIntValue() == bdGrade.getFirstCalculate()) {
                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，不算奖金
                // 验证是否验证考核
//                if(bdGrade.getFirstAssess() != null && EAssessmentType.REPURCHASE_ASSESS.getValue() == bdGrade.getFirstAssess()){
//                    if (Objects.equals(CountryConstants.CHINA_COUNTRY, targetMemberSettleExt.getPkSettleCountry()) && !cuMemberAssessMap.containsKey(targetMemberSettleExt.getPkMember()) &&
//                            EYesNo.YES.getIntValue() != targetMemberSettleExt.getPurchaseStatus()) {
//                        BigDecimal minAchieve = ComputeUtil.obtainMinAchieve(targetMemberSettleExt.getABalance(), targetMemberSettleExt.getBBalance());
//                        targetMemberSettleExt.setABalance(ComputeUtil.computeSubtractAbs(targetMemberSettleExt.getABalance(), minAchieve));
//                        targetMemberSettleExt.setBBalance(ComputeUtil.computeSubtractAbs(targetMemberSettleExt.getBBalance(), minAchieve));
//                    }else{
//                        touchNum++;
//                    }
//                } else {
//                    touchNum++;
//                }
                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;
    }

    /**
     * 计算辅导收益（领导奖）
     *
     * @param settleTableName         结算表
     * @param settleDateStr           结算日期
     * @param period                  期间
     * @param bonusConfigDTO          参数
     * @param firPurchaseOrderList    订单列表
     * @param cuMemberBonusExpandList 量奖明细
     * @param cuMemberBonusMap        所有计算出来的奖金汇总
     * @param firstBool               true=首购，false=复购
     * @param orderBool               true=有订单，false=没有订单（延缓发放处理）
     */
    List<CuMemberBonusCoach> calculateCoachBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleDateStr, BonusConfigDTO bonusConfigDTO,
                                                 List<SaOrderExt> firPurchaseOrderList, List<CuMemberBonusExpand> cuMemberBonusExpandList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                 Map<Long, CuAwardsControl> cuAwardsControlMap, Map<Long, CuMemberRiskControl> riskControlMap, List<BdAwards> awardsList,
                                                 boolean firstBool, boolean orderBool) {
        Map<Long, SaOrderExt> saOrderExtMap = new HashMap<>(ComputeUtil.mapInitCapacity(firPurchaseOrderList.size()));
        firPurchaseOrderList.forEach(saOrderExt ->
                saOrderExtMap.put(saOrderExt.getPkId(), saOrderExt));
        return calculateCoachBonusOne(cuMemberSettleExtMap, settleTableName, settleDateStr, bonusConfigDTO, cuMemberBonusExpandList, period,
                cuMemberBonusMap, saOrderExtMap, cuAwardsControlMap, riskControlMap, awardsList, firstBool, orderBool);
    }

    /**
     * 计算领导奖
     */
    List<CuMemberBonusCoach> calculateCoachBonusOne(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleDateStr, BonusConfigDTO bonusConfigDTO,
                                                    List<CuMemberBonusExpand> cuMemberBonusExpandList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                    Map<Long, SaOrderExt> saOrderExtMap, Map<Long, CuAwardsControl> cuAwardsControlMap, Map<Long, CuMemberRiskControl> riskControlMap,
                                                    List<BdAwards> awardsList, boolean firstBool, boolean orderBool) {
        // 领导奖数据列表
        List<CuMemberBonusCoach> cuMemberBonusCoachList = new ArrayList<>();

        if (cuMemberBonusExpandList.size() > 0) {
            // 如果存在拓展收益则开始处理领导奖
            // 产生拓展收益的所有会员ID
            Set<Long> expandMemberSet = getMemberExpandBonus(cuMemberBonusMap, cuMemberBonusExpandList);

            // 查询会员产生拓展收益血缘上会员
            List<CuMemberSettleExt> cuMemberSettleExtList = iCuMemberTreeService.batchQueryCuMemberSettleParent(settleTableName, expandMemberSet);
            // 初始化父类网体的值
            getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);

            Map<Long, CuMemberAssess> cuMemberAssessMap = new HashMap<>();

            // TODO new 新逻辑没有复购考核，根据上月结余判断大小区，然后判断本月小区新増业绩来判断拿几代
            // 奖衔会员能拿几代领导奖（key:会员ID，value:奖衔值+上月结余+本月新増）
            Map<Long, CuMemberSettleExt> cuMemberBonusNumMap = getCoachAwardsMemberMap(settleTableName, settleDateStr, cuMemberSettleExtList);

            Map<Long, CuMemberSettleExt> bonusIdSettleMap = getMemberExpandBonus(cuMemberSettleExtMap);
            // 开始计算辅导奖，往上找10代血缘，判断血缘的奖衔是否 >= 5的倍数
            for (CuMemberBonusExpand cuMemberBonusExpand : cuMemberBonusExpandList) {
                List<CuMemberBonusCoach> coachBonusList = calculateBonusCoach(cuMemberSettleExtMap, bonusConfigDTO, period, cuMemberBonusMap,
                        saOrderExtMap, cuMemberAssessMap, bonusIdSettleMap, cuMemberBonusExpand, cuAwardsControlMap,
                        riskControlMap, cuMemberBonusNumMap, awardsList, firstBool, orderBool, settleDateStr);
                if (coachBonusList.size() > 0) {
                    cuMemberBonusCoachList.addAll(coachBonusList);
                }
            }
        }
        return cuMemberBonusCoachList;
    }

    /**
     * 计算领导奖（每条拓展收益计算领导奖）
     */
    private List<CuMemberBonusCoach> calculateBonusCoach(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, Integer period,
                                                         Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, SaOrderExt> saOrderExtMap, Map<Long, CuMemberAssess> cuMemberAssessMap,
                                                         Map<Long, CuMemberSettleExt> bonusIdSettleMap, CuMemberBonusExpand cuMemberBonusExpand, Map<Long, CuAwardsControl> cuAwardsControlMap,
                                                         Map<Long, CuMemberRiskControl> riskControlMap, Map<Long, CuMemberSettleExt> cuMemberBonusNumMap, List<BdAwards> awardsList,
                                                         boolean firstBool, boolean orderBool, String settleDateStr) {
        // 目前这个会员只用来处理备注会员信息使用
        CuMemberSettleExt sourceMemberSettleExt = bonusIdSettleMap.get(cuMemberBonusExpand.getPkBonus());
        // 用于回写血缘总共多少代
        List<CuMemberBonusCoach> backMemberBonusCoachList = new ArrayList<>();

        Long pkMember = cuMemberSettleExtMap.get(cuMemberBonusExpand.getPkBonus()).getPkParent();

        // 领导奖拿一共拿了多少代
        int coachGeneration = 0;
        // 获得量奖的人往上找10代血缘（非紧缩） -- 旧逻辑
//        for (int i = MagicNumberConstants.BLOOD_GENERATION_START; i <= MagicNumberConstants.BLOOD_GENERATION_END; i++) {

        // TODO new 新逻辑中使用紧缩制，向上发10次，奖衔满足考核的判断拿几代，要么发完10次，要么找到顶为止
        int i = MagicNumberConstants.BLOOD_GENERATION_START;
        // 领导奖从第1代开始计算，最多发10次
        while (i <= MagicNumberConstants.BLOOD_GENERATION_END) {
            // 当前需要拿奖金的会员
            CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(pkMember);
            if (null == targetMemberSettleExt) {
                break;
            }
            pkMember = targetMemberSettleExt.getPkParent();
            if (ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                    || EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()) {
                // 会员状态不正常 或者 停算收益 直接跳过
                continue;
            }
            if (firstBool) {
                if (validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.COACHING_INCOME.getValue())) {
                    // 校验当前国家是否有该奖项（首购辅导奖）
                    continue;
                }
            } else {
                if (validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.REPURCHASE_COACHING_INCOME.getValue())) {
                    // 校验当前国家是否有该奖项（复购辅导奖）
                    continue;
                }
            }

            SaOrderExt saOrderExt = saOrderExtMap.get(cuMemberBonusExpand.getPkOrder());
            if (orderBool && null == saOrderExt) {
                // 有订单 并且 订单为空
                continue;
            }

            CuMemberSettleExt coachAwardsMember = cuMemberBonusNumMap.get(targetMemberSettleExt.getPkMember());
            if (null == coachAwardsMember) {
                // 判断领导奖参数，如果不存在，直接跳过
                continue;
            }

            // 获取奖衔对应的领导奖配置
            BdAwards awardsCouch = getBdAwards(bonusConfigDTO, targetMemberSettleExt, cuAwardsControlMap);

            // 获取奖衔能拿多少代领导奖的奖衔值
            Integer awardsValue = this.getCoachAwardsMemberNum(awardsList, coachAwardsMember, awardsCouch, settleDateStr);

            // 判断是否有奖金
            if (awardsValue >= MagicNumberConstants.BLOOD_GENERATION_SERIES * i) {
                // TODO new 第一代必须是奖衔值大于等于5的，第二代必须是奖衔值大于等于10的...
                BdAwards coachAward = bonusConfigDTO.getAwardsValueMap().get(targetMemberSettleExt.getPkSettleCountry().toString() + ERangeType.AWARDS.getValue() + MagicNumberConstants.BLOOD_GENERATION_SERIES * i);
                // 辅导奖比例
                BigDecimal awardCalRadio = BigDecimal.ZERO;
                if (null != coachAward) {
                    awardCalRadio = coachAward.getCoachRatio();
                }
                // 生成辅导收益明细
                CuMemberBonusCoach cuMemberBonusCoach = getCuMemberBonusCoach(bonusConfigDTO, cuMemberBonusExpand, i, targetMemberSettleExt, awardCalRadio, firstBool);
                // TODO new 如果拓展收益是延缓发放，那么辅导收益也需要延缓发放
                if (EBonusIncomeStatus.DELAY_GRANT.getValue() == cuMemberBonusExpand.getIncomeStatus()) {
                    cuMemberBonusCoach.setIncomeStatus(EBonusIncomeStatus.DELAY_GRANT.getValue());
                }

                // TODO new 不走复购考核，改为根据本月新増小区业绩
//                // 正常状态的辅导奖需要判断复购考核，复购考核不通过的状态变为烧伤
//                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusCoach.getIncomeStatus()
//                        && EYesNo.NO.getIntValue() == targetMemberSettleExt.getPurchaseStatus()) {
//                    // 需要复购考核的
//                    CuMemberAssess cuMemberAssess = cuMemberAssessMap.get(targetMemberSettleExt.getPkMember());
//                    if (cuMemberAssess == null) {
//                        cuMemberBonusCoach.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
//                    }
//                }

                // 获取会员奖金数据
                CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);

                // K值设置
                if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
                    Integer generation = riskControlMap.get(cuMemberBonus.getPkMember()).getCoachGeneration();
                    if (generation < i) {
                        cuMemberBonusCoach.setIncomeStatus(EBonusIncomeStatus.RISK_CONTROL.getValue());
                    }
                }

                // 收益占比
                BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusCoach,
                        null != saOrderExt ? saOrderExt.getOrderAmount() : BigDecimal.ZERO,
                        null != saOrderExt ? saOrderExt.getInExchangeRate() : BigDecimal.ONE);
                coachRemark(saOrderExt, cuMemberBonusCoach, sourceMemberSettleExt, targetMemberSettleExt, firstBool);

                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusCoach.getIncomeStatus()) {
                    if (firstBool) {
                        // 首购处理
                        cuMemberBonus.setCoachIncome(ComputeUtil.computeAdd(cuMemberBonus.getCoachIncome(), cuMemberBonusCoach.getPretaxIncome()));
                        setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusCoach);
                    } else {
                        // 复购处理
                        cuMemberBonus.setRepurCoachIncome(ComputeUtil.computeAdd(cuMemberBonus.getRepurCoachIncome(), cuMemberBonusCoach.getPretaxIncome()));
                        setPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusCoach);
                    }
                }
                backMemberBonusCoachList.add(cuMemberBonusCoach);

                // 这一代领导奖计算完，计算代数加1
                i++;
            }
        }
        coachGeneration = --i;
        return handleCoachRemark(backMemberBonusCoachList, coachGeneration);
    }

    /**
     * 获取奖衔对应的辅导奖配置
     *
     * @param bonusConfigDTO        奖金参数设置
     * @param targetMemberSettleExt 父级
     */
    private BdAwards getBdAwards(BonusConfigDTO bonusConfigDTO, CuMemberSettleExt targetMemberSettleExt, Map<Long, CuAwardsControl> cuAwardsControlMap) {
        return getAwardsCouch(bonusConfigDTO, targetMemberSettleExt, cuAwardsControlMap);
    }

    private CuMemberBonusCoach getCuMemberBonusCoach(BonusConfigDTO bonusConfigDTO, CuMemberBonusExpand cuMemberBonusExpand,
                                                     int i, CuMemberSettleExt targetMemberSettleExt, BigDecimal awardCalRadio, boolean firstBool) {
        // 奖金项（首购、复购判断）
        Integer bonusItems = firstBool ? EBonusItems.COACHING_INCOME.getValue() : EBonusItems.REPURCHASE_COACHING_INCOME.getValue();
        CuMemberBonusCoach cuMemberBonusCoach = CuMemberBonusCoach.builder()
                .pkBonus(targetMemberSettleExt.getPkMember())
                .pkOrder(cuMemberBonusExpand.getPkOrder())
                .pkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), bonusItems))
                .incomeStatus(cuMemberBonusExpand.getIncomeStatus())
                .calType(ECalType.RATIO.getValue())
                .calAchieve(cuMemberBonusExpand.getPretaxIncome())
                .currentGeneration(i)
                // 计算比例
                .calValue(awardCalRadio)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .pretaxIncome(ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getPretaxIncome(), awardCalRadio))
                .coachNoCapping(ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getExpandNoCapping(), awardCalRadio))
                .coachCapping(ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getExpandCapping(), awardCalRadio))
                .coachNormalHalf(ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getExpandNormalHalf(), awardCalRadio))
                .coachNormalReal(ComputeUtil.computeBonusMultiply(cuMemberBonusExpand.getExpandNormalReal(), awardCalRadio))
                .build();
        cuMemberBonusCoach.setPkCountry(targetMemberSettleExt.getPkSettleCountry());
        cuMemberBonusCoach.setPkCreator(MagicNumberConstants.PK_ADMIN);
        cuMemberBonusCoach.setPkModified(cuMemberBonusExpand.getPkModified());
        if (EExpireStatus.TERMINATED.getValue() == targetMemberSettleExt.getExpireStatus()) {
            cuMemberBonusCoach.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
        }
        return cuMemberBonusCoach;
    }

    /**
     * 处理拓展表备注
     *
     * @param backMemberBonusCoachList 临时记录辅导奖列表
     * @param i                        第几代
     */
    private List<CuMemberBonusCoach> handleCoachRemark(List<CuMemberBonusCoach> backMemberBonusCoachList, int i) {
        List<CuMemberBonusCoach> cuMemberBonusCoachList = new ArrayList<>();
        for (CuMemberBonusCoach cuMemberBonusCoach : backMemberBonusCoachList) {
            cuMemberBonusCoach.setCoachGeneration(i);
            cuMemberBonusCoach.setRemark(cuMemberBonusCoach.getRemark().replace("#", cuMemberBonusCoach.getCoachGeneration().toString()));
            cuMemberBonusCoachList.add(cuMemberBonusCoach);
        }
        return cuMemberBonusCoachList;
    }

    /**
     * 计算报单服务费
     *
     * @param settleTableName      结算表
     * @param period               期间
     * @param bonusConfigDTO       参数
     * @param firPurchaseOrderList 订单列表
     * @param cuMemberBonusMap     所有计算出来的奖金汇总
     */
    List<CuMemberBonusDetail> calculateServiceBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleDate, String settleTableName, BonusConfigDTO bonusConfigDTO,
                                                    List<SaOrderExt> firPurchaseOrderList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap) {
        List<CuMemberBonusDetail> cuMemberBonusDetailList = new ArrayList<>();
        // 先过滤数据，验证报单人是否在网体列表中，不在需要从数据库中查询
        Set<Long> serviceMemberSet = new HashSet<>();
        firPurchaseOrderList.forEach(saOrderExt -> {
            CuMemberSettleExt cuMemberSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
            if (cuMemberSettleExt != null && cuMemberSettleExt.getPkCenterCode() != null) {
                serviceMemberSet.add(cuMemberSettleExt.getPkCenterCode());
            }
        });
        Map<Long, CuMemberAssess> cuMemberAssessMap = packageMemberSettleByPkMemberSet(cuMemberSettleExtMap, settleDate, settleTableName, serviceMemberSet);
        // 计算报单服务费
        for (SaOrderExt saOrderExt : firPurchaseOrderList) {
            // 只有注册订单有报单服务费
            if (EOrderType.REGISTER_ORDER.getValue() == saOrderExt.getOrderType()
                    || Objects.equals(EOrderType.SPECIAL_REGISTER_ORDER.getValue(), saOrderExt.getOrderType())) {
                CuMemberBonusDetail cuMemberBonusDetail = calculateServiceBonusOne(settleDate, cuMemberAssessMap, cuMemberSettleExtMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt);
                if (cuMemberBonusDetail != null) {
                    cuMemberBonusDetailList.add(cuMemberBonusDetail);
                }
            }
        }
        // 查询会员
        return cuMemberBonusDetailList;
    }

    /**
     * @Description: 计算服务中心奖
     * @return: CuMemberBonusDetail
     */
    CuMemberBonusDetail calculateServiceBonusOne(String settleDate, Map<Long, CuMemberAssess> cuMemberAssessMap, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt) {
        CuMemberSettleExt sourceMemberSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
        if (sourceMemberSettleExt == null || sourceMemberSettleExt.getPkCenterCode() == null) {
            return null;
        }
        CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(sourceMemberSettleExt.getPkCenterCode());
        if (targetMemberSettleExt == null
                || ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                || EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()
                || ERegistrationAuthority.SERVICE.getValue() != targetMemberSettleExt.getRegisterAuthority()) {
            // 非正常会员、停算收益、不是服务中心，都不进行处理
            return null;
        }
        // 验证是否有奖金
        if (validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.SERVICE_SUBSIDIES.getValue())) {
            return null;
        }
        // 获取会员奖金数据
        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
        BdBonusService bdBonusService = bonusConfigDTO.getBonusServiceMap().get(targetMemberSettleExt.getPkSettleCountry().toString() + EServiceType.SUBSIDY.getValue());
//        if (bdBonusService.getAssessmentType() != null && EAssessmentType.REPURCHASE_ASSESS.getValue() == bdBonusService.getAssessmentType()) {
//            // 复购考核不通过，不存在报单服务费
//            boolean flag = cuMemberAssessMap == null || !cuMemberAssessMap.containsKey(targetMemberSettleExt.getPkMember());
//            if (Objects.equals(CountryConstants.CHINA_COUNTRY, targetMemberSettleExt.getPkSettleCountry()) && flag) {
//                return null;
//            }
//        }
        // 服务补贴奖金明细
        CuMemberBonusDetail cuMemberBonusDetail = getCuMemberBonusDetail(saOrderExt, targetMemberSettleExt, cuMemberBonus);
        BigDecimal serviceRadio = bdBonusService.getServiceRadio();
        // 计算比例
        cuMemberBonusDetail.setCalValue(serviceRadio);
        cuMemberBonusDetail.setPkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.SERVICE_SUBSIDIES.getValue()));
        cuMemberBonusDetail.setPretaxIncome(ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), serviceRadio));
        // 收益占比
        BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusDetail, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
        serviceRemark(saOrderExt, cuMemberBonusDetail, sourceMemberSettleExt, targetMemberSettleExt);
//        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusDetail.getIncomeStatus()
//                && EYesNo.NO.getIntValue() == targetMemberSettleExt.getPurchaseStatus()) {
//            // 需要复购考核的
//            if (cuMemberAssessMap == null || !cuMemberAssessMap.containsKey(targetMemberSettleExt.getPkMember())) {
//                cuMemberBonusDetail.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
//            }
//        }
        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusDetail.getIncomeStatus()) {
            cuMemberBonus.setServiceIncome(ComputeUtil.computeAdd(cuMemberBonus.getServiceIncome(), cuMemberBonusDetail.getPretaxIncome()));
            setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusDetail);
        }
        return cuMemberBonusDetail;
    }

    /**
     * 计算报单服务费
     * 车奖 全球分红  有奖衔的会员，复购考核通过的，根据对应奖衔可拿代数配置拿下面代数的（推荐+拓展+领导+分红）奖金合计为基数的相应代数的比率（配置值）
     * 跟领导奖一样的算法，不算启动卡
     *
     * @param settleDateStr 结算日期
     * @param period        期间
     */
    List<CuMemberBonusDetail> calculateShareBonus(String settleDateStr, BonusConfigDTO bonusConfigDTO, Integer period,
                                                  Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, CuAwardsControl> cuAwardsControlMap) {
        List<CuMemberBonusDetail> cuMemberBonusDetailList = new ArrayList<>();

        Date settleDate = DateUtils.parseStringToDate(settleDateStr);
        String currentFirstDate = DateUtils.currentMonthFirstDateStr(settleDate);
        String beforeMonthLastDate = DateUtils.beforeDateStr(1, ChronoUnit.DAYS, DateUtils.YYYY_MM_DD, currentFirstDate);
        // 查询上月最后一天
        Integer beforeMonthLastPeriod = iCuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(beforeMonthLastDate).getPkId();
        String settleTableName = TableNameConstants.CU_MEMBER_SETTLE + beforeMonthLastPeriod;
        String rangeTableName = TableNameConstants.CU_MEMBER_RANGE + beforeMonthLastPeriod;
        // 查询上月第一天
        String beforeMonthFirstDate = DateUtils.beforeMonthFirstDateStr(settleDate);
        Integer beforeMonthFirstPeriod = iCuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(beforeMonthFirstDate).getPkId();
        // 查询上月最后一天会员等级达到奖衔的会员
        Integer assessPeriod = iCuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(currentFirstDate).getPkId();
        String assessTableName = TableNameConstants.CU_MEMBER_ASSESS + DateUtils.getYear(settleDateStr);
        // 获取结算日期的第一天的日期
        // 查询复购考核结果
        List<CuMemberSettleExt> cuMemberSettleExtList = iCuMemberTreeService.queryMemberSettleByAwards(settleTableName, rangeTableName, beforeMonthFirstPeriod, beforeMonthLastPeriod);
        if (CollectionUtil.isNotEmpty(cuMemberSettleExtList)) {
            Map<Long, CuMemberAssess> cuMemberAssessMap = iCuMemberAssessService.queryCuMemberAssessByMember(assessTableName, assessPeriod, EAssessmentType.REPURCHASE_ASSESS.getValue(), cuMemberSettleExtList);
            for (CuMemberSettleExt targetMemberSettleExt : cuMemberSettleExtList) {
                SaOrder saOrder = SaOrder.builder().pkId(0L).orderAchieve(BigDecimal.ZERO).build();
                saOrder.setPkCountry(targetMemberSettleExt.getPkSettleCountry());
                CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrder, targetMemberSettleExt);
                CuMemberBonusDetail cuMemberBonusDetail = getCuMemberBonusDetail(saOrder, targetMemberSettleExt, cuMemberBonus);
                cuMemberBonusDetail.setPkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.DIVIDEND_INCOME.getValue()));
                // 获取计算比例，根据奖衔获取
                // 计算比例
                cuMemberBonusDetail.setCalAchieve(targetMemberSettleExt.getRealIncomeTotal());
                cuMemberBonusDetail.setCalValue(targetMemberSettleExt.getAbonusRatio());
                cuMemberBonusDetail.setPretaxIncome(ComputeUtil.computeBonusMultiply(targetMemberSettleExt.getRealIncomeTotal(), targetMemberSettleExt.getAbonusRatio()));
                shareRemark(cuMemberBonusDetail, settleDateStr);
                BdBonusDeduct bdBonusDeduct = bonusConfigDTO.getBonusDeductsMap().get(cuMemberBonusDetail.getPkBonusItems());
                cuMemberBonusDetail.setIncomeTax(BigDecimal.ZERO);
                cuMemberBonusDetail.setRealIncome(ComputeUtil.computeSubtract(cuMemberBonusDetail.getPretaxIncome(), cuMemberBonusDetail.getIncomeTax()));
                cuMemberBonusDetail.setPkCountry(targetMemberSettleExt.getPkSettleCountry());
                cuMemberBonusDetail.setPkCreator(MagicNumberConstants.PK_ADMIN);
//                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusDetail.getIncomeStatus()
//                        && EYesNo.NO.getIntValue() == targetMemberSettleExt.getPurchaseStatus()) {
//                    // 需要复购考核的
//                    CuMemberAssess cuMemberAssess = cuMemberAssessMap.get(targetMemberSettleExt.getPkMember());
//                    if (cuMemberAssess == null) {
//                        cuMemberBonusDetail.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
//                    }
//                }
                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusDetail.getIncomeStatus()) {
                    cuMemberBonus.setShareIncome(ComputeUtil.computeAdd(cuMemberBonus.getShareIncome(), cuMemberBonusDetail.getPretaxIncome()));
                    setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusDetail);
                }
                cuMemberBonusDetailList.add(cuMemberBonusDetail);
            }
        }
        return cuMemberBonusDetailList;
    }

    void calculateCuMemberBloodAchieveByOrder(String settleTableName, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap,
                                              List<SaOrderExt> firPurchaseOrderList, List<SaOrderExt> repurchaseOrderList,
                                              List<SaOrderExt> mallOrderList) {
        Set<Long> expandMemberSet = new HashSet<>();
        firPurchaseOrderList.forEach(saOrderExt -> expandMemberSet.add(saOrderExt.getPkMember()));
        repurchaseOrderList.forEach(saOrderExt -> expandMemberSet.add(saOrderExt.getPkMember()));
        mallOrderList.forEach(saOrderExt -> expandMemberSet.add(saOrderExt.getPkMember()));
        if (expandMemberSet.size() > 0) {
            List<CuMemberSettleExt> cuMemberSettleExtList = iCuMemberTreeService.batchQueryCuMemberSettleParent(settleTableName, expandMemberSet);
            // 初始化父类网体的值
            getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
            for (SaOrderExt saOrderExt : firPurchaseOrderList) {
                Long pkMember = saOrderExt.getPkMember();
                while (true) {
                    CuMemberSettleExt cuMemberSettleExt = cuMemberSettleExtMap.get(pkMember);
                    if (cuMemberSettleExt == null || cuMemberSettleExt.getPkParent() == null || cuMemberSettleExt.getPkParent() == 0) {
                        break;
                    }
                    CuMemberSettleExt parentMemberSettleExt = cuMemberSettleExtMap.get(cuMemberSettleExt.getPkParent());
                    if (EOrderType.REGISTER_ORDER.getValue() == saOrderExt.getOrderType()
                            || EOrderType.SPECIAL_REGISTER_ORDER.getValue() == saOrderExt.getOrderType()) {
                        parentMemberSettleExt.setRegisterBloNewPv(ComputeUtil.computeAdd(parentMemberSettleExt.getRegisterBloNewPv(), saOrderExt.getOrderAchieve()));
                    } else {
                        parentMemberSettleExt.setUpgradeBloNewPv(ComputeUtil.computeAdd(parentMemberSettleExt.getUpgradeBloNewPv(), saOrderExt.getOrderAchieve()));
                    }
                    pkMember = cuMemberSettleExt.getPkParent();
                }
            }
            for (SaOrderExt saOrderExt : repurchaseOrderList) {
                Long pkMember = saOrderExt.getPkMember();
                while (true) {
                    CuMemberSettleExt cuMemberSettleExt = cuMemberSettleExtMap.get(pkMember);
                    if (cuMemberSettleExt == null || cuMemberSettleExt.getPkParent() == null || cuMemberSettleExt.getPkParent() == 0) {
                        break;
                    }
                    CuMemberSettleExt parentMemberSettleExt = cuMemberSettleExtMap.get(cuMemberSettleExt.getPkParent());
                    parentMemberSettleExt.setRepurchaseBloNewPv(ComputeUtil.computeAdd(parentMemberSettleExt.getRepurchaseBloNewPv(), saOrderExt.getOrderAchieve()));
                    pkMember = cuMemberSettleExt.getPkParent();
                }
            }
            for (SaOrderExt saOrderExt : mallOrderList) {
                Long pkMember = saOrderExt.getPkMember();
                while (true) {
                    CuMemberSettleExt cuMemberSettleExt = cuMemberSettleExtMap.get(pkMember);
                    if (cuMemberSettleExt == null || cuMemberSettleExt.getPkParent() == null || cuMemberSettleExt.getPkParent() == 0) {
                        break;
                    }
                    CuMemberSettleExt parentMemberSettleExt = cuMemberSettleExtMap.get(cuMemberSettleExt.getPkParent());
                    parentMemberSettleExt.setMallBloNewPv(ComputeUtil.computeAdd(parentMemberSettleExt.getMallBloNewPv(), saOrderExt.getOrderAchieve()));
                    pkMember = cuMemberSettleExt.getPkParent();
                }
            }
        }
    }

    /**
     * 计算首购量碰
     *
     * @param period                  期间
     * @param cuMemberBonusMap        奖金汇总
     * @param cuMemberBonusExpandList 拓展奖奖金明细
     * @param saOrderExt              订单
     * @param touchNum                碰次
     * @param i                       当前碰次
     * @param sourceMemberSettleExt   提供奖金的人
     * @param targetMemberSettleExt   获得奖金的人
     * @param bdGrade                 等级对应的参数
     * @param countryExpandRatio      4-n时计算国家对应的参数
     */
    private void calculateExpandBonusByAchieve(Map<Long, CuMemberRiskControl> riskControlMap, 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, BigDecimal addTouch, Map<Long, CuMemberAssess> cuMemberAssessMap) {
        // 获取拓展收益奖项ID
        Integer pkBonusItems = getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.EXPANSION_INCOME.getValue());

        // 验证封顶方式 1=日 2=周，若是周的话需要获取 周奖金
//        BigDecimal weekExpandIncome = BigDecimal.ZERO;
//        if (systemConfigMap.containsKey(targetMemberSettleExt.getPkSettleCountry().toString() + ESystemConfig.EXPAND_CAP_METHOD.getKey())) {
//            String expandCapMethod = systemConfigMap.get(targetMemberSettleExt.getPkSettleCountry() + ESystemConfig.EXPAND_CAP_METHOD.getKey());
//            if (Objects.equals(expandCapMethod, Integer.toString(EExpandCapMethod.WEEK_SETTLE.getValue())) &&
//                    weekMemberBonusMap.containsKey(targetMemberSettleExt.getPkMember())) {
//                weekExpandIncome = weekMemberBonusMap.get(targetMemberSettleExt.getPkMember()).getExpandIncome();
//            }
//        }

        // 等级对应拓展比例
        BigDecimal gradeExpandRatio = bdGrade.getExpandRatio();

        // TODO new 中国会员，指定日期之前计算比例
//        // 验证受益人等级
//        CuMember cuMember = iCuMemberService.getMember(targetMemberSettleExt.getMemberCode());
//        if (targetMemberSettleExt.getPkSettleCountry().equals(CountryConstants.CHINA_COUNTRY)
//                && cuMember != null
//                && DateUtils.compareDate(DateUtils.parseStringToDate("2024-09-11"), cuMember.getPayTime()) > 0) {
//            if (targetMemberSettleExt.getGradeValue() == EGrade.VIP.getValue()) {
//                if (ComputeUtil.compareValue(countryExpandRatio, BigDecimal.valueOf(11)) && (i <= 3 || touchNum <= 10)) {
//                    countryExpandRatio = BigDecimal.valueOf(13);
//                }
//            } else if (targetMemberSettleExt.getGradeValue() == EGrade.MAKER.getValue()) {
//                if (ComputeUtil.compareValue(countryExpandRatio, BigDecimal.valueOf(10)) && (i <= 3 || touchNum <= 10)) {
//                    countryExpandRatio = BigDecimal.valueOf(11);
//                }
//            }
//        }

        // 获取等级封顶值
        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
        // 左右区获取最小的
        BigDecimal calAchieve = ComputeUtil.obtainMinAchieve(targetMemberSettleExt.getABalance(), targetMemberSettleExt.getBBalance());

        CuMemberBonusExpand cuMemberBonusExpand = getCuMemberBonusExpand(saOrderExt, touchNum, i, targetMemberSettleExt, countryExpandRatio, cuMemberBonus, calAchieve, pkBonusItems, addTouch, bdGrade);
        // 扣减a、b区结余
        targetMemberSettleExt.setABalance(ComputeUtil.computeSubtract(targetMemberSettleExt.getABalance(), calAchieve));
        targetMemberSettleExt.setBBalance(ComputeUtil.computeSubtract(targetMemberSettleExt.getBBalance(), 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);

        // K值设置
        if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
            actualIncome = ComputeUtil.computeBonusMultiply(actualIncome, riskControlMap.get(cuMemberBonus.getPkMember()).getExpandRatio());
            cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.RISK_CONTROL.getValue());
        }

        // 获取等级对应的封顶值（因为先计算复购，再计算首购，封顶需要把复购拓展也加上）
        BigDecimal expandIncome = ComputeUtil.computeAdd(ComputeUtil.computeAdd(cuMemberBonus.getExpandIncome(), actualIncome), cuMemberBonus.getRepurExpandIncome());

        // 判断收益 是否超过封顶值，超过的话变为封顶值
        // 判断是否烧伤，判断原奖金是否>=封顶值,奖金到了就是烧伤
        // 验证会员状态 封停状态跟冻结都正常计算奖金，封停的账号发放的时候奖金发放为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(bdGrade.getExpandCapping(), 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 = bdGrade.getExpandCapping();
        }

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

        if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
            cuMemberBonusExpand.setRemark(cuMemberBonusExpand.getRemark() + "K值比例:" + riskControlMap.get(cuMemberBonus.getPkMember()).getExpandRatio() + "。");
        }
        if (ComputeUtil.compareValue(addTouch)) {
            cuMemberBonusExpand.setRemark(cuMemberBonusExpand.getRemark() + "增加碰次：" + addTouch + "。");
        }

        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusExpand.getIncomeStatus()
                || EBonusIncomeStatus.RISK_CONTROL.getValue() == cuMemberBonusExpand.getIncomeStatus()) {
            // 判断会员状态，会员状态为封停的话状态修改为停收
            cuMemberBonus.setExpandIncome(ComputeUtil.computeSubtract(expandIncome, cuMemberBonus.getRepurExpandIncome()));
            setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusExpand);
        }
        cuMemberBonusExpandList.add(cuMemberBonusExpand);
    }

    /**
     * 还原会员结算表，将 轮次 +1 最小值变为0
     *
     * @param cuMemberSettleExt 结算体数据
     * @return: void
     */
    private void reductionMemberSettle(CuMemberSettleExt cuMemberSettleExt) {
        cuMemberSettleExt.setMinAchieve(BigDecimal.ZERO);
        cuMemberSettleExt.setSecond(0);
        cuMemberSettleExt.setRound(cuMemberSettleExt.getRound() + 1);
    }

    /**
     * 处理拓展延缓发放
     */
    public List<CuMemberBonusExpand> handleDelayExpand(BonusRecordDetailVO recordDetailVO, Map<Long, CuMemberBonus> cuMemberBonusMap, BonusConfigDTO bonusConfigDTO,
                                                       Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, Integer period, Integer yesterdayPeriod, String currentSettleTableName,
                                                       Map<Integer, BdGrade> gradeMap) {
        // 量奖（拓展收益）延缓发放主表量奖（拓展收益）延缓发放主表
        List<CuMemberBonusDelay> cuMemberBonusDelayList = new ArrayList<>();
        // 量奖（拓展收益）延缓发放明细列表
        List<CuMemberBonusDelayDetail> cuMemberBonusDelayDetailList = new ArrayList<>();
        // 已经追加拓展延缓明细的会员会员列表
        Set<Long> pkMemberSet = new HashSet<>();

        // 新添加的扩展收益
        List<CuMemberBonusExpand> cuMemberBonusExpandList = new ArrayList<>();
        if (null == recordDetailVO.getCuMemberBonusExpandList()) {
            recordDetailVO.setCuMemberBonusExpandList(new ArrayList<>());
        }
        if (null == recordDetailVO.getBonusDelayDetailAddMap()) {
            recordDetailVO.setBonusDelayDetailAddMap(new HashMap<>());
        }

        Map<Long, CuMemberBonusDelayDetail> bonusDelayDetailAddMap = recordDetailVO.getBonusDelayDetailAddMap();
        if (bonusDelayDetailAddMap.size() > 0) {
            // 拓展收益有延缓
            for (Long key : bonusDelayDetailAddMap.keySet()) {
                // 延缓收益信息
                CuMemberBonusDelayDetail cuMemberBonusDelayAddDetail = bonusDelayDetailAddMap.get(key);
                // 会员ID
                Long pkMember = cuMemberBonusDelayAddDetail.getPkMember();
                // TODO new 增加一条新増的延缓收益明细
                cuMemberBonusDelayDetailList.add(cuMemberBonusDelayAddDetail);

                // 发放收益 = 发放前收益 + 首购 + 复购
                BigDecimal pretaxIncome = cuMemberBonusDelayAddDetail.getBeforePretaxIncome().add(cuMemberBonusDelayAddDetail.getFirPretaxIncome()).add(cuMemberBonusDelayAddDetail.getRepPretaxIncome());
                // 发放后收益 = 发放前收益 + 首购 + 复购
                BigDecimal afterPretaxIncome = pretaxIncome;
                // 获取计算后的值
                cuMemberBonusDelayAddDetail.setAfterPretaxIncome(pretaxIncome);

                if (cuMemberBonusDelayAddDetail.getBeforePretaxIncome().compareTo(BigDecimal.ZERO) > 0) {
                    // 发放前延缓有值，根据等级判断生成一条拓展收益明细
                    if (cuMemberBonusDelayAddDetail.getExpandCapping().compareTo(pretaxIncome) < 0) {
                        // 封顶值 小于 收益，使用封顶值
                        pretaxIncome = cuMemberBonusDelayAddDetail.getExpandCapping();
                    }
                    // 记录已经追加拓展延缓明细的会员
                    pkMemberSet.add(pkMember);

                    // 结算会员信息
                    CuMemberSettleExt cuMemberSettleExt = cuMemberSettleExtMap.get(pkMember);
                    // TODO new 追加会员奖金拓展收益
                    CuMemberBonus cuMemberBonus = this.getCuMemberBonus(period, cuMemberBonusMap, pkMember,
                            cuMemberSettleExt.getIncomeStatus(), cuMemberSettleExt.getPkSettleCountry(), cuMemberSettleExt.getPkRate());
                    cuMemberBonus.setExpandCapping(cuMemberBonusDelayAddDetail.getExpandCapping());
                    cuMemberBonus.setExpandNoCapping(pretaxIncome);

                    // 获取拓展收益奖项
                    Integer pkBonusItems = getPkBonusItems(bonusConfigDTO, cuMemberBonusDelayAddDetail.getPkCountry(), EBonusItems.EXPANSION_INCOME.getValue());
                    BdGrade bdGrade = gradeMap.get(cuMemberSettleExt.getPkGrade());
                    // 创建一条拓展收益明细
                    CuMemberBonusExpand cuMemberBonusExpand = this.getCuMemberBonusExpandDelay(cuMemberSettleExt, cuMemberBonus, bdGrade.getExpandRatio(),
                            pkBonusItems, bdGrade);
                    cuMemberBonusExpand.setCalType(null != cuMemberBonusDelayAddDetail.getFirCalType() ? cuMemberBonusDelayAddDetail.getFirCalType() : cuMemberBonusDelayAddDetail.getRepCalType());
                    cuMemberBonusExpand.setCalValue(null != cuMemberBonusDelayAddDetail.getFirCalValue() ? cuMemberBonusDelayAddDetail.getFirCalValue() : cuMemberBonusDelayAddDetail.getRepCalValue());
                    cuMemberBonusExpand.setPretaxIncome(pretaxIncome);
                    cuMemberBonusExpand.setExpandNoCapping(pretaxIncome);
                    cuMemberBonusExpand.setExpandCapping(cuMemberBonusDelayAddDetail.getExpandCapping());
                    cuMemberBonusExpand.setExpandNormalHalf(ComputeUtil.computeMultiplyHalf(cuMemberBonusDelayAddDetail.getExpandCapping()));
                    cuMemberBonusExpand.setExpandNormalReal(ComputeUtil.computeMultiplyHalf(pretaxIncome));
                    cuMemberBonusExpand.setRemark(String.format(BonusMsgConstants.BONUS_EXPAND_DELAY, cuMemberSettleExt.getMemberCode() + cuMemberSettleExt.getMemberName()));
                    // 处理扣项，计算最终收益
                    BdBonusDeduct bdBonusDeduct = setDeplyBonusDetailDeduct(bonusConfigDTO, cuMemberBonusExpand);

                    if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusExpand.getIncomeStatus()) {
                        // 处理实发小计、实发收益总计
                        cuMemberBonus.setExpandIncome(pretaxIncome);
                        setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusExpand);
                    }
                    // TODO new 追加的一条延缓收益生成的拓展收益明细
                    cuMemberBonusExpandList.add(cuMemberBonusExpand);

                    // 封装延缓发放减少明细
                    CuMemberBonusDelayDetail cuMemberBonusDelayGrantDetail = CuMemberBonusDelayDetail.builder()
                            .pkMember(pkMember)
                            .period(period)
                            .beforePretaxIncome(cuMemberBonusDelayAddDetail.getAfterPretaxIncome())
                            .pretaxIncome(pretaxIncome)
                            .afterPretaxIncome(cuMemberBonusDelayAddDetail.getAfterPretaxIncome().subtract(pretaxIncome))
                            .incomeTax(cuMemberBonusExpand.getIncomeTax())
                            .realIncome(cuMemberBonusExpand.getRealIncome())
                            .type(EInfusingWaterType.BANK_TRANSFER.getValue())
                            .pkBonus(cuMemberBonusDelayAddDetail.getPkBonus())
                            .expandCapping(cuMemberBonusDelayAddDetail.getExpandCapping())
                            .build();
                    cuMemberBonusDelayGrantDetail.setPkCreator(cuMemberBonusDelayAddDetail.getPkCreator());
                    cuMemberBonusDelayGrantDetail.setPkCountry(cuMemberBonusDelayAddDetail.getPkCountry());
                    // TODO new 增加一条减少的延缓收益明细
                    cuMemberBonusDelayDetailList.add(cuMemberBonusDelayGrantDetail);

                    afterPretaxIncome = cuMemberBonusDelayGrantDetail.getAfterPretaxIncome();
                }

                // 添加延缓主表
                CuMemberBonusDelay cuMemberBonusDelay = CuMemberBonusDelay.builder()
                        .pkMember(pkMember)
                        .period(period)
                        .beforeGrantIncome(cuMemberBonusDelayAddDetail.getBeforePretaxIncome())
                        .grantIncome(pretaxIncome)
                        .afterGrantIncome(afterPretaxIncome)
                        .pkBonus(cuMemberBonusDelayAddDetail.getPkBonus())
                        .build();
                cuMemberBonusDelay.setPkCreator(cuMemberBonusDelayAddDetail.getPkCreator());
                cuMemberBonusDelay.setPkCountry(cuMemberBonusDelayAddDetail.getPkCountry());
                // TODO new 增加一条延缓主表
                cuMemberBonusDelayList.add(cuMemberBonusDelay);
            }
        }

        // 处理当天没有奖金的延缓发放
        this.handleNotGrantDelay(cuMemberBonusExpandList, cuMemberBonusMap, bonusConfigDTO, cuMemberSettleExtMap, period, yesterdayPeriod, currentSettleTableName,
                gradeMap, pkMemberSet, cuMemberBonusDelayList, cuMemberBonusDelayDetailList);

        recordDetailVO.setCuMemberBonusDelayList(cuMemberBonusDelayList);
        recordDetailVO.setCuMemberBonusDelayDetailList(cuMemberBonusDelayDetailList);
        recordDetailVO.getCuMemberBonusExpandList().addAll(cuMemberBonusExpandList);

        return cuMemberBonusExpandList;
    }

    /**
     * 获取奖衔会员各能拿多少代
     *
     * @param settleTableName       结算表
     * @param settleDateStr         结算日期
     * @param cuMemberSettleExtList
     */
    private Map<Long, CuMemberSettleExt> getCoachAwardsMemberMap(String settleTableName, String settleDateStr, List<CuMemberSettleExt> cuMemberSettleExtList) {
        // 奖衔会员能拿几代领导奖（key:会员ID，value:奖衔值+上月结余+本月新増）
        Map<Long, CuMemberSettleExt> cuMemberBonusNumMap = new HashMap<>();

        // 拓展收益血缘上会员ID
        List<Long> pkAwardsMemberList = cuMemberSettleExtList.stream().map(CuMemberSettleExt::getPkMember).distinct().collect(Collectors.toList());

        Date settleDate = DateUtils.parseStringToDate(settleDateStr);
        // 之前月份的最后一期
        Integer monthLastPeriod = iCuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(DateUtils.beforeMonthLastDateStr(settleDate)).getPkId();
        String settleTableNameMonthLast = TableNameConstants.CU_MEMBER_SETTLE + monthLastPeriod;

        // TODO new 有奖衔的会员，本月左右区新増，上月最后一期左右区结余（需要确保上月最后一期日结表存在）
        List<CuMemberSettleExt> awardsMemberSettleList = iCuMemberTreeService.listMemberMonthAssess(settleTableName, settleTableNameMonthLast, pkAwardsMemberList);

        if (CollectionUtil.isNotEmpty(awardsMemberSettleList)) {
            for (CuMemberSettleExt tmpCuMemberSettleExt : awardsMemberSettleList) {
                cuMemberBonusNumMap.put(tmpCuMemberSettleExt.getPkMember(), tmpCuMemberSettleExt);
            }
        }
        return cuMemberBonusNumMap;
    }

    /**
     * 处理当天没有奖金的延缓发放
     */
    private void handleNotGrantDelay(List<CuMemberBonusExpand> cuMemberBonusExpandList, Map<Long, CuMemberBonus> cuMemberBonusMap, BonusConfigDTO bonusConfigDTO,
                                     Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, Integer period, Integer yesterdayPeriod, String currentSettleTableName,
                                     Map<Integer, BdGrade> gradeMap, Set<Long> pkMemberSet,
                                     List<CuMemberBonusDelay> cuMemberBonusDelayList, List<CuMemberBonusDelayDetail> cuMemberBonusDelayDetailList) {
        // TODO new 需要今天没有奖金产生，但是还有延缓奖金没发放的会员
        List<CuMemberSettleExt> notGrantDelayExtList = iCuMemberBonusDelayService.listDelayNotBonus(currentSettleTableName, pkMemberSet, yesterdayPeriod);
        if (CollectionUtil.isNotEmpty(notGrantDelayExtList)) {
            for (CuMemberSettleExt cuMemberSettleExt : notGrantDelayExtList) {
                // 会员ID
                Long pkMember = cuMemberSettleExt.getPkMember();
                // 拓展收益
                BigDecimal pretaxIncome = cuMemberSettleExt.getAfterGrantIncome();
                BdGrade bdGrade = gradeMap.get(cuMemberSettleExt.getPkGrade());
                // 等级封顶值
                BigDecimal expandCapping = bdGrade.getExpandCapping();

                if (expandCapping.compareTo(pretaxIncome) < 0) {
                    // 封顶值 小于 收益，使用封顶值
                    pretaxIncome = expandCapping;
                }

                // 结算会员信息
                getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExt);

                // 追加会员奖金收益
                CuMemberBonus cuMemberBonus = this.getCuMemberBonus(period, cuMemberBonusMap, pkMember,
                        cuMemberSettleExt.getIncomeStatus(), cuMemberSettleExt.getPkSettleCountry(), cuMemberSettleExt.getPkRate());
                cuMemberBonus.setExpandNoCapping(pretaxIncome);
                cuMemberBonus.setExpandCapping(expandCapping);

                // 获取拓展收益奖项
                Integer pkBonusItems = getPkBonusItems(bonusConfigDTO, cuMemberSettleExt.getPkSettleCountry(), EBonusItems.EXPANSION_INCOME.getValue());
                // 创建一条拓展收益明细
                CuMemberBonusExpand cuMemberBonusExpand = this.getCuMemberBonusExpandDelay(cuMemberSettleExt, cuMemberBonus, bdGrade.getExpandRatio(),
                        pkBonusItems, bdGrade);
                cuMemberBonusExpand.setPretaxIncome(pretaxIncome);
                cuMemberBonusExpand.setExpandNoCapping(pretaxIncome);
                cuMemberBonusExpand.setExpandCapping(expandCapping);
                cuMemberBonusExpand.setExpandNormalHalf(ComputeUtil.computeMultiplyHalf(expandCapping));
                cuMemberBonusExpand.setExpandNormalReal(ComputeUtil.computeMultiplyHalf(pretaxIncome));
                cuMemberBonusExpand.setRemark(String.format(BonusMsgConstants.BONUS_EXPAND_DELAY, cuMemberSettleExt.getMemberCode() + cuMemberSettleExt.getMemberName()));
                // 处理扣项，计算最终收益
                BdBonusDeduct bdBonusDeduct = setDeplyBonusDetailDeduct(bonusConfigDTO, cuMemberBonusExpand);

                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusExpand.getIncomeStatus()) {
                    // 处理实发小计、实发收益总计
                    cuMemberBonus.setExpandIncome(pretaxIncome);
                    setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusExpand);
                }
                // TODO new 追加的一条延缓收益生成的拓展收益明细
                cuMemberBonusExpandList.add(cuMemberBonusExpand);

                // 封装延缓发放减少明细
                CuMemberBonusDelayDetail cuMemberBonusDelayGrantDetail = CuMemberBonusDelayDetail.builder()
                        .pkMember(pkMember)
                        .period(period)
                        .beforePretaxIncome(cuMemberSettleExt.getAfterGrantIncome())
                        .pretaxIncome(pretaxIncome)
                        .afterPretaxIncome(cuMemberSettleExt.getAfterGrantIncome().subtract(pretaxIncome))
                        .incomeTax(cuMemberBonusExpand.getIncomeTax())
                        .realIncome(cuMemberBonusExpand.getRealIncome())
                        .type(EInfusingWaterType.BANK_TRANSFER.getValue())
                        .pkBonus(pkMember)
                        .expandCapping(expandCapping)
                        .build();
                cuMemberBonusDelayGrantDetail.setPkCreator(MagicNumberConstants.PK_ADMIN);
                cuMemberBonusDelayGrantDetail.setPkCountry(cuMemberSettleExt.getPkCountry());
                // TODO new 增加一条减少的延缓收益明细
                cuMemberBonusDelayDetailList.add(cuMemberBonusDelayGrantDetail);

                // 添加延缓主表
                CuMemberBonusDelay cuMemberBonusDelay = CuMemberBonusDelay.builder()
                        .pkMember(pkMember)
                        .period(period)
                        .beforeGrantIncome(cuMemberSettleExt.getAfterGrantIncome())
                        .grantIncome(pretaxIncome)
                        .afterGrantIncome(cuMemberSettleExt.getAfterGrantIncome().subtract(pretaxIncome))
                        .pkBonus(pkMember)
                        .build();
                cuMemberBonusDelay.setPkCreator(MagicNumberConstants.PK_ADMIN);
                cuMemberBonusDelay.setPkCountry(cuMemberSettleExt.getPkCountry());
                // TODO new 增加一条延缓主表
                cuMemberBonusDelayList.add(cuMemberBonusDelay);
            }
        }
    }

    /**
     * 获取领导奖实际的奖衔值
     *
     * @param awardsList        奖衔列表
     * @param coachAwardsMember 会员奖衔数据（上月结余、本月新増等）
     * @param bdAwards          当前奖衔（处理过真实奖衔控制）
     * @param settleDateStr     结算日期
     * @return
     */
    private Integer getCoachAwardsMemberNum(List<BdAwards> awardsList, CuMemberSettleExt coachAwardsMember, BdAwards bdAwards, String settleDateStr) {
        // 奖衔值倒序排序
        List<BdAwards> tmpAwardsList = awardsList.stream().sorted(Comparator.comparingInt(BdAwards::getAwardsValue).reversed()).collect(Collectors.toList());

        if (ESysName.LX.getValue().equals(BdConfig.getSysName())) {
            // 乐学系统
            // 2025年9月1日之前不需要校验，直接按奖衔拿
            if (settleDateStr.compareTo("2025-09-01") < 0
                    && (EEnv.ONLINE.getValue().equals(BdConfig.getEnv())
                    || EEnv.TEST.getValue().equals(BdConfig.getEnv()))
            ) {
                // 生产环境（2025.09.01之前，领导奖不需要校验业绩，是什么奖衔就按什么奖衔处理）
                return bdAwards.getAwardsValue();
            }
        } else if (ESysName.BD.getValue().equals(BdConfig.getSysName())) {
            // 北大系统
            // 2025.05.21 会员 BD62233572（10690），2025-06-01前领导奖免考
            if (coachAwardsMember.getPkMember().equals(10690L)
                    && (settleDateStr.compareTo("2025-06-01") < 0
                    && settleDateStr.compareTo("2025-05-20") >= 0)
            ) {
                return bdAwards.getAwardsValue();
            }
        }

        if (EYesNo.YES.getIntValue() == coachAwardsMember.getPurchaseStatus()) {
            // 免考 -- 不需要计算当月新増业绩，直接按当前奖衔进行处理
            return bdAwards.getAwardsValue();
        }

        // 小区业绩
        BigDecimal smallPV;
        // 上月左右区结余
        if (coachAwardsMember.getABalance().compareTo(coachAwardsMember.getBBalance()) > 0) {
            // 左区大，右区小区
            smallPV = coachAwardsMember.getBSumPv();
        } else if (coachAwardsMember.getABalance().compareTo(coachAwardsMember.getBBalance()) < 0) {
            // 右区大，左区小区
            smallPV = coachAwardsMember.getASumPv();
        } else {
            // 左右区相同
            if (coachAwardsMember.getASumPv().compareTo(coachAwardsMember.getBSumPv()) <= 0) {
                // 左区 小于等于 右区，左区等于小区
                smallPV = coachAwardsMember.getASumPv();
            } else {
                // 右区小区
                smallPV = coachAwardsMember.getBSumPv();
            }
        }
        // 业绩判断奖衔值，默认为Q0
        Integer pvAwardsValue = EAwards.MEMBER.getValue();
        // 月新増业绩判断应该拿几代
        for (BdAwards tmpBdAwards : tmpAwardsList) {
            if (tmpBdAwards.getSmallAssess().compareTo(smallPV) <= 0) {
                pvAwardsValue = tmpBdAwards.getAwardsValue();
                break;
            }
        }
        // 业绩判断奖衔值不能大于当前奖衔的奖衔值
        if (pvAwardsValue.compareTo(bdAwards.getAwardsValue()) > 0) {
            return bdAwards.getAwardsValue();
        }
        return pvAwardsValue;
    }

}
