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

import com.hzs.bonus.achieve.service.ICuMemberRangeService;
import com.hzs.bonus.base.service.ICuMemberService;
import com.hzs.bonus.detail.service.ICuMemberAwardsService;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.TableNameConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.domain.bonus.BdBonusDeduct;
import com.hzs.common.domain.member.achieve.ext.CuMemberRangeExt;
import com.hzs.common.domain.member.bonus.*;
import com.hzs.common.domain.member.detail.CuMemberAwards;
import com.hzs.common.domain.member.ext.BdWaresBonusExt;
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.system.config.BdRangeAwards;
import com.hzs.system.config.dto.BonusConfigDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * 计算乐享极差收益
 */
@Component
public class BonusSettleRangeHandle extends BonusSettleHandle {

    @Autowired
    private ICuMemberRangeService iCuMemberRangeService;
    @Autowired
    private ICuMemberAwardsService iCuMemberAwardsService;
    @Autowired
    private ICuMemberService iCuMemberService;

    /**
     * 实时计算当月奖衔
     */
    Map<Long, CuMemberRangeExt> calculateCuMemberRangeAwardsByDay(SaOrderExt saOrderExt, List<BdRangeAwards> rangeAwardsList, String secondRangeTableName, int beforePeriod, int currentPeriod) {
        String rangeTableName = TableNameConstants.CU_MEMBER_RANGE + beforePeriod;
        iCuMemberRangeService.mergeMemberSecondRangeByRange(rangeTableName, secondRangeTableName, saOrderExt.getPkMember());
        // 极差奖衔封装为2个treeMap
        Map<Integer, BdRangeAwards> consumeRangeAwardsMap = new TreeMap<>();
        Map<Integer, BdRangeAwards> bloodRangeAwardsMap = new TreeMap<>();
        packageRangeAwardsByType(rangeAwardsList, consumeRangeAwardsMap, bloodRangeAwardsMap);
        // 按照血缘，查询该会员所有伞上会员
        Map<Long, List<CuMemberRangeExt>> parentRangeExtMap = iCuMemberRangeService.queryCuMemberSecondRangeParent(rangeTableName, secondRangeTableName, saOrderExt.getPkMember());
        Map<Long, CuMemberRangeExt> memberRangeExtMap = getMemberSettle(parentRangeExtMap);
        // 计算奖衔
        // 先算团队奖衔，计算完奖金后在计算消费奖衔，计算完奖衔计算奖金
        // 计算自消费奖衔
        CuMemberRangeExt sourceMemberRangeExt = memberRangeExtMap.get(saOrderExt.getPkMember());
        CuMemberRangeExt targetMemberRangeExt = memberRangeExtMap.get(sourceMemberRangeExt.getPkParent());
        // 个人累计消费pv
        sourceMemberRangeExt.setConsumePv(ComputeUtil.computeAdd(sourceMemberRangeExt.getConsumePv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
        sourceMemberRangeExt.setNewPv(ComputeUtil.computeAdd(sourceMemberRangeExt.getNewPv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
        // 个人月消费pv,当月会员且当月有消费，推荐有效数量+1
        if (sourceMemberRangeExt.getMonthMember() == EYesNo.YES.getIntValue() && ComputeUtil.compareEqual(sourceMemberRangeExt.getMonthPv(), BigDecimal.ZERO)) {
            targetMemberRangeExt.setEffectiveNum(targetMemberRangeExt.getEffectiveNum() + 1);
            targetMemberRangeExt.setNewEffectiveNum(targetMemberRangeExt.getNewEffectiveNum() + 1);
        }
        sourceMemberRangeExt.setMonthPv(ComputeUtil.computeAdd(sourceMemberRangeExt.getMonthPv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
        // 奖衔升级记录
        List<CuMemberAwards> cuMemberAwardsList = new ArrayList<>();
        // 消费奖衔
        cuMemberAwardsList.addAll(calculateConsumeRangeAwards(currentPeriod, parentRangeExtMap, memberRangeExtMap, rangeTableName, sourceMemberRangeExt, saOrderExt, consumeRangeAwardsMap));
        // 团队奖衔
        cuMemberAwardsList.addAll(calculateBloodRangeAwards(currentPeriod, parentRangeExtMap, memberRangeExtMap, rangeTableName, saOrderExt, bloodRangeAwardsMap, sourceMemberRangeExt.getPkParent(), secondRangeTableName));
        if (cuMemberAwardsList.size() > 0) {
            iCuMemberAwardsService.saveBatchCuMemberAwards(cuMemberAwardsList);
            // 更新会员表,更新奖衔
            iCuMemberService.updateCuMemberRangeByPeriod(cuMemberAwardsList, currentPeriod);
        }
        return memberRangeExtMap;
    }

    void calculateRangeEvBonus(Map<Long, CuMemberBonus> cuMemberBonusMap, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberRangeExt> memberRangeExtMap, List<CuMemberBonusPush> cuMemberBonusPushList, List<BdWaresBonusExt> bdWaresBonusExtList, SaOrderExt saOrderExt) {
        CuMemberRangeExt sourceMemberRangeExt = memberRangeExtMap.get(saOrderExt.getPkMember());
        if (ComputeUtil.compareValue(saOrderExt.getOrderAssAchieve(), BigDecimal.valueOf(15.625))) {
            // 1= 自己购买了11单 2= 上3代拿 100 200 300 上3代各拿100 上11代各拿1100
            int specialWaresState = 0;
            BdWaresBonusExt calWaresBonusExt = null;
            for (SaOrderItemsExt saOrderItemsExt : saOrderExt.getOrderItemsExtList()) {
                boolean flag = Boolean.FALSE;
                if (bdWaresBonusExtList != null && bdWaresBonusExtList.size() > 0) {
                    for (BdWaresBonusExt bdWaresBonusExt : bdWaresBonusExtList) {
                        if (bdWaresBonusExt.getPkWares().equals(saOrderItemsExt.getPkWares())) {
                            specialWaresState = 2;
                            flag = Boolean.TRUE;
                            calWaresBonusExt = bdWaresBonusExt;
                            break;
                        }
                    }
                }
                if (flag) {
                    break;
                }
            }
            if (specialWaresState > 0) {
                sourceMemberRangeExt.setBuyEffectiveNum(sourceMemberRangeExt.getBuyEffectiveNum() + calWaresBonusExt.getTotalAlgebra());
                int algebra = 0;
                for (BdWaresBonusItems bdWaresBonusItems : calWaresBonusExt.getBdWaresBonusItemsList()) {
                    CuMemberBonusPush cuMemberBonusPush = calculatePushBonusOne(sourceMemberRangeExt, memberRangeExtMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt,
                            bdWaresBonusItems.getAlgebra() - algebra, bdWaresBonusItems.getAssAchieve(), cuMemberBonusPushList);
                    if (cuMemberBonusPush != null) {
                        sourceMemberRangeExt = memberRangeExtMap.get(cuMemberBonusPush.getPkBonus());
                        algebra = bdWaresBonusItems.getAlgebra();
                    }
                }
            } else {
                sourceMemberRangeExt.setBuyEffectiveNum(sourceMemberRangeExt.getBuyEffectiveNum() + 1);
                calculatePushBonusOne(sourceMemberRangeExt, memberRangeExtMap, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt,
                        sourceMemberRangeExt.getBuyEffectiveNum(), saOrderExt.getOrderAssAchieve(), cuMemberBonusPushList);
            }
        }
    }


    private void packageRangeAwardsByType(List<BdRangeAwards> rangeAwardsList, Map<Integer, BdRangeAwards> consumeRangeAwardsMap, Map<Integer, BdRangeAwards> bloodRangeAwardsMap) {
        for (BdRangeAwards bdRangeAwards : rangeAwardsList) {
            if (ComputeUtil.compareValue(bdRangeAwards.getConsumePv())) {
                consumeRangeAwardsMap.put(bdRangeAwards.getAwardsValue(), bdRangeAwards);
            }
            if (ComputeUtil.compareValue(bdRangeAwards.getTeamConsumeCheck())) {
                bloodRangeAwardsMap.put(bdRangeAwards.getAwardsValue(), bdRangeAwards);
            }
        }
    }

    /*
     *  先计算奖衔,奖衔计算分为2种，先计算自己消费足够的，S1-S3，S4以上的另一种方式，自消费的只有购买人，其他的都是根据业绩，注意，有人可以直接是S4
     * 先验证团队业绩，小区业绩，验证小市场需要从上往下走 s1只能通过自消费，除了购买人其他人丛S2开始升级
     * 计算个人消费奖项
     **/
    public List<CuMemberAwards> calculateConsumeRangeAwards(Integer period, Map<Long, List<CuMemberRangeExt>> parentRangeExtMap, Map<Long, CuMemberRangeExt> memberRangeExtMap, String rangeTableName,
                                                            CuMemberRangeExt sourceMemberRangeExt, SaOrderExt saOrderExt,
                                                            Map<Integer, BdRangeAwards> consumeRangeAwardsMap) {
        int rangeAwardsValue = 2;
        List<CuMemberAwards> cuMemberAwardsList = new ArrayList<>();
        while (consumeRangeAwardsMap.containsKey(sourceMemberRangeExt.getRangeAwardsValue() + rangeAwardsValue)) {
            // 验证pv是否满足
            BdRangeAwards bdRangeAwards = consumeRangeAwardsMap.get(sourceMemberRangeExt.getRangeAwardsValue() + rangeAwardsValue);
            if (ComputeUtil.compareValue(sourceMemberRangeExt.getTeamConsumePv(), bdRangeAwards.getTeamConsumeCheck()) &&
                    ComputeUtil.compareValue(sourceMemberRangeExt.getConsumePv(), bdRangeAwards.getConsumePv())) {
                // 去结算表种查询该会员下所有会员，会员团队业绩+消费业绩是业绩 计算小区业绩 团队业绩-小区业绩 验证小区、直推必有一种
                // 如果需要验证小区
                if (ComputeUtil.compareValue(bdRangeAwards.getCommunityCheck())) {
                    List<CuMemberRangeExt> cuMemberRangeExtList = iCuMemberRangeService.queryCuMemberRangeExtByParent(rangeTableName, sourceMemberRangeExt.getPkMember(), saOrderExt.getPayTime());
                    // 需要验证团队业绩，小区业绩
                    if (calculateAwards(parentRangeExtMap, memberRangeExtMap, sourceMemberRangeExt, bdRangeAwards, cuMemberRangeExtList, false)) {
                        break;
                    }
                }
                cuMemberAwardsList.add(getCuMemberAwards(sourceMemberRangeExt, period, saOrderExt, bdRangeAwards));
                sourceMemberRangeExt.setPkRangeAwards(bdRangeAwards.getPkId());
                sourceMemberRangeExt.setPkAwards(bdRangeAwards.getPkAwards());
                sourceMemberRangeExt.setRangeAwardsValue(bdRangeAwards.getAwardsValue());
                rangeAwardsValue += 2;
            } else {
                break;
            }
        }
        // 当月有消费，修改为考核通过
        if (sourceMemberRangeExt.getMonthMember() == EYesNo.YES.getIntValue() && ComputeUtil.compareValue(sourceMemberRangeExt.getMonthPv())) {
            sourceMemberRangeExt.setAssessStatus(EAssessStatus.EXAMINE_PASS.getValue());
        }
        sourceMemberRangeExt.setConsumeStatus(EYesNo.YES.getIntValue());
        return cuMemberAwardsList;
    }

    /*
     *  计算团队极差奖衔
     **/
    public List<CuMemberAwards> calculateBloodRangeAwards(Integer period, Map<Long, List<CuMemberRangeExt>> parentRangeExtMap, Map<Long, CuMemberRangeExt> memberRangeExtMap, String rangeTableName, SaOrderExt saOrderExt,
                                                          Map<Integer, BdRangeAwards> bloodRangeAwardsMap, long pkParent, String secondRangeTableName) {
        // 计算血缘奖衔，一级一级升级，分为2段，s2、s3 一级，s3以上一级，先验证团队总业绩,
        // 小市场先验证目前小市场加新增是否满足，满足计算，不满足不计算，不满足小市场先累计，算小市场，每天最终计算完毕重新计算S1以上小市场
        List<CuMemberAwards> cuMemberAwardsList = new ArrayList<>();
        CuMemberRangeExt sourceMemberRangeExt = memberRangeExtMap.get(saOrderExt.getPkMember());
        while (true) {
            CuMemberRangeExt targetMemberRangeExt = memberRangeExtMap.get(pkParent);
            if (targetMemberRangeExt == null) {
                break;
            }
            // 无效会员不累计业绩,当月会员有消费，上月会员考核通过
            if (EYesNo.YES.getIntValue() == targetMemberRangeExt.getConsumeStatus()) {
                targetMemberRangeExt.setTeamConsumeAmount(ComputeUtil.computeAdd(targetMemberRangeExt.getTeamConsumeAmount(), saOrderExt.getOrderAmount()));
                targetMemberRangeExt.setTeamConsumePv(ComputeUtil.computeAdd(targetMemberRangeExt.getTeamConsumePv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
                targetMemberRangeExt.setTeamMonthAmount(ComputeUtil.computeAdd(targetMemberRangeExt.getTeamMonthAmount(), saOrderExt.getOrderAmount()));
                targetMemberRangeExt.setTeamMonthPv(ComputeUtil.computeAdd(targetMemberRangeExt.getTeamMonthPv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
                targetMemberRangeExt.setNewTeamPv(ComputeUtil.computeAdd(targetMemberRangeExt.getNewTeamPv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));

                sourceMemberRangeExt.setDeptTeamConsumeAmount(ComputeUtil.computeAdd(sourceMemberRangeExt.getDeptTeamConsumeAmount(), saOrderExt.getOrderAmount()));
                sourceMemberRangeExt.setDeptTeamConsumePv(ComputeUtil.computeAdd(sourceMemberRangeExt.getDeptTeamConsumePv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
                sourceMemberRangeExt.setDeptTeamMonthAmount(ComputeUtil.computeAdd(sourceMemberRangeExt.getDeptTeamMonthAmount(), saOrderExt.getOrderAmount()));
                sourceMemberRangeExt.setDeptTeamMonthPv(ComputeUtil.computeAdd(sourceMemberRangeExt.getDeptTeamMonthPv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
                sourceMemberRangeExt.setDeptNewTeamPv(ComputeUtil.computeAdd(sourceMemberRangeExt.getDeptNewTeamPv(), ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve())));
            }
            if (targetMemberRangeExt.getAssessStatus() == EAssessStatus.EXAMINE_PASS.getValue()) {
                int rangeAwardsValue = 2;
                while (bloodRangeAwardsMap.containsKey(targetMemberRangeExt.getRangeAwardsValue() + rangeAwardsValue)) {
                    // 验证pv是否满足
                    BdRangeAwards bdRangeAwards = bloodRangeAwardsMap.get(targetMemberRangeExt.getRangeAwardsValue() + rangeAwardsValue);
                    if (ComputeUtil.compareValue(targetMemberRangeExt.getTeamConsumePv(), bdRangeAwards.getTeamConsumeCheck())) {
                        // 去结算表种查询该会员下所有会员，会员团队业绩+消费业绩是业绩 计算小区业绩 团队业绩-小区业绩 验证小区、直推必有一种
                        List<CuMemberRangeExt> cuMemberRangeExtList;
                        if (secondRangeTableName != null) {
                            cuMemberRangeExtList = iCuMemberRangeService.querySecondCuMemberRangeExtByParent(rangeTableName, secondRangeTableName, targetMemberRangeExt.getPkMember());
                        } else {
                            cuMemberRangeExtList = iCuMemberRangeService.queryCuMemberRangeExtByParent(rangeTableName, targetMemberRangeExt.getPkMember(), saOrderExt.getPayTime());
                        }
                        if (cuMemberRangeExtList.size() > 0) {
                            if (calculateAwards(parentRangeExtMap, memberRangeExtMap, targetMemberRangeExt, bdRangeAwards, cuMemberRangeExtList, true)) {
                                break;
                            }
                            // 验证血缘部门，需要有几个部门大于考核等级，数据库验证一次，
                            // 当日的实时奖衔，这个位置直接在会员表中计算就可以
                            if (bdRangeAwards.getPlaceNum() > 0) {
                                if (secondRangeTableName != null) {
                                    iCuMemberRangeService.mergeSecondCuMemberRangeExt(secondRangeTableName, parentRangeExtMap.get(targetMemberRangeExt.getPkMember()));
                                    // 验证
                                    Integer placeNum = iCuMemberRangeService.validateSecondCuMemberPlaceAwards(secondRangeTableName, cuMemberRangeExtList, bdRangeAwards.getCheckAwards());
                                    if (bdRangeAwards.getPlaceNum() > placeNum) {
                                        break;
                                    }
                                } else {
                                    // 更新网体，更新伞下
                                    iCuMemberRangeService.mergeCuMemberRangeExt(rangeTableName, parentRangeExtMap.get(targetMemberRangeExt.getPkMember()));
                                    // 验证
                                    Integer placeNum = iCuMemberRangeService.validateCuMemberPlaceAwards(rangeTableName, cuMemberRangeExtList, bdRangeAwards.getCheckAwards(), saOrderExt.getPayTime());
                                    if (bdRangeAwards.getPlaceNum() > placeNum) {
                                        break;
                                    }
                                }
                            }
                        }
                        cuMemberAwardsList.add(getCuMemberAwards(targetMemberRangeExt, period, saOrderExt, bdRangeAwards));
                        targetMemberRangeExt.setPkRangeAwards(bdRangeAwards.getPkId());
                        targetMemberRangeExt.setPkAwards(bdRangeAwards.getPkAwards());
                        targetMemberRangeExt.setRangeAwardsValue(bdRangeAwards.getAwardsValue());
                        rangeAwardsValue += 2;
                        continue;
                    }
                    break;
                }
            }
            pkParent = targetMemberRangeExt.getPkParent();
            sourceMemberRangeExt = targetMemberRangeExt;
        }
        return cuMemberAwardsList;
    }

    /*
     *  计算奖衔，验证小区业绩和推荐数量是否满足
     **/
    private boolean calculateAwards(Map<Long, List<CuMemberRangeExt>> parentRangeExtMap, Map<Long, CuMemberRangeExt> memberRangeExtMap, CuMemberRangeExt targetMemberRangeExt, BdRangeAwards bdRangeAwards, List<CuMemberRangeExt> cuMemberRangeExtList, Boolean isRecommend) {
        BigDecimal bigAreaPv = BigDecimal.ZERO;
        Integer recommendNum = 0;
        for (CuMemberRangeExt cuMemberRangeExt : cuMemberRangeExtList) {
            if (parentRangeExtMap.containsKey(cuMemberRangeExt.getPkParent())) {
                parentRangeExtMap.get(cuMemberRangeExt.getPkParent()).add(cuMemberRangeExt);
            } else {
                List<CuMemberRangeExt> memberRangeExtList = new ArrayList<>();
                memberRangeExtList.add(cuMemberRangeExt);
                parentRangeExtMap.put(cuMemberRangeExt.getPkParent(), memberRangeExtList);
            }
            if (memberRangeExtMap.containsKey(cuMemberRangeExt.getPkMember())) {
                cuMemberRangeExt = memberRangeExtMap.get(cuMemberRangeExt.getPkMember());
            }
            // 团队业绩+个人业绩
            BigDecimal validatePv = ComputeUtil.computeAdd(cuMemberRangeExt.getDeptTeamConsumePv(), cuMemberRangeExt.getConsumePv());
            if (ComputeUtil.compareValue(validatePv, bigAreaPv)) {
                bigAreaPv = validatePv;
            }
            // 有效的,等级满足的算推荐数量、验证部门数量的 需要走语句
            if (cuMemberRangeExt.getAssessStatus() == EAssessStatus.EXAMINE_PASS.getValue() && bdRangeAwards.getCheckAwards() <= cuMemberRangeExt.getPkRangeAwards()) {
                recommendNum += 1;
            }
        }
        // 小区业绩
        BigDecimal communityCheck = ComputeUtil.computeSubtract(targetMemberRangeExt.getTeamConsumePv(), bigAreaPv);
        // 验证小区,验证失败
        if (ComputeUtil.compareGreaterThan(bdRangeAwards.getCommunityCheck(), communityCheck)) {
            return true;
        }
        // 验证推荐
        return isRecommend && bdRangeAwards.getRecommendNum() > recommendNum;
    }

    /*
     *  计算幸运奖，先计算有效代数，所有有效代数均分，比例10%
     **/
    CuMemberBonusCoach calculateLuckPushBonus(Map<Long, CuMemberRangeExt> memberRangeExtMap, Map<Long, CuMemberBonus> cuMemberBonusMap, BonusConfigDTO bonusConfigDTO,
                                              Integer period, SaOrderExt saOrderExt) {
        CuMemberRangeExt sourceMemberRangeExt = memberRangeExtMap.get(saOrderExt.getPkMember());
        long pkParent = sourceMemberRangeExt.getPkParent();
        // 计算代数
        while (true) {
            CuMemberRangeExt targetMemberRangeExt = memberRangeExtMap.get(pkParent);
            if (targetMemberRangeExt == null) {
                break;
            }
            pkParent = targetMemberRangeExt.getPkParent();
            if (ECategory.NORMAL.getValue() != targetMemberRangeExt.getCategory() ||
                    EAccountStatus.STOP_INCOME.getValue() == targetMemberRangeExt.getAccountStatus()) {
                continue;
            }
            // 验证推荐有效代数是否大于当前代数
            if (targetMemberRangeExt.getEffectiveNum() >= 1 && EAssessStatus.EXAMINE_PASS.getValue() == targetMemberRangeExt.getAssessStatus()) {
                getCuMemberBonus(period, cuMemberBonusMap, targetMemberRangeExt.getPkMember(),
                        targetMemberRangeExt.getIncomeStatus(), targetMemberRangeExt.getPkSettleCountry(), targetMemberRangeExt.getPkRate());
                CuMemberBonusCoach cuMemberBonusCoach = getCuMemberBonusCoach(bonusConfigDTO, saOrderExt, 1, targetMemberRangeExt);
                BigDecimal bonusRatio = BigDecimal.valueOf(10);
                cuMemberBonusCoach.setCoachGeneration(1);
                cuMemberBonusCoach.setCalValue(bonusRatio);
                cuMemberBonusCoach.setPretaxIncome(ComputeUtil.computeBonusMultiply(cuMemberBonusCoach.getCalAchieve(), bonusRatio));
                CuMemberBonus cuMemberBonus = cuMemberBonusMap.get(cuMemberBonusCoach.getPkBonus());
                BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusCoach, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                coachRangeRemark(saOrderExt, cuMemberBonusCoach, sourceMemberRangeExt, targetMemberRangeExt);
                if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusCoach.getIncomeStatus()) {
                    cuMemberBonus.setCloudDirectIncome(ComputeUtil.computeAdd(cuMemberBonus.getCloudDirectIncome(), cuMemberBonusCoach.getPretaxIncome()));
                    setCloudTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusCoach);
                }
                return cuMemberBonusCoach;
            }
        }
        return null;
    }

    /*
     *  计算极差收益，根据极差收益计算平级收益
     **/
    List<CuMemberBonusRange> calculateRangeBonus(Map<Long, CuMemberRangeExt> memberRangeExtMap, Map<Long, CuMemberBonus> cuMemberBonusMap, BonusConfigDTO bonusConfigDTO,
                                                 Integer period, SaOrderExt saOrderExt, List<BdRangeAwards> rangeAwardsList, List<CuMemberBonusDetail> cuMemberBonusDetailList) {
        List<CuMemberBonusRange> memberBonusRangeList = new ArrayList<>();
        // 用等级计算，按照一级级算
        BigDecimal bonusRatio = BigDecimal.ZERO;
        CuMemberRangeExt sourceMemberRangeExt = memberRangeExtMap.get(saOrderExt.getPkMember());
        long pkParent = sourceMemberRangeExt.getPkParent();
        int i = 0;
        boolean storeFlag = Boolean.TRUE;
        // 计算极差
        while (true) {
            CuMemberRangeExt targetMemberRangeExt = memberRangeExtMap.get(pkParent);
            if (targetMemberRangeExt == null) {
                break;
            }
            pkParent = targetMemberRangeExt.getPkParent();
            if (EAccountStatus.STOP_INCOME.getValue() == targetMemberRangeExt.getAccountStatus() ||
                    ECategory.NORMAL.getValue() != targetMemberRangeExt.getCategory() ||
                    EAssessStatus.EXAMINE_PASS.getValue() != targetMemberRangeExt.getAssessStatus()) {
                continue;
            }
            // 计算店铺收益
            if (storeFlag && targetMemberRangeExt.getRangeStoreStatus() == 2) {
                cuMemberBonusDetailList.add(calculateRangeStoreBonusOne(memberRangeExtMap, targetMemberRangeExt, bonusConfigDTO, period, cuMemberBonusMap, saOrderExt));
                storeFlag = Boolean.FALSE;
            }
            for (int j = i; j < rangeAwardsList.size(); j++) {
                BdRangeAwards bdRangeAwards = rangeAwardsList.get(j);
                if (targetMemberRangeExt.getPkRangeAwards().equals(bdRangeAwards.getPkId())) {
                    bonusRatio = ComputeUtil.computeSubtract(bdRangeAwards.getRangeRatio(), bonusRatio);
                    if (ComputeUtil.compareValue(bonusRatio)) {
                        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, targetMemberRangeExt.getPkMember(),
                                targetMemberRangeExt.getIncomeStatus(), targetMemberRangeExt.getPkSettleCountry(), targetMemberRangeExt.getPkRate());
                        int pkBonusItems = getPkBonusItems(bonusConfigDTO, targetMemberRangeExt.getPkSettleCountry(), EBonusItems.CLOUD_AGENT_FIRST_PURCHASE.getValue());
                        CuMemberBonusRange cuMemberBonusRange = getCuMemberBonusRange(saOrderExt, targetMemberRangeExt, cuMemberBonus, pkBonusItems);
                        cuMemberBonusRange.setCalValue(bonusRatio);
                        cuMemberBonusRange.setPretaxIncome(ComputeUtil.computeBonusMultiply(saOrderExt.getOrderAchieve(), bonusRatio));
                        cuMemberBonusRange.setPkRange(targetMemberRangeExt.getPkRangeAwards());
                        cuMemberBonusRange.setPkBeforeRange(sourceMemberRangeExt.getPkRangeAwards());
                        cuMemberBonusRange.setPkOrderItems(0L);
                        rangeRemark(saOrderExt, cuMemberBonusRange, sourceMemberRangeExt, targetMemberRangeExt);
                        BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusRange, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusRange.getIncomeStatus()) {
                            cuMemberBonus.setCloudPurIncome(ComputeUtil.computeAdd(cuMemberBonus.getCloudPurIncome(), cuMemberBonusRange.getPretaxIncome()));
                            setCloudTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusRange);
                        }
                        memberBonusRangeList.add(cuMemberBonusRange);
                        bonusRatio = bdRangeAwards.getRangeRatio();
                        sourceMemberRangeExt = targetMemberRangeExt;
                    }
                    j++;
                    i = j;
                    break;
                }
            }
            if (i >= rangeAwardsList.size()) {
                break;
            }
        }
        // 根据极差奖金计算平级奖金
        List<CuMemberBonusRange> memberOrdBonusRangeList = new ArrayList<>();
        for (CuMemberBonusRange cuMemberBonusRange : memberBonusRangeList) {
            sourceMemberRangeExt = memberRangeExtMap.get(cuMemberBonusRange.getPkBonus());
            pkParent = sourceMemberRangeExt.getPkParent();
            // 拿2次平级
            int oriLevel = 0;
            while (true) {
                CuMemberRangeExt targetMemberRangeExt = memberRangeExtMap.get(pkParent);
                if (targetMemberRangeExt == null) {
                    break;
                }
                pkParent = targetMemberRangeExt.getPkParent();
                if (EAccountStatus.STOP_INCOME.getValue() == targetMemberRangeExt.getAccountStatus() ||
                        ECategory.NORMAL.getValue() != targetMemberRangeExt.getCategory() ||
                        EAssessStatus.EXAMINE_PASS.getValue() != targetMemberRangeExt.getAssessStatus()) {
                    continue;
                }
                if (oriLevel < 2) {
                    if (targetMemberRangeExt.getPkRangeAwards().equals(sourceMemberRangeExt.getPkRangeAwards())) {
                        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, targetMemberRangeExt.getPkMember(),
                                targetMemberRangeExt.getIncomeStatus(), targetMemberRangeExt.getPkSettleCountry(), targetMemberRangeExt.getPkRate());
                        int pkBonusItems = getPkBonusItems(bonusConfigDTO, targetMemberRangeExt.getPkSettleCountry(), EBonusItems.CLOUD_AGENT_REPURCHASE.getValue());
                        CuMemberBonusRange oriMemberBonusRange = getCuMemberBonusRange(saOrderExt, targetMemberRangeExt, cuMemberBonus, pkBonusItems);
                        oriMemberBonusRange.setCalAchieve(cuMemberBonusRange.getPretaxIncome());
                        oriMemberBonusRange.setCalValue(BigDecimal.valueOf(10));
                        oriMemberBonusRange.setPretaxIncome(ComputeUtil.computeBonusMultiply(oriMemberBonusRange.getCalAchieve(), oriMemberBonusRange.getCalValue()));
                        oriMemberBonusRange.setPkRange(targetMemberRangeExt.getPkRangeAwards());
                        oriMemberBonusRange.setPkBeforeRange(sourceMemberRangeExt.getPkRangeAwards());
                        oriMemberBonusRange.setPkOrderItems(0L);
                        oriRangeRemark(saOrderExt, oriMemberBonusRange, sourceMemberRangeExt, targetMemberRangeExt);
                        BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, oriMemberBonusRange, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
                        if (EBonusIncomeStatus.NORMAL.getValue() == oriMemberBonusRange.getIncomeStatus()) {
                            cuMemberBonus.setCloudRepurIncome(ComputeUtil.computeAdd(cuMemberBonus.getCloudRepurIncome(), oriMemberBonusRange.getPretaxIncome()));
                            setCloudTotal(bdBonusDeduct, cuMemberBonus, oriMemberBonusRange);
                        }
                        memberOrdBonusRangeList.add(oriMemberBonusRange);
                        oriLevel++;
                    }
                } else {
                    break;
                }
            }
        }
        if (memberOrdBonusRangeList.size() > 0) {
            memberBonusRangeList.addAll(memberOrdBonusRangeList);
        }
        return memberBonusRangeList;
    }

    /**
     * 计算某条订单的推荐奖金
     */
    CuMemberBonusPush calculatePushBonusOne(CuMemberRangeExt sourceMemberRangeExt, Map<Long, CuMemberRangeExt> cuMemberRangeExtMap, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                            SaOrderExt saOrderExt, int algebra, BigDecimal orderAssAchieve, List<CuMemberBonusPush> cuMemberBonusPushList) {
        if (sourceMemberRangeExt == null) {
            return null;
        }
        if (algebra >= 12) {
            return null;
        }
        long pkParent = sourceMemberRangeExt.getPkParent();
        int i = 1;
        while (true) {
            CuMemberRangeExt targetMemberRangeExt = cuMemberRangeExtMap.get(pkParent);
            if (targetMemberRangeExt == null) {
                break;
            }
            pkParent = targetMemberRangeExt.getPkParent();
            if (i < algebra) {
                i++;
                continue;
            }
            // 死点没有奖金,自身没有购买没有奖金
            if (ECategory.NORMAL.getValue() != targetMemberRangeExt.getCategory() || EAccountStatus.STOP_INCOME.getValue() == targetMemberRangeExt.getAccountStatus() ||
                    targetMemberRangeExt.getBuyEffectiveNum() <= 0 || EAssessStatus.EXAMINE_PASS.getValue() != targetMemberRangeExt.getAssessStatus()) {
                // 记录烧伤记录
                targetMemberRangeExt.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
            }
            if (validatePkBonusItems(bonusConfigDTO, targetMemberRangeExt.getPkSettleCountry(), EBonusItems.HELP_EACH_INCOME.getValue())) {
                continue;
            }
            CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, targetMemberRangeExt.getPkMember(),
                    targetMemberRangeExt.getIncomeStatus(), targetMemberRangeExt.getPkSettleCountry(), targetMemberRangeExt.getPkRate());
            // 直推奖金明细
            int pkBonusItem = getPkBonusItems(bonusConfigDTO, targetMemberRangeExt.getPkSettleCountry(), EBonusItems.HELP_EACH_INCOME.getValue());
            CuMemberBonusPush cuMemberBonusPush = getCuMemberBonusPush(saOrderExt, targetMemberRangeExt, cuMemberBonus, pkBonusItem);
            cuMemberBonusPush.setCalType(ECalType.VALUE.getValue());
            // 前2代买的有特殊规则
            if (algebra == 1) {
                // 第一代前三单需要自购一单，从第四单开始需要自动二单，需要验证是否买了第二单
                if (targetMemberRangeExt.getFirstAgent() >= 3 && targetMemberRangeExt.getBuyEffectiveNum() <= 1) {
                    continue;
                }
                targetMemberRangeExt.setFirstAgent(targetMemberRangeExt.getFirstAgent() + 1);
                cuMemberBonusPush.setSecond(targetMemberRangeExt.getFirstAgent());
            } else if (algebra == 2) {
                if (targetMemberRangeExt.getSecondAgent() < 3 && targetMemberRangeExt.getBuyEffectiveNum() <= 1) {
                    continue;
                } else if (targetMemberRangeExt.getSecondAgent() >= 3 && targetMemberRangeExt.getBuyEffectiveNum() <= 2) {
                    continue;
                }
                targetMemberRangeExt.setSecondAgent(targetMemberRangeExt.getSecondAgent() + 1);
                cuMemberBonusPush.setSecond(targetMemberRangeExt.getSecondAgent());
            } else {
                if (targetMemberRangeExt.getBuyEffectiveNum() < algebra) {
                    continue;
                }
                cuMemberBonusPush.setSecond(-1);
            }
            cuMemberBonusPush.setRound(algebra);
            cuMemberBonusPush.setCalAchieve(orderAssAchieve);
            cuMemberBonusPush.setCalValue(BigDecimal.ONE);
            cuMemberBonusPush.setPretaxIncome(orderAssAchieve);
            BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusPush, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
            recommendRangeRemark(saOrderExt, cuMemberBonusPush, cuMemberRangeExtMap, targetMemberRangeExt);
            if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusPush.getIncomeStatus()) {
                cuMemberBonus.setRepurPushIncome(ComputeUtil.computeAdd(cuMemberBonus.getRepurPushIncome(), cuMemberBonusPush.getPretaxIncome()));
                setCloudTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusPush);
            }
            cuMemberBonusPushList.add(cuMemberBonusPush);
            if (targetMemberRangeExt.getIncomeStatus() == EBonusIncomeStatus.NORMAL.getValue()) {
                return cuMemberBonusPush;
            } else {
                cuMemberBonusPush.setSecond(-1);
            }
        }
        return null;
    }

    /**
     * 计算服务中心奖
     */
    CuMemberBonusDetail calculateRangeStoreBonusOne(Map<Long, CuMemberRangeExt> cuMemberRangeExtMap, CuMemberRangeExt targetMemberRangeExt, BonusConfigDTO bonusConfigDTO, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrderExt saOrderExt) {
        CuMemberRangeExt sourceMemberRangeExt = cuMemberRangeExtMap.get(saOrderExt.getPkMember());
        if (targetMemberRangeExt == null || ECategory.NORMAL.getValue() != targetMemberRangeExt.getCategory() || EAccountStatus.STOP_INCOME.getValue() == targetMemberRangeExt.getAccountStatus() ||
                EAssessStatus.EXAMINE_PASS.getValue() != targetMemberRangeExt.getAssessStatus()) {
            return null;
        }
        // 验证是否有奖金
        if (validatePkBonusItems(bonusConfigDTO, targetMemberRangeExt.getPkSettleCountry(), EBonusItems.STORE_INCOME.getValue())) {
            return null;
        }
        CuMemberBonus cuMemberBonus = getCuMemberBonus(period, cuMemberBonusMap, targetMemberRangeExt.getPkMember(),
                targetMemberRangeExt.getIncomeStatus(), targetMemberRangeExt.getPkSettleCountry(), targetMemberRangeExt.getPkRate());
        CuMemberBonusDetail cuMemberBonusDetail = getCuMemberBonusDetail(saOrderExt, targetMemberRangeExt, cuMemberBonus);
        BigDecimal serviceRadio = BigDecimal.valueOf(5);
        // 计算比例
        cuMemberBonusDetail.setCalValue(serviceRadio);
        cuMemberBonusDetail.setPkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberRangeExt.getPkSettleCountry(), EBonusItems.STORE_INCOME.getValue()));
        cuMemberBonusDetail.setPretaxIncome(ComputeUtil.computeBonusMultiply(cuMemberBonusDetail.getCalAchieve(), serviceRadio));
        // 收益占比
        BdBonusDeduct bdBonusDeduct = setBonusDetailDeduct(bonusConfigDTO, cuMemberBonusDetail, saOrderExt.getOrderAmount(), saOrderExt.getInExchangeRate());
        rangeServiceRemark(saOrderExt, cuMemberBonusDetail, sourceMemberRangeExt, targetMemberRangeExt);
        if (EBonusIncomeStatus.NORMAL.getValue() == cuMemberBonusDetail.getIncomeStatus()) {
            cuMemberBonus.setStoreIncome(ComputeUtil.computeAdd(cuMemberBonus.getStoreIncome(), cuMemberBonusDetail.getPretaxIncome()));
            setCloudTotal(bdBonusDeduct, cuMemberBonus, cuMemberBonusDetail);
        }
        return cuMemberBonusDetail;
    }

    CuMemberBonusPush getCuMemberBonusPush(SaOrderExt saOrderExt, CuMemberRangeExt cuMemberRangeExt, CuMemberBonus cuMemberBonus, Integer pkBonusItems) {
        CuMemberBonusPush cuMemberBonusPush = CuMemberBonusPush.builder()
                .pkOrder(saOrderExt.getPkId())
                .pkBonus(cuMemberBonus.getPkId())
                .pkBonusItems(pkBonusItems)
                // 正常还是烧伤
                .incomeStatus(cuMemberRangeExt.getIncomeStatus())
                .calType(ECalType.RATIO.getValue())
                .pretaxIncome(BigDecimal.ZERO)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .round(-1)
                .second(-1)
                .build();
        cuMemberBonusPush.setPkCountry(cuMemberRangeExt.getPkSettleCountry());
        cuMemberBonusPush.setPkCreator(MagicNumberConstants.PK_ADMIN);
        return cuMemberBonusPush;
    }

    protected CuMemberBonusCoach getCuMemberBonusCoach(BonusConfigDTO bonusConfigDTO, SaOrderExt saOrderExt,
                                                       int i, CuMemberRangeExt targetMemberRangeExt) {
        CuMemberBonusCoach cuMemberBonusCoach = CuMemberBonusCoach.builder()
                .pkBonus(targetMemberRangeExt.getPkMember())
                .pkOrder(saOrderExt.getPkId())
                .pkBonusItems(getPkBonusItems(bonusConfigDTO, targetMemberRangeExt.getPkSettleCountry(), EBonusItems.CLOUD_AGENT_DIRECT_PUSH.getValue()))
                .calType(ECalType.RATIO.getValue())
                .incomeStatus(targetMemberRangeExt.getIncomeStatus())
                .calAchieve(saOrderExt.getOrderAchieve())
                .currentGeneration(i)
                // 计算比例
                .calValue(BigDecimal.ZERO)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .pretaxIncome(BigDecimal.ZERO)
                .coachNoCapping(BigDecimal.ZERO)
                .coachCapping(BigDecimal.ZERO)
                .coachNormalHalf(BigDecimal.ZERO)
                .coachNormalReal(BigDecimal.ZERO)
                .build();
        cuMemberBonusCoach.setPkCountry(targetMemberRangeExt.getPkSettleCountry());
        cuMemberBonusCoach.setPkCreator(MagicNumberConstants.PK_ADMIN);
        return cuMemberBonusCoach;
    }

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

    /**
     * @param memberRangeMap 查询出来的结算数据
     *                       记录需要修改的会员结算表数据, 安置的
     */
    private Map<Long, CuMemberRangeExt> getMemberSettle(Map<Long, List<CuMemberRangeExt>> memberRangeMap) {
        Map<Long, CuMemberRangeExt> memberRangeExtMap = new HashMap<>();
        memberRangeMap.forEach((key, memberRangeExtList) -> {
            memberRangeExtList.forEach(cuMemberSettleExt -> {
                if (!memberRangeExtMap.containsKey(cuMemberSettleExt.getPkMember())) {
                    memberRangeExtMap.put(cuMemberSettleExt.getPkMember(), cuMemberSettleExt);
                } else {
                    CuMemberRangeExt cuMemberRangeExt = memberRangeExtMap.get(cuMemberSettleExt.getPkMember());
                    if (cuMemberRangeExt.getNewTeamPv() == null) {
                        cuMemberRangeExt.setNewTeamPv(BigDecimal.ZERO);
                    }
                }
            });
        });
        return memberRangeExtMap;
    }

    private CuMemberAwards getCuMemberAwards(CuMemberRangeExt sourceRangeExt, Integer period, SaOrderExt saOrderExt, BdRangeAwards bdRangeAwards) {
        CuMemberAwards cuMemberAwards = CuMemberAwards.builder()
                .pkMember(sourceRangeExt.getPkMember())
                .period(period)
                .upType(EUpgradeType.AUTO_UPGRADE.getValue())
                // 原等级
                .oldLevel(sourceRangeExt.getPkRangeAwards())
                .newLevel(bdRangeAwards.getPkId())
                // 默认不免考
                .purchaseStatus(EYesNo.NO.getIntValue())
                .pkOrder(saOrderExt.getPkId())
                .build();
        cuMemberAwards.setPkCreator(MagicNumberConstants.PK_ADMIN);
        cuMemberAwards.setPkCountry(saOrderExt.getPkCountry());
        cuMemberAwards.setCreationTime(saOrderExt.getPayTime());
        return cuMemberAwards;
    }

    /**
     * @param saOrderExt           订单
     * @param targetMemberRangeExt 奖金网体
     * @param cuMemberBonus        奖金主表
     *                             奖金明细 报单服务费、分红、云代首购、云代复购、海豆收益
     * @return: CuMemberBonusDetail
     */
    private CuMemberBonusDetail getCuMemberBonusDetail(SaOrder saOrderExt, CuMemberRangeExt targetMemberRangeExt, CuMemberBonus cuMemberBonus) {
        CuMemberBonusDetail cuMemberBonusDetail = CuMemberBonusDetail.builder()
                .pkOrder(saOrderExt.getPkId())
                .calType(ECalType.RATIO.getValue())
                .incomeStatus(targetMemberRangeExt.getIncomeStatus())
                .calAchieve(ComputeUtil.computeAdd(saOrderExt.getOrderAchieve(), saOrderExt.getOrderAssAchieve()))
                .pkBonus(cuMemberBonus.getPkId())
                .pretaxIncome(BigDecimal.ZERO)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .build();
        cuMemberBonusDetail.setPkCountry(targetMemberRangeExt.getPkSettleCountry());
        cuMemberBonusDetail.setPkCreator(MagicNumberConstants.PK_ADMIN);
        return cuMemberBonusDetail;
    }
}
