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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.hzs.bonus.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.bonus.bonus.service.ICuMemberBonusService;
import com.hzs.bonus.bonus.service.ICuMemberShareDetailService;
import com.hzs.common.core.constant.*;
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.achieve.CuMemberSettlePeriod;
import com.hzs.common.domain.member.base.CuAwardsControl;
import com.hzs.common.domain.member.bonus.*;
import com.hzs.common.domain.member.ext.CuMemberSettleCountryExt;
import com.hzs.common.domain.member.ext.CuMemberSettleDetailExt;
import com.hzs.common.domain.member.ext.CuMemberSettleExt;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.ext.SaOrderItemsExt;
import com.hzs.common.domain.sale.order.SaOrder;
import com.hzs.common.domain.sale.order.SaOrderItems;
import com.hzs.common.domain.system.config.BdAwards;
import com.hzs.common.domain.system.config.BdGrade;
import com.hzs.system.base.ISystemConfigServiceApi;
import com.hzs.system.config.IGradeServiceApi;
import com.hzs.system.config.dto.*;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * @Description: 计算首购的奖金处理类
 * @Author: sui q
 * @Time: 2022/11/15 10:08
 * @Classname: BonusSettleComponent
 * @PackageName: com.hzs.member.achieve.service.impl
 */
@Component
public class BonusSettleFirstPurchaseHandle extends BonusSettleHandle {

    @DubboReference
    private IGradeServiceApi gradeServiceApi;

    @DubboReference
    private ISystemConfigServiceApi systemConfigServiceApi;

    @Autowired
    private ICuMemberSettlePeriodService cuMemberSettlePeriodService;

    @Autowired
    private ICuMemberBonusService cuMemberBonusService;

    /**
     * @param settleTableName      结算表
     * @param bonusConfigDTO       参数
     * @param firPurchaseOrderList 首单
     * @Description: 计算直推奖
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/10 14:17
     */
    List<CuMemberBonusPush> calculateRecommendBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleTableNameDetail, BonusConfigDTO bonusConfigDTO,
                                                    List<SaOrderExt> firPurchaseOrderList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, CuMemberRiskControl> riskControlMap) {
        // 查询 各个国家 3单循环 4单循环的配置值
        // 获得会员的轮、次，按照订单时间进行
        // 根据订单获取轮次，要回写
        List<CuMemberSettleExt> cuMemberSettleExtList = cuMemberTreeService.batchQueryMemberSettleBySaOrder(settleTableName, settleTableNameDetail, firPurchaseOrderList);
        getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
        // 推荐奖明细
        List<CuMemberBonusPush> cuMemberBonusPushList = new ArrayList<>();
        // 等级对应的业绩
        for (SaOrderExt saOrderExt : firPurchaseOrderList) {
            CuMemberBonusPush cuMemberBonusPush = calculatePushBonusOne(cuMemberSettleExtMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt, riskControlMap);
            if (cuMemberBonusPush != null) {
                cuMemberBonusPushList.add(cuMemberBonusPush);
            }
        }
        return cuMemberBonusPushList;
    }

    /**
     * 计算某条订单的推荐奖金
     *
     * @return: void
     * @Author: sui q
     * @Date: 2023/2/4 13:57
     */
    CuMemberBonusPush calculatePushBonusOne(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                            SaOrderExt saOrderExt, Map<Long, CuMemberRiskControl> riskControlMap) {
        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.POINT_SHARE_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);
        Map<String, BdGrade> gradeMap = bonusConfigDTO.getGradeMap();
        BdGrade bdGrade = gradeMap.get(targetMemberSettleExt.getPkSettleCountry().toString() + "_" + targetMemberSettleExt.getPkGrade());
        // 根据会员等级获取，等级对应的参数，等级对应的直推比例
        // 直接计算奖金 业绩 * 计算值，判断是否有扣项
        // 获取等级对应的业绩
        BigDecimal orderAchieve = saOrderExt.getOrderAchieve();
        cuMemberBonusPush.setCalType(ECalType.RATIO.getValue());
        cuMemberBonusPush.setCalValue(bdGrade.getPushRatio());
        cuMemberBonusPush.setCalAchieve(orderAchieve);
        cuMemberBonusPush.setPretaxIncome(ComputeUtil.computeBonusMultiply(orderAchieve, cuMemberBonusPush.getCalValue()));
        // K值设置
        if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
            cuMemberBonusPush.setPretaxIncome(ComputeUtil.computeBonusMultiply(cuMemberBonusPush.getPretaxIncome(), riskControlMap.get(cuMemberBonus.getPkMember()).getDirectPushRatio()));
            cuMemberBonusPush.setIncomeStatus(EBonusIncomeStatus.RISK_CONTROL.getValue());
        }
        setBonusPushIncome(cuMemberSettleExtMap, bonusConfigDTO, saOrderExt, cuMemberBonus, cuMemberBonusPush);
        if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
            cuMemberBonusPush.setRemark(cuMemberBonusPush.getRemark() + ",K值比例:" + riskControlMap.get(cuMemberBonus.getPkMember()).getDirectPushRatio());
        }
        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() ||
                EBonusIncomeStatus.RISK_CONTROL.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)
                .build();
        cuMemberBonusPush.setPkCountry(cuMemberSettleExt.getPkSettleCountry());
        cuMemberBonusPush.setPkCreator(MagicNumberConstants.PK_ADMIN);
        return cuMemberBonusPush;
    }

    /**
     * @param settleTableName      结算表
     * @param period               期间
     * @param bonusConfigDTO       参数
     * @param firPurchaseOrderList 首单
     * @param cuMemberBonusMap     所有计算出来的奖金汇总
     * @Description: 计算拓展收益
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/10 14:17
     */
    List<CuMemberBonusExpand> calculateExpandBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleDate, String settleTableName, String settleTableNameDetail, BonusConfigDTO bonusConfigDTO,
                                                   List<SaOrderExt> firPurchaseOrderList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, CuMemberRiskControl> riskControlMap) {
        Map<String, String> systemConfigMap = systemConfigServiceApi.getBonusSystemConfig().getData();
        Map<Long, CuMemberBonus> weekMemberBonusMap = getWeekMemberBonusMap(settleDate, period);
        // 根据开始期间、结束期间查询
        List<CuMemberBonusExpand> cuMemberBonusExpandList = new ArrayList<>();
        // 获取所有订单的上级，根据订单往上一步步计算
        Map<Long, List<CuMemberSettleExt>> memberSettleMap = cuMemberTreeService.batchQueryCuMemberSettlePlaceParent(settleTableName, settleTableNameDetail, firPurchaseOrderList);
        for (Long pkOrder : memberSettleMap.keySet()) {
            // 所有需要计算的父节点，只计算新增
            List<CuMemberSettleExt> cuMemberSettleExtList = memberSettleMap.get(pkOrder);
            // 先进行初始化所有的安置人，存储需要修改的值,cuMemberSettleExtMap最终修改的
            getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
        }
        for (SaOrderExt saOrderExt : firPurchaseOrderList) {
            // 所有需要计算的父节点，只计算新增
            List<CuMemberSettleExt> cuMemberSettleExtList = memberSettleMap.get(saOrderExt.getPkId());
            int touchNum = 1;
            List<CuMemberBonusExpand> expandList = calculateExpandBonusOne(riskControlMap, weekMemberBonusMap, systemConfigMap, touchNum, cuMemberSettleExtMap, bonusConfigDTO, period, settleDate, cuMemberBonusMap, cuMemberSettleExtList, saOrderExt);
            if (expandList.size() > 0) {
                for (CuMemberBonusExpand cuMemberBonusExpand : expandList) {
                    cuMemberBonusExpand.setExpandTouch(expandList.size());
                    cuMemberBonusExpand.setRemark(cuMemberBonusExpand.getRemark().replace("#", cuMemberBonusExpand.getExpandTouch().toString()));
                }
                cuMemberBonusExpandList.addAll(expandList);
            }
        }
        // 根据订单往上穿业绩，只计算新增
        return cuMemberBonusExpandList;
    }

    private Map<Long, CuMemberBonus> getWeekMemberBonusMap(String settleDate, Integer period) {
        // 根据结算日期获取周期的期间，用于海外
        String recentlyMonday = DateUtils.getRecentlyTuesday(settleDate);
        CuMemberSettlePeriod startMemberSettlePeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(recentlyMonday);
        // 查询封顶周期是周的国家的所有人的拓展收益、复购拓展收益
        return cuMemberBonusService.queryWeekMemberBonus(startMemberSettlePeriod.getPkId(), period);
    }

    /**
     * @Description: 计算量奖
     * @return: List<CuMemberBonusExpand>
     * @Author: sui q
     * @Date: 2023/2/4 14:18
     */
    List<CuMemberBonusExpand> calculateExpandBonusOne(Map<Long, CuMemberRiskControl> riskControlMap, Map<Long, CuMemberBonus> weekMemberBonusMap, Map<String, String> systemConfigMap, int touchNum, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO,
                                                      Integer period, String settleDate, Map<Long, CuMemberBonus> cuMemberBonusMap, List<CuMemberSettleExt> cuMemberSettleExtList, SaOrderExt saOrderExt) {
        List<CuMemberBonusExpand> cuMemberBonusExpandList = new ArrayList<>();
        if (CollectionUtil.isEmpty(cuMemberSettleExtList)) {
            return cuMemberBonusExpandList;
        }
        Map<String, BdGrade> gradeMap = bonusConfigDTO.getGradeMap();
        // 先准备值，准备好值后，开始计算，计算碰次
        for (CuMemberSettleExt sourceMemberSettleExt : cuMemberSettleExtList) {
            // 数据已经准备好了，肯定有值，map中是实际的值，先计算新增，然后根据新增结算计算碰次，list是为了存储碰次的顺序
            CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(sourceMemberSettleExt.getPkPlaceParent());
            if (targetMemberSettleExt == null || ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory() ||
                    EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus()) {
                continue;
            }
            List<CuMemberSettleDetailExt> cuMemberSettleDetailExtList = targetMemberSettleExt.getCuMemberSettleDetailExtList();
            if(CollectionUtil.isNotEmpty(cuMemberSettleDetailExtList)){
                Map<Integer, CuMemberSettleDetailExt> cuMemberSettleDetailExtMap = new HashMap<>();
                targetMemberSettleExt.getCuMemberSettleDetailExtList().forEach(cuMemberSettleDetailExt ->
                        cuMemberSettleDetailExtMap.put(cuMemberSettleDetailExt.getPlaceDept(), cuMemberSettleDetailExt));
                if(cuMemberSettleDetailExtMap.containsKey(sourceMemberSettleExt.getPlaceDept())){
                    CuMemberSettleDetailExt cuMemberSettleDetailExt = cuMemberSettleDetailExtMap.get(sourceMemberSettleExt.getPlaceDept());
                    // 计算业绩
                    BdGrade bdGrade = gradeMap.get(targetMemberSettleExt.getPkSettleCountry().toString() + "_" + targetMemberSettleExt.getPkGrade());
                    // 左区
                    // K值设置
                    if (riskControlMap.containsKey(targetMemberSettleExt.getPkMember())) {
                        CuMemberRiskControl cuMemberRiskControl = riskControlMap.get(targetMemberSettleExt.getPkMember());
                        cuMemberSettleDetailExt.setNewAmount(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getNewAmount(), ComputeUtil.computeBonusMultiply(convertLocalCurrency(saOrderExt, bonusConfigDTO), cuMemberRiskControl.getAchieveRatio())));
                        cuMemberSettleDetailExt.setNewPv(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getNewPv(), ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), cuMemberRiskControl.getAchieveRatio())));
                        cuMemberSettleDetailExt.setABalance(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getABalance(), ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), cuMemberRiskControl.getAchieveRatio())));
                        cuMemberSettleDetailExt.setBBalance(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getBBalance(), ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), cuMemberRiskControl.getAchieveRatio())));
                    }else{
                        cuMemberSettleDetailExt.setNewAmount(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getNewAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
                        cuMemberSettleDetailExt.setNewPv(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getNewPv(), saOrderExt.getOrderAchieve()));
                        cuMemberSettleDetailExt.setABalance(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getABalance(), saOrderExt.getOrderAchieve()));
                        cuMemberSettleDetailExt.setBBalance(ComputeUtil.computeAdd(cuMemberSettleDetailExt.getBBalance(), saOrderExt.getOrderAchieve()));
                    }
                    // 计算奖金  2部门和1部门碰  2部门和3部门碰
                    int leftDept = sourceMemberSettleExt.getPlaceDept() - 1;
                    if (leftDept >= EPlaceDept.LEFT_DEPT.getValue()) {
                        if (cuMemberSettleDetailExtMap.containsKey(leftDept)) {
                            CuMemberSettleDetailExt leftCuMemberSettleExt = cuMemberSettleDetailExtMap.get(leftDept);
                            // 获取等级封顶值
                            CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
                            while (ComputeUtil.compareValue(bdGrade.getTouchPv()) && ComputeUtil.compareValue(leftCuMemberSettleExt.getBBalance(), bdGrade.getTouchPv()) &&
                                    ComputeUtil.compareValue(cuMemberSettleDetailExt.getABalance(), bdGrade.getTouchPv())) {
                                // 扣减a、b区结余
                                leftCuMemberSettleExt.setBBalance(ComputeUtil.computeSubtract(leftCuMemberSettleExt.getBBalance(), bdGrade.getTouchPv()));
                                cuMemberSettleDetailExt.setABalance(ComputeUtil.computeSubtract(cuMemberSettleDetailExt.getABalance(), bdGrade.getTouchPv()));
                                calculateExpandBonusByTouch(riskControlMap, weekMemberBonusMap, systemConfigMap, bonusConfigDTO, settleDate, saOrderExt, cuMemberBonusExpandList, sourceMemberSettleExt, bdGrade, targetMemberSettleExt, cuMemberBonus, touchNum, cuMemberSettleDetailExt);
                                touchNum++;
                            }
                        }
                    }
                    int rightDept = sourceMemberSettleExt.getPlaceDept() + 1;
                    if (cuMemberSettleDetailExtMap.containsKey(rightDept)) {
                        CuMemberSettleDetailExt rightCuMemberSettleExt = cuMemberSettleDetailExtMap.get(rightDept);
                        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
                        while (ComputeUtil.compareValue(bdGrade.getTouchPv()) && ComputeUtil.compareValue(cuMemberSettleDetailExt.getBBalance(), bdGrade.getTouchPv()) && ComputeUtil.compareValue(rightCuMemberSettleExt.getABalance(), bdGrade.getTouchPv())) {
                            // 扣减a、b区结余
                            cuMemberSettleDetailExt.setBBalance(ComputeUtil.computeSubtract(cuMemberSettleDetailExt.getBBalance(), bdGrade.getTouchPv()));
                            rightCuMemberSettleExt.setABalance(ComputeUtil.computeSubtract(rightCuMemberSettleExt.getABalance(), bdGrade.getTouchPv()));
                            calculateExpandBonusByTouch(riskControlMap, weekMemberBonusMap, systemConfigMap, bonusConfigDTO, settleDate, saOrderExt, cuMemberBonusExpandList, sourceMemberSettleExt, bdGrade, targetMemberSettleExt, cuMemberBonus, touchNum, rightCuMemberSettleExt);
                            touchNum ++;
                        }
                    }
                }
            }
            // 处理各个国家的业绩组成
            List<CuMemberSettleCountryExt> cuMemberSettleCountryExtList = targetMemberSettleExt.getCuMemberSettleCountryExtList();
            if(CollectionUtil.isEmpty(cuMemberSettleCountryExtList)){
                cuMemberSettleCountryExtList = new ArrayList<>();
                packageCuMemberSettleCountry(saOrderExt, sourceMemberSettleExt, cuMemberSettleCountryExtList, bonusConfigDTO);
            }else{
                Map<String, CuMemberSettleCountryExt> cuMemberSettleCountryExtHashMap = new HashMap<>();
                cuMemberSettleCountryExtList.forEach(cuMemberSettleCountryExt ->
                        cuMemberSettleCountryExtHashMap.put(cuMemberSettleCountryExt.getPlaceDept() + "_" + cuMemberSettleCountryExt.getPkCountry(), cuMemberSettleCountryExt));
                String key = sourceMemberSettleExt.getPlaceDept() + "_" + saOrderExt.getPkCountry();
                if(cuMemberSettleCountryExtHashMap.containsKey(key)) {
                    CuMemberSettleCountryExt cuMemberSettleCountryExt = cuMemberSettleCountryExtHashMap.get(key);
                    cuMemberSettleCountryExt.setNewAmount(ComputeUtil.computeAdd(cuMemberSettleCountryExt.getNewAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
                    cuMemberSettleCountryExt.setNewPv(ComputeUtil.computeAdd(cuMemberSettleCountryExt.getNewPv(), saOrderExt.getOrderAchieve()));
                }else{
                    packageCuMemberSettleCountry(saOrderExt, sourceMemberSettleExt, cuMemberSettleCountryExtList, bonusConfigDTO);
                }
            }
            targetMemberSettleExt.setCuMemberSettleCountryExtList(cuMemberSettleCountryExtList);
        }
        return cuMemberBonusExpandList;
    }

    private void packageCuMemberSettleCountry(SaOrderExt saOrderExt, CuMemberSettleExt sourceMemberSettleExt, List<CuMemberSettleCountryExt> cuMemberSettleCountryExtList, BonusConfigDTO bonusConfigDTO) {
        CuMemberSettleCountryExt cuMemberSettleCountryExt = CuMemberSettleCountryExt.builder()
                .pkMember(sourceMemberSettleExt.getPkPlaceParent())
                .placeDept(sourceMemberSettleExt.getPlaceDept())
                .pkCountry(saOrderExt.getPkCountry())
                .newAmount(convertLocalCurrency(saOrderExt, bonusConfigDTO))
                .newPv(saOrderExt.getOrderAchieve())
                .build();
        cuMemberSettleCountryExtList.add(cuMemberSettleCountryExt);
    }

    private void calculateExpandBonusByTouch(Map<Long, CuMemberRiskControl> riskControlMap, Map<Long, CuMemberBonus> weekMemberBonusMap, Map<String, String> systemConfigMap, BonusConfigDTO bonusConfigDTO, String settleDate, SaOrderExt saOrderExt, List<CuMemberBonusExpand> cuMemberBonusExpandList, CuMemberSettleExt sourceMemberSettleExt, BdGrade bdGrade,
                                             CuMemberSettleExt targetMemberSettleExt, CuMemberBonus cuMemberBonus, int touchNum, CuMemberSettleDetailExt rightCuMemberSettleExt) {
        // 计算奖金
        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();
            }
        }
        CuMemberBonusExpand cuMemberBonusExpand = getCuMemberBonusExpand(saOrderExt, settleDate, touchNum, targetMemberSettleExt, bdGrade.getTouchBonus(), cuMemberBonus, bdGrade.getTouchPv(), pkBonusItems);
        // 计算收益 先计算出会员最大的收益
        // 获取等级对应的封顶值
        BigDecimal touchBonus = bdGrade.getTouchBonus();
        // K值设置
        if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
            touchBonus = ComputeUtil.computeBonusMultiply(touchBonus, riskControlMap.get(cuMemberBonus.getPkMember()).getExpandRatio());
            cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.RISK_CONTROL.getValue());
        }
        BigDecimal expandIncome = ComputeUtil.computeAdd(ComputeUtil.computeAdd(rightCuMemberSettleExt.getExpandCapping(), touchBonus), weekExpandIncome);
        // 判断收益 是否超过封顶值，超过的话变为封顶值
        // 判断是否烧伤，判断原奖金是否>=封顶值,奖金到了就是烧伤
        // 验证会员状态 封停状态跟冻结都正常计算奖金，封停的账号发放的时候奖金发放为0，冻结的账号正常发放，不能登录
        cuMemberBonusExpand.setPretaxIncome(bdGrade.getTouchBonus());
        if (ComputeUtil.compareValue(ComputeUtil.computeAdd(rightCuMemberSettleExt.getExpandCapping(), weekExpandIncome), bdGrade.getExpandCapping())) {
            cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
            expandIncome =  ComputeUtil.computeSubtract(bdGrade.getExpandCapping(), weekExpandIncome);
            touchBonus = BigDecimal.ZERO;
        } else if (ComputeUtil.compareGreaterThan(expandIncome, bdGrade.getExpandCapping())) {
            BigDecimal realIncome = ComputeUtil.computeSubtract(ComputeUtil.computeSubtract(bdGrade.getExpandCapping(), weekExpandIncome), cuMemberBonus.getExpandIncome());
            //存在一半烧伤一半正常的值，拆2条
            // 拓展明细表 进行修改
            cuMemberBonusExpand.setPretaxIncome(realIncome);
            CuMemberBonusExpand fireCuMemberBonusExpand = BeanUtil.copyProperties(cuMemberBonusExpand, CuMemberBonusExpand.class);
            BigDecimal fireIncome = ComputeUtil.computeSubtract(expandIncome, realIncome);
            fireCuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
            fireCuMemberBonusExpand.setPretaxIncome(fireIncome);
            // 收益占比
            setBonusDetailDeduct(bonusConfigDTO, fireCuMemberBonusExpand, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
            expandRemark(saOrderExt, fireCuMemberBonusExpand, sourceMemberSettleExt, targetMemberSettleExt);
            cuMemberBonusExpandList.add(fireCuMemberBonusExpand);
            // 拓展收益取封顶最大值
            expandIncome = ComputeUtil.computeSubtract(bdGrade.getExpandCapping(), weekExpandIncome);
            touchBonus = realIncome;
        }
        // 收益占比
        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 (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusExpand.getIncomeStatus() ||
                EBonusIncomeStatus.RISK_CONTROL.getValue() == cuMemberBonusExpand.getIncomeStatus()) {
            // 判断会员状态，会员状态为封停的话状态修改为停收
            cuMemberBonus.setExpandIncome(ComputeUtil.computeAdd(cuMemberBonus.getExpandIncome(), touchBonus));
//            cuMemberBonus.setExpandIncome(ComputeUtil.computeSubtract(expandIncome, weekExpandIncome));
            rightCuMemberSettleExt.setExpandCapping(expandIncome);
            setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusExpand);
        }
        cuMemberBonusExpandList.add(cuMemberBonusExpand);
    }

    /**
     * @param settleTableName      结算表
     * @param period               期间
     * @param settleDate           结算日期
     * @param bonusConfigDTO       参数
     * @param firPurchaseOrderList 订单列表
     * @param cuMemberBonusMap     所有计算出来的奖金汇总
     * @Description: 计算见点收益
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/10 14:17
     */
    List<CuMemberBonusCoach> calculateSeePointBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleTableNameDetail, String settleDate, BonusConfigDTO bonusConfigDTO,
                                                    List<SaOrderExt> firPurchaseOrderList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, CuMemberRiskControl> riskControlMap) {
        Set<Long> expandMemberSet = new HashSet<>();
        firPurchaseOrderList.forEach(saOrderExt ->
                expandMemberSet.add(saOrderExt.getPkMember()));
        // 1.查找会员血缘伞上
        // 2.计算会员血缘伞上累计业绩，新增业绩
        // 3.获取等级列表，获取各个等级的见点代数
        // 4。验证会员等级是否大于等于当前等级，代数，验证是否满足资格
        List<CuMemberSettleExt> cuMemberSettleExtList = cuMemberTreeService.batchCuMemberSettlePlaceParent(settleTableName, settleTableNameDetail, expandMemberSet);
        // 初始化父类网体的值
        getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
        Map<String, CuMemberSettleExt> memberSettleExtMap = new HashMap<>();
        for (CuMemberSettleExt cuMemberSettleExt : cuMemberSettleExtList) {
            String key = cuMemberSettleExt.getPkPlaceParent() + "_" + cuMemberSettleExt.getPlaceDept();
            memberSettleExtMap.put(key, cuMemberSettleExtMap.get(cuMemberSettleExt.getPkPlaceParent()));
        }
        List<CuMemberBonusCoach> cuMemberBonusCoachList = new ArrayList<>();
        for (SaOrderExt saOrderExt : firPurchaseOrderList) {
            List<CuMemberBonusCoach> cuMemberBonusSeePointS = calculateBonusSeePoint(cuMemberSettleExtMap, memberSettleExtMap, bonusConfigDTO, settleDate, period, cuMemberBonusMap, saOrderExt, riskControlMap);
            if (cuMemberBonusSeePointS.size() > 0) {
                cuMemberBonusCoachList.addAll(cuMemberBonusSeePointS);
            }
        }
        return cuMemberBonusCoachList;
    }

    /**
     * @Description: 计算领导奖
     * @return: List<CuMemberBonusCoach>
     * @Author: sui q
     * @Date: 2023/2/8 17:16
     */
    private List<CuMemberBonusCoach> calculateBonusSeePoint(Map<Long, CuMemberSettleExt> totalSettleExtMap, Map<String, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO, String settleDate, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                            SaOrderExt saOrderExt, Map<Long, CuMemberRiskControl> riskControlMap) {
        List<CuMemberBonusCoach> backMemberBonusCoachList = new ArrayList<>();
        CuMemberSettleExt sourceMemberSettleExt = totalSettleExtMap.get(saOrderExt.getPkMember());
        String targetKey = sourceMemberSettleExt.getPkPlaceParent() + "_" + sourceMemberSettleExt.getPlaceDept();
        List<BdGrade> gradeList = bonusConfigDTO.getSeePointGradeMap().get(sourceMemberSettleExt.getPkSettleCountry());
        if(CollectionUtil.isEmpty(gradeList)){
            return backMemberBonusCoachList;
        }
        Map<String, BdGrade> gradeMap = new LinkedHashMap<>();
        for (BdGrade bdGrade : gradeList) {
            gradeMap.put(bdGrade.getPkCountry().toString() + "_" + bdGrade.getPkId(), bdGrade);
        }
//        Long pkParent = sourceMemberSettleExt.getPkParent();
        int coachGeneration = 0;
        int beforeAlgebra = 0;
        for (String key : gradeMap.keySet()) {
            BdGrade bdGrade = gradeMap.get(key);
            int algebra = bdGrade.getAlgebra() - beforeAlgebra;
            boolean flag = false;
            while (algebra > 0) {
                CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(targetKey);
                if (targetMemberSettleExt == null) {
                    flag = true;
                    break;
                }
                targetKey = targetMemberSettleExt.getPkPlaceParent() + "_" + targetMemberSettleExt.getPlaceDept();
//                pkParent = targetMemberSettleExt.getPkParent();
                // 验证会员是否有奖金，判断有效期是否大于结算日期
                if (ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory()
                ||validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.SEE_POINT_INCOME.getValue())
                        || targetMemberSettleExt.getGradeValue() < bdGrade.getGradeValue()) {
                    continue;
                }
                algebra--;
                coachGeneration++;
                CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
                // 判断会员状态
                CuMemberBonusCoach cuMemberBonusCoach = getCuMemberBonusSeePoint(bonusConfigDTO, saOrderExt, coachGeneration, targetMemberSettleExt, bdGrade.getSeePointRatio());
                if(validateExistBonus(targetMemberSettleExt, settleDate)){
                    cuMemberBonusCoach.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
                }
                if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
                    cuMemberBonusCoach.setPretaxIncome(ComputeUtil.computeBonusMultiply(cuMemberBonusCoach.getPretaxIncome(), riskControlMap.get(cuMemberBonus.getPkMember()).getSeePointAward()));
                    cuMemberBonusCoach.setIncomeStatus(EBonusIncomeStatus.RISK_CONTROL.getValue());
                }
                // 判断考核状态，是否考核通过
                // 收益占比
                BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusCoach, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                seePointRemark(saOrderExt, cuMemberBonusCoach, sourceMemberSettleExt, targetMemberSettleExt);
                if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
                    cuMemberBonusCoach.setRemark(cuMemberBonusCoach.getRemark() + ",K值比例:" + riskControlMap.get(cuMemberBonus.getPkMember()).getSeePointAward());
                }
                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusCoach.getIncomeStatus() ||
                        EBonusIncomeStatus.RISK_CONTROL.getValue() == cuMemberBonusCoach.getIncomeStatus()) {
                    cuMemberBonus.setSeePointIncome(ComputeUtil.computeAdd(cuMemberBonus.getSeePointIncome(), cuMemberBonusCoach.getPretaxIncome()));
                    setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusCoach);
                }
                backMemberBonusCoachList.add(cuMemberBonusCoach);
            }
            if(bdGrade.getAlgebra() > beforeAlgebra) {
                beforeAlgebra = bdGrade.getAlgebra();
            }
            if (flag) {
                break;
            }
        }
        return handleCoachRemark(backMemberBonusCoachList, coachGeneration);
    }

    /**
     * @param settleTableName         结算表
     * @param period                  期间
     * @param settleDateStr           结算日期
     * @param bonusConfigDTO          参数
     * @param firPurchaseOrderList    订单列表
     * @param cuMemberBonusExpandList 量奖明细
     * @param cuMemberBonusMap        所有计算出来的奖金汇总
     * @Description: 计算辅导收益
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/10 14:17
     */
    List<CuMemberBonusCoach> calculateCoachBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleTableNameDetail, String settleDateStr, BonusConfigDTO bonusConfigDTO,
                                                 List<SaOrderExt> firPurchaseOrderList, List<CuMemberBonusExpand> cuMemberBonusExpandList, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                                 Map<Long, CuAwardsControl> cuAwardsControlMap, Map<Long, CuMemberRiskControl> riskControlMap) {
        Map<Long, SaOrderExt> saOrderExtMap = new HashMap<>(ComputeUtil.mapInitCapacity(firPurchaseOrderList.size()));
        firPurchaseOrderList.forEach(saOrderExt ->
                saOrderExtMap.put(saOrderExt.getPkId(), saOrderExt));
        return calculateCoachBonusOne(cuMemberSettleExtMap, settleTableName, settleTableNameDetail, settleDateStr, bonusConfigDTO, cuMemberBonusExpandList, period, cuMemberBonusMap, saOrderExtMap, cuAwardsControlMap, riskControlMap);
    }

    /**
     * @Description: 计算领导奖
     * @return: List<CuMemberBonusCoach>
     * @Author: sui q
     * @Date: 2023/2/8 17:16
     */
    List<CuMemberBonusCoach> calculateCoachBonusOne(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleTableNameDetail, 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<CuMemberBonusCoach> cuMemberBonusCoachList = new ArrayList<>();
        if (cuMemberBonusExpandList.size() > 0) {
            Set<Long> expandMemberSet = getMemberExpandBonus(cuMemberBonusMap, cuMemberBonusExpandList);
            List<CuMemberSettleExt> cuMemberSettleExtList = cuMemberTreeService.batchQueryCuMemberSettleParent(settleTableName, settleTableNameDetail, expandMemberSet);
            // 初始化父类网体的值
            getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
            // 获取复购考核结果
            // 开始计算辅导奖，往上找10代血缘，判断血缘的奖衔是否>= 5的倍数
            Map<Long, CuMemberSettleExt> bonusIdSettleMap = getMemberExpandBonus(cuMemberSettleExtMap);
            for (CuMemberBonusExpand cuMemberBonusExpand : cuMemberBonusExpandList) {
                List<CuMemberBonusCoach> coachBonusList = calculateBonusCoach(cuMemberSettleExtMap, settleDateStr, bonusConfigDTO, period, cuMemberBonusMap, saOrderExtMap, bonusIdSettleMap, cuMemberBonusExpand, cuAwardsControlMap, riskControlMap);
                if (coachBonusList.size() > 0) {
                    cuMemberBonusCoachList.addAll(coachBonusList);
                }
            }
        }
        return cuMemberBonusCoachList;
    }

    /**
     * @Description: 计算领导奖
     * @return: List<CuMemberBonusCoach>
     * @Author: sui q
     * @Date: 2023/2/8 17:16
     */
    private List<CuMemberBonusCoach> calculateBonusCoach(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleDate, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, SaOrderExt> saOrderExtMap, Map<Long, CuMemberSettleExt> bonusIdSettleMap,
                                                         CuMemberBonusExpand cuMemberBonusExpand, Map<Long, CuAwardsControl> cuAwardsControlMap, Map<Long, CuMemberRiskControl> riskControlMap) {
        CuMemberSettleExt sourceMemberSettleExt = bonusIdSettleMap.get(cuMemberBonusExpand.getPkBonus());
        Long pkMember = cuMemberSettleExtMap.get(cuMemberBonusExpand.getPkBonus()).getPkParent();
        // 获得量奖的人往上找10代血缘
        // 用于回写血缘总共多少代
        List<CuMemberBonusCoach> backMemberBonusCoachList = new ArrayList<>();
        int coachGeneration;
        for (coachGeneration = MagicNumberConstants.BLOOD_GENERATION_START; coachGeneration <= MagicNumberConstants.BLOOD_GENERATION_END; coachGeneration++) {
            CuMemberSettleExt targetMemberSettleExt = cuMemberSettleExtMap.get(pkMember);
            if (targetMemberSettleExt == null) {
                break;
            }
            pkMember = targetMemberSettleExt.getPkParent();
            if (ECategory.NORMAL.getValue() != targetMemberSettleExt.getCategory() ||
                    EAccountStatus.STOP_INCOME.getValue() == targetMemberSettleExt.getAccountStatus() ||
                    validatePkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.COACHING_INCOME.getValue()) ||
                    validateExistBonus(targetMemberSettleExt, settleDate)) {
                coachGeneration--;
                continue;
            }
            SaOrderExt saOrderExt = saOrderExtMap.get(cuMemberBonusExpand.getPkOrder());
            CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrderExt, targetMemberSettleExt);
            BdAwards awardsCouch = getBdAwards(bonusConfigDTO, targetMemberSettleExt, cuAwardsControlMap);
            // 判断是否有奖金
            if (awardsCouch.getAwardsValue() >= MagicNumberConstants.BLOOD_GENERATION_SERIES * coachGeneration) {
                BdAwards coachAward = bonusConfigDTO.getAwardsValueMap().get(targetMemberSettleExt.getPkSettleCountry().toString() + ERangeType.AWARDS.getValue() + MagicNumberConstants.BLOOD_GENERATION_SERIES * coachGeneration);
                BigDecimal awardCalRadio = BigDecimal.ZERO;
                if (coachAward != null) {
                    awardCalRadio = coachAward.getCoachRatio();
                }
                // 判断会员状态
                CuMemberBonusCoach cuMemberBonusCoach = getCuMemberBonusCoach(bonusConfigDTO, cuMemberBonusExpand, coachGeneration, targetMemberSettleExt, awardCalRadio);
                // 判断考核状态，是否考核通过
                // K值设置
                if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
                    cuMemberBonusCoach.setPretaxIncome(ComputeUtil.computeBonusMultiply(cuMemberBonusCoach.getPretaxIncome(), riskControlMap.get(cuMemberBonus.getPkMember()).getManagerRatio()));
                    cuMemberBonusCoach.setIncomeStatus(EBonusIncomeStatus.RISK_CONTROL.getValue());
                }
                // 收益占比
                BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusCoach, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                coachRemark(saOrderExt, cuMemberBonusCoach, sourceMemberSettleExt, targetMemberSettleExt);
                if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
                    cuMemberBonusCoach.setRemark(cuMemberBonusCoach.getRemark() + ",K值比例:" + riskControlMap.get(cuMemberBonus.getPkMember()).getManagerRatio());
                }
                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusCoach.getIncomeStatus() ||
                        EBonusIncomeStatus.RISK_CONTROL.getValue() == cuMemberBonusCoach.getIncomeStatus()) {
                    cuMemberBonus.setCoachIncome(ComputeUtil.computeAdd(cuMemberBonus.getCoachIncome(), cuMemberBonusCoach.getPretaxIncome()));
                    // 等额获得全球积分
                    cuMemberBonus.setGlobalPoints(cuMemberBonus.getCoachIncome());
                    setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusCoach);
                }
                backMemberBonusCoachList.add(cuMemberBonusCoach);
            }else {
                coachGeneration--;
            }
        }
        return handleCoachRemark(backMemberBonusCoachList, coachGeneration);
    }

    /**
     * @param settleTableName  结算表
     * @param period           期间
     * @param bonusConfigDTO   参数
     * @param cuMemberBonusMap 所有计算出来的奖金汇总
     * @Description: 计算领袖收益  自己新增大区pv * 领袖奖比例 * 自己小区之和/ 其他组内所有成员小区之和
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/10 14:17
     */
    List<CuMemberBonusDetail> calculateLeaderBonus(String settleTableName, String settleTableNameDetail, String settleDate, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, Map<Long, CuMemberRiskControl> riskControlMap) {
        List<CuMemberSettleExt> cuMemberSettleExtList = cuMemberTreeService.queryEnoughLeaderCuMemberSettle(settleTableName, settleTableNameDetail);
        List<CuMemberBonusDetail> cuMemberBonusDetailList = new ArrayList<>();
        if (cuMemberSettleExtList.size() > 0) {
            // 初始化父类网体的值
            Map<Long, CuMemberSettleExt> cuMemberSettleExtMap = new HashMap<>();
            getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
            Map<BigDecimal, List<CuMemberSettleExt>> memberSettleMap = new HashMap<>();
            // 获取伞下
//            Map<Long, List<CuMemberSettleExt>> placeParentMemberSettleMap = new HashMap<>();
            for (CuMemberSettleExt cuMemberSettleExt : cuMemberSettleExtList) {
                if(ComputeUtil.compareValue(cuMemberSettleExt.getAbonusRatio())){
                    if (memberSettleMap.containsKey(cuMemberSettleExt.getAbonusRatio())) {
                        memberSettleMap.get(cuMemberSettleExt.getAbonusRatio()).add(cuMemberSettleExt);
                    } else {
                        List<CuMemberSettleExt> memberSettleExtList = new ArrayList<>();
                        memberSettleExtList.add(cuMemberSettleExt);
                        memberSettleMap.put(cuMemberSettleExt.getAbonusRatio(), memberSettleExtList);
                    }
//                    if (placeParentMemberSettleMap.containsKey(cuMemberSettleExt.getPkPlaceParent())) {
//                        placeParentMemberSettleMap.get(cuMemberSettleExt.getPkPlaceParent()).add(cuMemberSettleExt);
//                    } else {
//                        List<CuMemberSettleExt> memberSettleExtList = new ArrayList<>();
//                        memberSettleExtList.add(cuMemberSettleExt);
//                        placeParentMemberSettleMap.put(cuMemberSettleExt.getPkPlaceParent(), memberSettleExtList);
//                    }
                }
            }
            for (BigDecimal bonusRation : memberSettleMap.keySet()) {
                // 按照比例进行分组，计算组内 小区之和
                List<CuMemberSettleExt> memberSettleExtList = memberSettleMap.get(bonusRation);
                BigDecimal allAddSmallPv = BigDecimal.ZERO;
                for (CuMemberSettleExt cuMemberSettleExt : memberSettleExtList) {
                    // 计算大小区
                    BigDecimal bigAreaPv = BigDecimal.ZERO;
                    BigDecimal smallAreaPv = BigDecimal.ZERO;
                    List<CuMemberSettleDetailExt> cuMemberSettleDetailExtList = cuMemberSettleExt.getCuMemberSettleDetailExtList();
                    if(CollectionUtil.isNotEmpty(cuMemberSettleDetailExtList)) {
                        for (int i = 1; i < cuMemberSettleDetailExtList.size(); i++) {
                            CuMemberSettleDetailExt cuMemberSettleDetailExt = cuMemberSettleDetailExtList.get(i);
                            BigDecimal addNewPv = cuMemberSettleDetailExt.getMonNewPv();
                            if (ComputeUtil.compareValue(bigAreaPv, addNewPv)) {
                                smallAreaPv = addNewPv;
                            } else {
                                smallAreaPv = bigAreaPv;
                                bigAreaPv = addNewPv;
                            }
                        }
                        cuMemberSettleExt.setBigAreaPv(bigAreaPv);
                        cuMemberSettleExt.setSmallAreaPv(smallAreaPv);
                        allAddSmallPv = ComputeUtil.computeAdd(allAddSmallPv, smallAreaPv);
                    }
                    // 会员伞下数据
//                    if (placeParentMemberSettleMap.containsKey(cuMemberSettleExt.getPkPlaceParent())) {
////                        List<CuMemberSettleExt> placeParentMemberList = placeParentMemberSettleMap.get(cuMemberSettleExt.getPkPlaceParent());
//                        // 查询出大区， 小区业绩之和
//                        // 由于这是会员伞下数据，会员伞下业绩 = 伞下的伞下业绩 + 自己;
//                        BigDecimal bigAreaPv = BigDecimal.ZERO;
//                        BigDecimal smallAreaPv = BigDecimal.ZERO;
//                        for (int i = 1; i < placeParentMemberList.size(); i++) {
//                            CuMemberSettleExt memberSettleExt = placeParentMemberList.get(i);
//                            Map<Integer, CuMemberSettleDetailExt> cuMemberSettleDetailExtMap = new HashMap<>();
//                            memberSettleExt.getCuMemberSettleDetailExtList().forEach(cuMemberSettleDetailExt ->
//                                    cuMemberSettleDetailExtMap.put(cuMemberSettleDetailExt.getPlaceDept(), cuMemberSettleDetailExt));
//                            BigDecimal addNewPv = ComputeUtil.computeAdd(memberSettleExt.getMonNewPv(), memberSettleExt.getRegisterMonNewPv());
//                            if (ComputeUtil.compareValue(bigAreaPv, addNewPv)) {
//                                smallAreaPv = addNewPv;
//                            } else {
//                                smallAreaPv = bigAreaPv;
//                                bigAreaPv = addNewPv;
//                            }
//                        }
//                        cuMemberSettleExt.setBigAreaPv(bigAreaPv);
//                        cuMemberSettleExt.setSmallAreaPv(smallAreaPv);
//                        allAddSmallPv = ComputeUtil.computeAdd(allAddSmallPv, smallAreaPv);
//                    }
                }
                if (ComputeUtil.compareValue(allAddSmallPv)) {
                    // 计算领袖奖 自己新增大区pv * 领袖奖比例 * 自己小区之和/ 其他组内所有成员小区之和
                    for (CuMemberSettleExt targetMemberSettleExt : memberSettleExtList) {
                        // 验证会员是否有奖金，判断有效期是否大于结算日期
                        if (validateExistBonus(targetMemberSettleExt, settleDate)) {
                            continue;
                        }
                        // 处理pk_rate
                        SaOrder saOrder = SaOrder.builder()
                                .pkId(0L)
                                .orderAchieve(targetMemberSettleExt.getSmallAreaPv())
                                .build();
                        saOrder.setPkCountry(targetMemberSettleExt.getPkCountry());
                        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, saOrder, targetMemberSettleExt);
                        BigDecimal leaderIncome = ComputeUtil.computeDivide(ComputeUtil.computeMultiply(ComputeUtil.computeBonusMultiply(targetMemberSettleExt.getBigAreaPv(), bonusRation), targetMemberSettleExt.getSmallAreaPv()),
                                allAddSmallPv);
                        // 领袖奖金明细
                        CuMemberBonusDetail cuMemberBonusDetail = getCuMemberBonusDetail(saOrder, targetMemberSettleExt, cuMemberBonus);
                        cuMemberBonusDetail.setPkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.DIVIDEND_INCOME.getValue()));
                        cuMemberBonusDetail.setCalValue(bonusRation);
                        cuMemberBonusDetail.setPretaxIncome(leaderIncome);
                        // K值设置
                        if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
                            cuMemberBonusDetail.setPretaxIncome(ComputeUtil.computeBonusMultiply(cuMemberBonusDetail.getPretaxIncome(), riskControlMap.get(cuMemberBonus.getPkMember()).getManagerRatio()));
                            cuMemberBonusDetail.setIncomeStatus(EBonusIncomeStatus.RISK_CONTROL.getValue());
                        }
                        leaderShareRemark(cuMemberBonusDetail, period, targetMemberSettleExt.getBigAreaPv(), targetMemberSettleExt.getSmallAreaPv(), allAddSmallPv, bonusRation);
                        if (riskControlMap.containsKey(cuMemberBonus.getPkMember())) {
                            cuMemberBonusDetail.setRemark(cuMemberBonusDetail.getRemark() + ",K值比例:" + riskControlMap.get(cuMemberBonus.getPkMember()).getManagerRatio());
                        }
                        BdBonusDeduct bdBonusDeduct = bonusConfigDTO.getBonusDeductsMap().get(cuMemberBonusDetail.getPkBonusItems());
                        BigDecimal incomeTax = BigDecimal.ZERO;
                        if (bdBonusDeduct != null) {
                            incomeTax = ComputeUtil.computeBonusMultiply(cuMemberBonusDetail.getPretaxIncome(), ComputeUtil.computeAdd(bdBonusDeduct.getPlatformRatio(), bdBonusDeduct.getBackRatio()));
                        }
                        cuMemberBonusDetail.setIncomeTax(incomeTax);
                        cuMemberBonusDetail.setRealIncome(ComputeUtil.computeSubtract(cuMemberBonusDetail.getPretaxIncome(), cuMemberBonusDetail.getIncomeTax()));
                        cuMemberBonusDetail.setPkCountry(targetMemberSettleExt.getPkSettleCountry());
                        cuMemberBonusDetail.setPkCreator(MagicNumberConstants.PK_ADMIN);
                        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusDetail.getIncomeStatus() ||
                                EBonusIncomeStatus.RISK_CONTROL.getValue() == cuMemberBonusDetail.getIncomeStatus()) {
                            cuMemberBonus.setShareIncome(ComputeUtil.computeAdd(cuMemberBonus.getShareIncome(), cuMemberBonusDetail.getPretaxIncome()));
                            setFirstPurchaseTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusDetail);
                        }
                        cuMemberBonusDetailList.add(cuMemberBonusDetail);
                    }
                }
            }
        }
        return cuMemberBonusDetailList;
    }

    /**
     * 判断是否是服务中心，服务中心算主任
     *
     * @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) {
        CuMemberBonusCoach cuMemberBonusCoach = CuMemberBonusCoach.builder()
                .pkBonus(targetMemberSettleExt.getPkMember())
                .pkOrder(cuMemberBonusExpand.getPkOrder())
                .pkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.COACHING_INCOME.getValue()))
                .calType(ECalType.RATIO.getValue())
                .incomeStatus(cuMemberBonusExpand.getIncomeStatus())
                .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);
        return cuMemberBonusCoach;
    }

    private CuMemberBonusCoach getCuMemberBonusSeePoint(BonusConfigDTO bonusConfigDTO, SaOrderExt saOrderExt,
                                                        int i, CuMemberSettleExt targetMemberSettleExt, BigDecimal awardCalRadio) {
        CuMemberBonusCoach cuMemberBonusCoach = CuMemberBonusCoach.builder()
                .pkBonus(targetMemberSettleExt.getPkMember())
                .pkOrder(saOrderExt.getPkId())
                .pkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberSettleExt.getPkSettleCountry(), EBonusItems.SEE_POINT_INCOME.getValue()))
                .calType(ECalType.RATIO.getValue())
                .incomeStatus(EIncomeStatus.NORMAL.getValue())
                .calAchieve(saOrderExt.getOrderAchieve())
                .currentGeneration(i)
                // 计算比例
                .calValue(awardCalRadio)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .coachNoCapping(BigDecimal.ZERO)
                .coachCapping(BigDecimal.ZERO)
                .coachNormalHalf(BigDecimal.ZERO)
                .coachNormalReal(BigDecimal.ZERO)
                .pretaxIncome(ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), awardCalRadio))
                .build();
        cuMemberBonusCoach.setPkCountry(targetMemberSettleExt.getPkSettleCountry());
        cuMemberBonusCoach.setPkCreator(MagicNumberConstants.PK_ADMIN);
        return cuMemberBonusCoach;
    }

    /**
     * @param backMemberBonusCoachList 临时记录辅导奖列表
     * @param i                        第几代
     * @Description: 处理拓展表备注
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/17 18:02
     */
    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;
    }

}
