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

import cn.hutool.core.collection.CollectionUtil;
import com.hzs.bonus.achieve.param.MemberAchieveParam;
import com.hzs.bonus.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.bonus.achieve.service.ICuMemberTreeService;
import com.hzs.bonus.base.service.ICuMemberService;
import com.hzs.bonus.detail.service.ICuMemberAssessService;
import com.hzs.common.core.constant.BonusFieldConstants;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.msg.BonusMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.domain.bonus.BdBonusDeduct;
import com.hzs.common.domain.member.achieve.CuMemberTree;
import com.hzs.common.domain.member.base.CuAwardsControl;
import com.hzs.common.domain.member.bonus.*;
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.order.SaOrder;
import com.hzs.common.domain.sale.order.SaOrderBonus;
import com.hzs.common.domain.system.config.BdAwards;
import com.hzs.common.domain.system.config.BdGrade;
import com.hzs.common.domain.system.config.ext.BdBonusItemsExt;
import com.hzs.sale.order.ISaOrderServiceApi;
import com.hzs.system.base.ICurrencyServiceApi;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.config.IBonusItemsServiceApi;
import com.hzs.system.config.dto.BonusConfigDTO;
import com.hzs.system.config.dto.BonusExpandDTO;
import com.hzs.system.config.dto.RangeDTO;
import com.hzs.system.sys.dto.BdCurrencyDTO;
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.*;

/**
 * @Description:
 * @Author: sui q
 * @Time: 2022/11/16 11:24
 * @Classname: BonusSettleHandle
 * @PackageName: com.hzs.member.achieve.service.impl
 */
@Component
public abstract class BonusSettleHandle {

    protected ICuMemberTreeService cuMemberTreeService;

    @DubboReference
    protected ISaOrderServiceApi saOrderServiceApi;

    @DubboReference
    protected IBonusItemsServiceApi bonusItemsServiceApi;

    @DubboReference
    private ICurrencyServiceApi currencyServiceApi;

    @Autowired
    public void setCuMemberTreeService(ICuMemberTreeService cuMemberTreeService) {
        this.cuMemberTreeService = cuMemberTreeService;
    }

    private ICuMemberSettlePeriodService cuMemberSettlePeriodService;

    private ICuMemberAssessService cuMemberAssessService;

    @Autowired
    private ICuMemberService cuMemberService;

    @Autowired
    public void setCuMemberAssessService(ICuMemberAssessService cuMemberAssessService) {
        this.cuMemberAssessService = cuMemberAssessService;
    }

    @Autowired
    public void setCuMemberSettlePeriodService(ICuMemberSettlePeriodService cuMemberSettlePeriodService) {
        this.cuMemberSettlePeriodService = cuMemberSettlePeriodService;
    }

    public ICuMemberSettlePeriodService getCuMemberSettlePeriodService() {
        return cuMemberSettlePeriodService;
    }

    public ICuMemberAssessService getCuMemberAssessService() {
        return cuMemberAssessService;
    }

    /**
     * @param bonusConfigDTO  奖金参数汇总
     * @param memberSettleExt 会员
     * @Description: 获取等级对应的拓展奖配置
     * @return: BdGrade
     * @Author: sui q
     * @Date: 2022/11/16 11:24
     */
    protected BdGrade getGradeExpand(BonusConfigDTO bonusConfigDTO, CuMemberSettleExt memberSettleExt) {
        return bonusConfigDTO.getGradeMap().get(memberSettleExt.getPkSettleCountry().toString() + "_" + memberSettleExt.getPkGrade());
    }

    /**
     * @param bonusConfigDTO  奖金参数汇总
     * @param memberSettleExt 会员
     * @Description: 获取主任奖衔值对应的辅导奖配置
     * @return: BdAwards
     * @Author: sui q
     * @Date: 2022/11/17 10:13
     */
    protected BdAwards getDirectorAwardsCouch(BonusConfigDTO bonusConfigDTO, CuMemberSettleExt memberSettleExt) {
        return bonusConfigDTO.getAwardsValueMap().get(memberSettleExt.getPkSettleCountry().toString() + ERangeType.AWARDS.getValue() + EAwards.HEADER.getValue());
    }

    /**
     * @param bonusConfigDTO  奖金参数汇总
     * @param memberSettleExt 会员
     * @Description: 获取奖衔对应的辅导奖配置
     * @return: BdAwards
     * @Author: sui q
     * @Date: 2022/11/17 10:13
     */
    protected BdAwards getAwardsCouch(BonusConfigDTO bonusConfigDTO, CuMemberSettleExt memberSettleExt, Map<Long, CuAwardsControl> cuAwardsControlMap) {
        Integer pkAwards = getPkRealAwards(memberSettleExt.getPkMember(), memberSettleExt.getPkAwards(), cuAwardsControlMap);
        return bonusConfigDTO.getAwardsMap().get(memberSettleExt.getPkSettleCountry().toString() + ERangeType.AWARDS.getValue() + pkAwards);
    }

    private Integer getPkRealAwards(Long pkMember, Integer pkAwards, Map<Long, CuAwardsControl> cuAwardsControlMap) {
        if (cuAwardsControlMap.containsKey(pkMember)) {
            int giveRealAwards = cuAwardsControlMap.get(pkMember).getRealAwards();
            int pkControlAwards = cuAwardsControlMap.get(pkMember).getExtremeAwards();
            if (pkAwards <= giveRealAwards && pkAwards < pkControlAwards) {
                // 实际奖衔 <= 赠与奖衔时，用实际奖衔和集成奖衔取大的
                pkAwards = pkControlAwards;
            }
        }
        return pkAwards;
    }

    /**
     * @param bonusConfigDTO  奖金配置汇总
     * @param memberSettleExt 会员
     * @param endTouch        4-n的次数
     * @param bdGrade         等级
     * @Description: 获得国家对应的4-n参数比例
     * @return: BigDecimal
     * @Author: sui q
     * @Date: 2022/11/16 11:27
     */
    protected BigDecimal getCountryExpand(BonusConfigDTO bonusConfigDTO, CuMemberSettleExt memberSettleExt, Integer endTouch, BdGrade bdGrade) {
        BonusExpandDTO bonusExpand = bonusConfigDTO.getBonusExpandMap().get(memberSettleExt.getPkSettleCountry());
        BigDecimal countryExpandRatio = ComputeUtil.computeDivide(bonusExpand.getExpandRatio(), BigDecimal.valueOf(endTouch));
        if (ComputeUtil.compareValue(countryExpandRatio, bdGrade.getExpandRatio())) {
            return bdGrade.getExpandRatio();
        }
        return countryExpandRatio;
    }

    /**
     * @param bonusConfigDTO  奖金配置汇总
     * @param memberSettleExt 会员
     * @param endTouch        4-n的次数
     * @param bdGrade         等级
     * @Description: 获得国家对应的4-n参数比例
     * @return: BigDecimal
     * @Author: sui q
     * @Date: 2022/11/16 11:27
     */
    protected BigDecimal getCountryRepurchaseExpand(BonusConfigDTO bonusConfigDTO, CuMemberSettleExt memberSettleExt, Integer endTouch, BdGrade bdGrade) {
        BonusExpandDTO bonusExpand = bonusConfigDTO.getBonusExpandMap().get(memberSettleExt.getPkSettleCountry());
        BigDecimal countryExpandRatio = ComputeUtil.computeDivide(bonusExpand.getExpandRatio(), BigDecimal.valueOf(endTouch));
        if (ComputeUtil.compareValue(countryExpandRatio, bdGrade.getRepurchaseRatio())) {
            return bdGrade.getRepurchaseRatio();
        }
        return countryExpandRatio;
    }

    /**
     * 获得奖项主键，验证该国是否有该奖项
     *
     * @param bonusConfigDTO 参数
     * @param pkCountry      国家
     * @param bonusItems     值
     * @return int
     */
    protected Boolean validatePkBonusItems(BonusConfigDTO bonusConfigDTO, Integer pkCountry, Integer bonusItems) {
        BdBonusItemsExt bdBonusItemsExt = bonusConfigDTO.getBonusItemsExtMap().get(pkCountry.toString() + bonusItems);
        return bdBonusItemsExt == null || bdBonusItemsExt.getPkId() == null;
    }

    /**
     * 获得奖项主键
     *
     * @param bonusConfigDTO 参数
     * @param pkCountry      国家
     * @param bonusItems     值
     * @return int
     */
    protected Integer getPkBonusItems(BonusConfigDTO bonusConfigDTO, Integer pkCountry, Integer bonusItems) {
        return bonusConfigDTO.getBonusItemsExtMap().get(pkCountry.toString() + bonusItems).getPkId();
    }

    /**
     * 获得有量奖的会员
     *
     * @param cuMemberBonusMap        奖金汇总表
     * @param cuMemberBonusExpandList 量奖明细
     */
    protected Set<Long> getMemberExpandBonus(Map<Long, CuMemberBonus> cuMemberBonusMap, List<CuMemberBonusExpand> cuMemberBonusExpandList) {
        Map<Long, CuMemberBonus> pkMemberSettleMap = new HashMap<>(ComputeUtil.mapInitCapacity(cuMemberBonusMap.size()));
        cuMemberBonusMap.forEach((key, cuMemberBonus) -> {
            // 判断 cuMemberSettleExtMap中这个人是否是免考，免考的不查询考核是否通过，过滤数据
            pkMemberSettleMap.put(cuMemberBonus.getPkId(), cuMemberBonus);
        });
        Set<Long> expandMemberSet = new HashSet<>();
        cuMemberBonusExpandList.forEach(cuMemberBonusExpand -> {
            // 只查询有量奖的人的考核记录
            if (pkMemberSettleMap.containsKey(cuMemberBonusExpand.getPkBonus())) {
                expandMemberSet.add(pkMemberSettleMap.get(cuMemberBonusExpand.getPkBonus()).getPkMember());
            }
        });
        return expandMemberSet;
    }

    /**
     * 获得有量奖的会员
     *
     * @param cuMemberSettleExtMap 奖金汇总表
     */
    protected Map<Long, CuMemberSettleExt> getMemberExpandBonus(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap) {
        Map<Long, CuMemberSettleExt> pkMemberSettleMap = new HashMap<>(ComputeUtil.mapInitCapacity(cuMemberSettleExtMap.size()));
        cuMemberSettleExtMap.forEach((key, cuMemberSettleExt) ->
                pkMemberSettleMap.put(cuMemberSettleExt.getPkMember(), cuMemberSettleExt));
        return pkMemberSettleMap;
    }

    /**
     * @param cuMemberSettleExtMap  会员结算
     * @param cuMemberSettleExtList 查询出来的结算数据
     * @Description: 记录需要修改的会员结算表数据, 安置的
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/15 9:52
     */
    protected void getMemberSettle(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, List<CuMemberSettleExt> cuMemberSettleExtList) {
        cuMemberSettleExtList.forEach(cuMemberSettleExt -> {
            if (cuMemberSettleExtMap.containsKey(cuMemberSettleExt.getPkMember())) {
                CuMemberSettleExt memberSettleExt = cuMemberSettleExtMap.get(cuMemberSettleExt.getPkMember());
                if (memberSettleExt.getPkParent() == null) {
                    memberSettleExt.setPkParent(cuMemberSettleExt.getPkParent());
                }
                if (memberSettleExt.getPkPlaceParent() == null) {
                    memberSettleExt.setPkPlaceParent(cuMemberSettleExt.getPkPlaceParent());
                }
                if (memberSettleExt.getPlaceDept() == null) {
                    memberSettleExt.setPlaceDept(cuMemberSettleExt.getPlaceDept());
                }
                if (memberSettleExt.getPkGrade() == null) {
                    memberSettleExt.setPkGrade(cuMemberSettleExt.getPkGrade());
                }
                if (memberSettleExt.getGradeValue() == null) {
                    memberSettleExt.setGradeValue(cuMemberSettleExt.getGradeValue());
                }
                if (memberSettleExt.getPkAwards() == null) {
                    memberSettleExt.setPkAwards(cuMemberSettleExt.getPkAwards());
                }
                if (memberSettleExt.getRegisterAuthority() == null) {
                    memberSettleExt.setRegisterAuthority(cuMemberSettleExt.getRegisterAuthority());
                }
                if (memberSettleExt.getCustomerType() == null) {
                    memberSettleExt.setCustomerType(cuMemberSettleExt.getCustomerType());
                }
                if(memberSettleExt.getSumPv() == null){
                    memberSettleExt.setSumPv(cuMemberSettleExt.getSumPv());
                }
            } else {
                cuMemberSettleExt.setRegisterNewAmount(BigDecimal.ZERO);
                cuMemberSettleExt.setRegisterNewPv(BigDecimal.ZERO);
                cuMemberSettleExt.setRegisterBloPv(BigDecimal.ZERO);
                cuMemberSettleExt.setRegisterBloNewPv(BigDecimal.ZERO);
                cuMemberSettleExt.setBigAreaDept(EPlaceDept.ZERO_DEPT.getValue());
                if(CollectionUtil.isNotEmpty(cuMemberSettleExt.getCuMemberSettleDetailExtList())){
                    for (CuMemberSettleDetailExt cuMemberSettleDetailExt : cuMemberSettleExt.getCuMemberSettleDetailExtList()) {
                        cuMemberSettleDetailExt.setNewPv(BigDecimal.ZERO);
                        cuMemberSettleDetailExt.setNewAmount(BigDecimal.ZERO);
                        cuMemberSettleDetailExt.setExpandCapping(BigDecimal.ZERO);
                    }
                }
                cuMemberSettleExtMap.put(cuMemberSettleExt.getPkMember(), cuMemberSettleExt);
            }
        });
    }

    /**
     * @param saOrderExt           订单编号
     * @param cuMemberBonusPush    直推奖
     * @param cuMemberSettleExtMap 存储会员网体的map
     * @Description: 获得 直推收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void recommendRemark(SaOrderExt saOrderExt, CuMemberBonusPush cuMemberBonusPush, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap) {
        CuMemberSettleExt sourceCuMemberSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
        CuMemberSettleExt targetCuMemberSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkReference());
        String remark = String.format(BonusMsgConstants.RECOMMEND_DIRECT, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusPush.getRealIncome());
        cuMemberBonusPush.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusExpand     拓展奖
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 拓展收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void expandRemark(SaOrderExt saOrderExt, CuMemberBonusExpand cuMemberBonusExpand,
                                CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.EXPAND, cuMemberBonusExpand.getCurrentTouch(), saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusExpand.getCalAchieve(), cuMemberBonusExpand.getCalValue());
        cuMemberBonusExpand.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusPush       拓展奖
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 拓展收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void repurchasePushRemark(SaOrderExt saOrderExt, CuMemberBonusPush cuMemberBonusPush,
                                        CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.REPURCHASE_PUSH, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusPush.getCalAchieve(), cuMemberBonusPush.getCalValue());
        cuMemberBonusPush.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusExpand     拓展奖
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 拓展收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void repurchaseExpandRemark(SaOrderExt saOrderExt, CuMemberBonusExpand cuMemberBonusExpand,
                                          CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.REPURCHASE_EXPAND, cuMemberBonusExpand.getCurrentTouch(), cuMemberBonusExpand.getExpandTouch(), saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusExpand.getCalAchieve(), cuMemberBonusExpand.getCalValue());
        cuMemberBonusExpand.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusCoach      辅导奖
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 辅导收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void coachRemark(SaOrderExt saOrderExt, CuMemberBonusCoach cuMemberBonusCoach,
                               CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.COACH, cuMemberBonusCoach.getCurrentGeneration(), saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusCoach.getCalAchieve(), cuMemberBonusCoach.getCalValue());
        cuMemberBonusCoach.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusCoach      辅导奖
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 辅导收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void seePointRemark(SaOrderExt saOrderExt, CuMemberBonusCoach cuMemberBonusCoach,
                               CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.SEE_POINT, cuMemberBonusCoach.getCurrentGeneration(), saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusCoach.getCalAchieve(), cuMemberBonusCoach.getCalValue());
        cuMemberBonusCoach.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusDetail     报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void serviceRemark(SaOrderExt saOrderExt, CuMemberBonusDetail cuMemberBonusDetail,
                                 CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.SERVICE, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getCalAchieve(), cuMemberBonusDetail.getCalValue());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusDetail     报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void makerDirectRemark(SaOrderExt saOrderExt, CuMemberBonusDetail cuMemberBonusDetail,
                                     CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.MAKER_DIRECT, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getPretaxIncome());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusDetail     报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void haiFunRemark(SaOrderExt saOrderExt, CuMemberBonusDetail cuMemberBonusDetail,
                                CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.HAI_FUN, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getPretaxIncome());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusDetail     报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void makerShareRemark(SaOrderExt saOrderExt, CuMemberBonusDetail cuMemberBonusDetail,
                                    CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.MAKER_DIRECT, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getPretaxIncome());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusDetail     报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 嗨粉推荐的收益
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void hiFunRemark(SaOrderExt saOrderExt, CuMemberBonusDetail cuMemberBonusDetail,
                               CuMemberSettleExt sourceCuMemberSettleExt, CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.HI_FUN, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getRealIncome());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param cuMemberBonusDetail 分红
     * @Description: 获得 分红收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void leaderShareRemark(CuMemberBonusDetail cuMemberBonusDetail, Integer period,
                                     BigDecimal bigAreaPv, BigDecimal smallAreaPv, BigDecimal allSmallAreaPv, BigDecimal bonusRation) {
        String remark = String.format(BonusMsgConstants.SHARE, period,
                cuMemberBonusDetail.getPretaxIncome(), bigAreaPv, smallAreaPv, allSmallAreaPv, bonusRation);
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param cuMemberBonusDetail 分红
     * @param settleDate          结算日期
     * @Description: 获得 分红收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void shareCouponRemark(CuMemberBonusDetail cuMemberBonusDetail, String settleDate) {
        String remark = String.format(BonusMsgConstants.SHARE_COUPON, DateUtils.getMonth(settleDate),
                cuMemberBonusDetail.getPretaxIncome());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param cuMemberBonusDetail 分红
     * @Description: 获得 分红收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void storeRemark(CuMemberBonusDetail cuMemberBonusDetail, SaOrderExt saOrderExt, CuMemberSettleExt sourceMemberSettleExt, CuMemberSettleExt targetMemberSettleExt ) {
        String remark = String.format(BonusMsgConstants.STORE, saOrderExt.getOrderCode(), sourceMemberSettleExt.getMemberCode() + sourceMemberSettleExt.getMemberName(),
                targetMemberSettleExt.getMemberCode() + targetMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getCalAchieve(), cuMemberBonusDetail.getCalValue());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param cuMemberBonusDetail 分红
     * @Description: 获得 分红收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void storeRangeRemark(CuMemberBonusDetail cuMemberBonusDetail, SaOrderExt saOrderExt, CuMemberSettleExt sourceMemberSettleExt,
                                    CuMemberSettleExt targetMemberSettleExt, String beforeLevelName, String levelName) {
        String remark = String.format(BonusMsgConstants.STORE_RANGE, saOrderExt.getOrderCode(), sourceMemberSettleExt.getMemberCode() + sourceMemberSettleExt.getMemberName(),
                targetMemberSettleExt.getMemberCode() + targetMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getCalAchieve(), beforeLevelName, levelName);
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param cuMemberBonusDetail 分红
     * @Description: 获得 分红收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void globalShareRemark(CuMemberBonusDetail cuMemberBonusDetail, String msg) {
        String remark = String.format(msg, cuMemberBonusDetail.getPretaxIncome());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusRange      报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void rangeRemark(SaOrderExt saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberSettleExt sourceCuMemberSettleExt,
                               CuMemberSettleExt targetCuMemberSettleExt, Map<String, RangeDTO> rangePkDtoMap) {
        RangeDTO beforeOrderRangeDto = rangePkDtoMap.get(targetCuMemberSettleExt.getPkSettleCountry().toString() + cuMemberBonusRange.getPkBeforeRange());
        RangeDTO orderRangeDto = rangePkDtoMap.get(sourceCuMemberSettleExt.getPkSettleCountry().toString() + cuMemberBonusRange.getPkRange());
        String remark = String.format(BonusMsgConstants.SHARE_RANGE, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), beforeOrderRangeDto == null? "" : beforeOrderRangeDto.getRangeName(), orderRangeDto == null ? "" : orderRangeDto.getRangeName());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void sharePointRemark(CuMemberSettleExt targetCuMemberSettleExt, CuMemberBonusPoint cuMemberBonusPoint, BigDecimal firePointIncome) {
        String remark = String.format(BonusMsgConstants.SHARE_PONT, targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusPoint.getPretaxIncome(), firePointIncome);
        cuMemberBonusPoint.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusRange      报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void sameLevelRemark(SaOrderExt saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberSettleExt sourceCuMemberSettleExt,
                               CuMemberSettleExt targetCuMemberSettleExt, RangeDTO beforeOrderRangeDto, RangeDTO orderRangeDto ) {
//        RangeDTO beforeOrderRangeDto = rangePkDtoMap.get(targetCuMemberSettleExt.getPkSettleCountry().toString() + cuMemberBonusRange.getPkBeforeRange());
//        RangeDTO orderRangeDto = rangePkDtoMap.get(sourceCuMemberSettleExt.getPkSettleCountry().toString() + cuMemberBonusRange.getPkRange());
        String remark = String.format(BonusMsgConstants.SAME_LEVEL_RANGE, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), beforeOrderRangeDto == null? "" : beforeOrderRangeDto.getRangeName(), orderRangeDto == null ? "" : orderRangeDto.getRangeName());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusRange      报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void rangeRemark(SaOrderExt saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberSettleExt sourceCuMemberSettleExt,
                               CuMemberSettleExt targetCuMemberSettleExt, RangeDTO parentRangeDto, RangeDTO beforeRangeDto) {
        String remark = String.format(BonusMsgConstants.SHARE_RANGE, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), beforeRangeDto.getRangeName(), parentRangeDto.getRangeName());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * @param saOrderExt              订单编号
     * @param cuMemberBonusRange      报单服务费
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void xueRangeRemark(SaOrderExt saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberSettleExt sourceCuMemberSettleExt,
                                  CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.LE_XUE_SHARE_RANGE, saOrderExt.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                ComputeUtil.computeDivide(targetCuMemberSettleExt.getRetailPrice(), BigDecimal.valueOf(6.4)), targetCuMemberSettleExt.getGradeValue());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * @param saOrder                 订单编号
     * @param cuMemberBonusDetail     云代首购
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void cloudAgentRemark(SaOrder saOrder, CuMemberBonusDetail cuMemberBonusDetail, CuMemberSettleExt sourceCuMemberSettleExt,
                                    CuMemberSettleExt targetCuMemberSettleExt, String msg) {
        String remark = String.format(msg, saOrder.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getCalAchieve(), cuMemberBonusDetail.getCalValue());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * @param saOrder                 订单编号
     * @param cuMemberBonusDetail     云代首购
     * @param sourceCuMemberSettleExt 提供奖金的人
     * @param targetCuMemberSettleExt 获得奖金的人
     * @Description: 获得 报单服务费收益的备注
     * @return: String
     * @Author: sui q
     * @Date: 2022/11/17 11:22
     */
    protected void repurchaseCouponsRemark(SaOrder saOrder, CuMemberBonusDetail cuMemberBonusDetail, CuMemberSettleExt sourceCuMemberSettleExt,
                                           CuMemberSettleExt targetCuMemberSettleExt) {
        String remark = String.format(BonusMsgConstants.REPURCHASE_COUPON_RANGE, saOrder.getOrderCode(),
                sourceCuMemberSettleExt.getMemberCode() + sourceCuMemberSettleExt.getMemberName(),
                targetCuMemberSettleExt.getMemberCode() + targetCuMemberSettleExt.getMemberName(),
                cuMemberBonusDetail.getCalAchieve(), cuMemberBonusDetail.getCalValue(), cuMemberBonusDetail.getRealIncome());
        cuMemberBonusDetail.setRemark(remark);
    }

    /**
     * 获取会员奖金汇总表
     *
     * @param period            期间
     * @param cuMemberBonusMap  奖金汇总map
     * @param saOrder            汇率
     * @param cuMemberSettleExt 获取奖金的会员
     * @return CuMemberBonus
     */
    protected CuMemberBonus getCuMemberBonus(Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, SaOrder saOrder,
                                             CuMemberSettleExt cuMemberSettleExt) {
        Integer pkRate = saOrder.getPkRate();
        if (pkRate == null || !Objects.equals(cuMemberSettleExt.getPkSettleCountry(), saOrder.getPkCountry())) {
            CurrencyDTO currencyDTO = currencyServiceApi.getCurrency(cuMemberSettleExt.getPkSettleCountry()).getData();
            pkRate = currencyDTO.getPkId();
        }
        Long pkMember = cuMemberSettleExt.getPkMember();
        if (cuMemberBonusMap.containsKey(pkMember)) {
            return cuMemberBonusMap.get(pkMember);
        } else {
            CuMemberBonus cuMemberBonus = CuMemberBonus.builder()
                    // 暂时赋值一个long，暂时把主子表关联起来，计算后，从数据库获得索引，在修改
                    .pkId(pkMember)
                    .pkMember(pkMember)
                    .period(period)
                    .pkRate(pkRate)
                    .incomeStatus(cuMemberSettleExt.getIncomeStatus())
                    .directIncome(BigDecimal.ZERO)
                    .seePointIncome(BigDecimal.ZERO)
                    .expandIncome(BigDecimal.ZERO)
                    .expandNoCapping(BigDecimal.ZERO)
                    .coachIncome(BigDecimal.ZERO)
                    .shareIncome(BigDecimal.ZERO)
                    .serviceIncome(BigDecimal.ZERO)
                    .backPoints(BigDecimal.ZERO)
                    .serviceSpend(BigDecimal.ZERO)
                    .purRealSubtotal(BigDecimal.ZERO)
                    .repurRangeIncome(BigDecimal.ZERO)
                    .sameLevelIncome(BigDecimal.ZERO)
                    .pointShareIncome(BigDecimal.ZERO)
                    .fireShareIncome(BigDecimal.ZERO)
                    .repurRealSubtotal(BigDecimal.ZERO)
                    .globalPoints(BigDecimal.ZERO)
                    .storeIncome(BigDecimal.ZERO)
                    .storeRangeIncome(BigDecimal.ZERO)
                    .realIncomeTotal(BigDecimal.ZERO)
                    .build();
            cuMemberBonus.setPkCreator(MagicNumberConstants.PK_ADMIN);
            cuMemberBonus.setPkCountry(cuMemberSettleExt.getPkSettleCountry());
            cuMemberBonus.setGrantStatus(EGrantStatus.SETTLED.getValue());
            cuMemberBonusMap.put(pkMember, cuMemberBonus);
            return cuMemberBonus;
        }
    }

    protected CuMemberBonusExpand getCuMemberBonusExpand(SaOrderExt saOrderExt, String settleDate, int i, CuMemberSettleExt targetMemberSettleExt, BigDecimal touchBonus, CuMemberBonus cuMemberBonus, BigDecimal calAchieve,
                                                         Integer pkBonusItems) {
        CuMemberBonusExpand cuMemberBonusExpand = CuMemberBonusExpand.builder()
                .pkBonus(cuMemberBonus.getPkId())
                .pkOrder(saOrderExt.getPkId())
                .pkBonusItems(pkBonusItems)
                .calType(ECalType.RATIO.getValue())
                .incomeStatus(targetMemberSettleExt.getIncomeStatus())
                .currentTouch(i)
                .expandTouch(0)
                .calValue(touchBonus)
                .calAchieve(calAchieve)
                .pretaxIncome(BigDecimal.ZERO)
                .expandNoCapping(BigDecimal.ZERO)
                .expandCapping(BigDecimal.ZERO)
                .expandNormalHalf(BigDecimal.ZERO)
                .expandNormalReal(BigDecimal.ZERO)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .build();
        cuMemberBonusExpand.setPkCountry(targetMemberSettleExt.getPkSettleCountry());
        cuMemberBonusExpand.setPkCreator(MagicNumberConstants.PK_ADMIN);
        if (EAccountStatus.STOP_PROFIT.getValue() == targetMemberSettleExt.getAccountStatus()) {
            cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.STOP_INCOME.getValue());
        }
        // 验证会员是否有奖金，判断有效期是否大于结算日期
        if(validateExistBonus(targetMemberSettleExt, settleDate)){
            cuMemberBonusExpand.setIncomeStatus(EBonusIncomeStatus.FIRE_BURN.getValue());
        }
        return cuMemberBonusExpand;
    }

    /**
     * @param cuMemberSettleExtMap 树关系
     * @param settleTableName      结算表
     * @param saOrderList          订单
     * @Description: 根据订单获取会员的血缘父级，用于嗨粉推荐、复购极差
     * @return: void
     * @Author: sui q
     * @Date: 2023/1/4 14:10
     */
    protected List<CuMemberSettleExt> getMemberParentBySaOrder(Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, String settleTableName, String settleTableNameDetail, List<SaOrderExt> saOrderList) {
        Set<Long> memberSet = new HashSet<>();
        saOrderList.forEach(saOrderExt -> memberSet.add(saOrderExt.getPkMember()));
        List<CuMemberSettleExt> cuMemberSettleExtList = cuMemberTreeService.batchQueryCuMemberSettleParent(settleTableName, settleTableNameDetail, memberSet);
        getMemberSettle(cuMemberSettleExtMap, cuMemberSettleExtList);
        return cuMemberSettleExtList;
    }

    /**
     * @param awardsMap        奖衔
     * @param parentMemberTree 会员树历史记录
     * @Description: 获取会员的极差等级，验证会员是否有奖衔
     * @return: String
     * @Author: sui q
     * @Date: 2023/1/4 14:22
     */
    protected String getMemberCountryKey(Map<String, BdAwards> awardsMap, CuMemberTree parentMemberTree, Map<Long, CuAwardsControl> cuAwardsControlMap) {
        Integer pkAwards = getPkRealAwards(parentMemberTree.getPkMember(), parentMemberTree.getPkAwards(), cuAwardsControlMap);
        String key = parentMemberTree.getPkSettleCountry().toString() + ERangeType.AWARDS.getValue() + pkAwards;
        String awardKey = parentMemberTree.getPkSettleCountry() + parentMemberTree.getPkAwards().toString();
        if (awardsMap.get(awardKey) != null && EAwards.MEMBER.getValue() == awardsMap.get(awardKey).getAwardsValue()) {
            key = parentMemberTree.getPkSettleCountry().toString() + ERangeType.GRADE.getValue() + parentMemberTree.getPkGrade();
        }
        return key;
    }

    protected RangeDTO getRangeDto(Map<String, RangeDTO> rangeDtoMap, Map<String, BdAwards> awardsMap, CuMemberTree parentMemberTree, Map<Long, CuAwardsControl> cuAwardsControlMap) {
        String key = getMemberCountryKey(awardsMap, parentMemberTree, cuAwardsControlMap);
        return rangeDtoMap.get(key);
    }

    /**
     * @param awardsMap        奖衔
     * @param parentMemberTree 会员树历史记录
     * @Description: 获取会员的极差等级，验证会员是否有奖衔
     * @return: String
     * @Author: sui q
     * @Date: 2023/1/4 14:22
     */
    protected String getMemberKey(Map<String, BdAwards> awardsMap, CuMemberTree parentMemberTree) {
        String key = Integer.toString(ERangeType.AWARDS.getValue()) + parentMemberTree.getPkAwards();
        String awardKey = parentMemberTree.getPkSettleCountry().toString() + parentMemberTree.getPkAwards().toString();
        if (EAwards.MEMBER.getValue() == awardsMap.get(awardKey).getAwardsValue()) {
            key = Integer.toString(ERangeType.GRADE.getValue()) + parentMemberTree.getPkGrade();
        }
        return key;
    }

    /**
     * @param saOrderExt            订单
     * @param targetMemberSettleExt 奖金网体
     * @param cuMemberBonus         奖金主表
     * @Description: 奖金明细 报单服务费、分红、云代首购、云代复购、海豆收益
     * @return: CuMemberBonusDetail
     * @Author: sui q
     * @Date: 2023/1/5 16:31
     */
    protected CuMemberBonusDetail getCuMemberBonusDetail(SaOrder saOrderExt, CuMemberSettleExt targetMemberSettleExt, CuMemberBonus cuMemberBonus) {
        CuMemberBonusDetail cuMemberBonusDetail = CuMemberBonusDetail.builder()
                .pkBonus(cuMemberBonus.getPkId())
                .pkOrder(saOrderExt.getPkId())
                .calType(ECalType.RATIO.getValue())
                .incomeStatus(targetMemberSettleExt.getIncomeStatus())
                .calAchieve(saOrderExt.getOrderAchieve())
                .pretaxIncome(BigDecimal.ZERO)
                .incomeTax(BigDecimal.ZERO)
                .realIncome(BigDecimal.ZERO)
                .incomeRatio(BigDecimal.ZERO)
                .incomeDialRatio(BigDecimal.ZERO)
                .orderDialRatio(BigDecimal.ZERO)
                .build();
        cuMemberBonusDetail.setPkCountry(targetMemberSettleExt.getPkSettleCountry());
        cuMemberBonusDetail.setPkCreator(MagicNumberConstants.PK_ADMIN);
        return cuMemberBonusDetail;
    }

    /**
     * @param cuMemberBonus 奖金明细
     * @param bonusDetail   奖金明细表
     * @Description: 设置奖金扣项，计算税前收益，扣税，实际收益, 设置主表
     * @return: void
     * @Author: sui q
     * @Date: 2023/1/11 11:17
     */
    protected void setBonusDeduct(BdBonusDeduct bdBonusDeduct, CuMemberBonus cuMemberBonus, Object bonusDetail) {
        BigDecimal pretaxIncome = ReflectUtils.invokeGetter(bonusDetail, BonusFieldConstants.PRETAX_INCOME);
        BigDecimal backRatio = BigDecimal.ZERO;
        BigDecimal platformRatio = BigDecimal.ZERO;
        if (bdBonusDeduct != null) {
            backRatio = bdBonusDeduct.getBackRatio();
            platformRatio = bdBonusDeduct.getPlatformRatio();
        }
        cuMemberBonus.setBackPoints(ComputeUtil.computeAdd(cuMemberBonus.getBackPoints(), ComputeUtil.computeBonusMultiply(pretaxIncome, backRatio)));
        cuMemberBonus.setServiceSpend(ComputeUtil.computeAdd(cuMemberBonus.getServiceSpend(), ComputeUtil.computeBonusMultiply(pretaxIncome, platformRatio)));
    }

    /**
     * @Description: 首购计算 扣项，小计，总计
     * @return: void
     * @Author: sui q
     * @Date: 2023/1/11 13:59
     */
    protected void setFirstPurchaseTotal(BdBonusDeduct bdBonusDeduct, CuMemberBonus cuMemberBonus, Object bonusDetail) {
        setBonusDeduct(bdBonusDeduct, cuMemberBonus, bonusDetail);
        BigDecimal realIncome = ReflectUtils.invokeGetter(bonusDetail, BonusFieldConstants.REAL_INCOME);
        cuMemberBonus.setPurRealSubtotal(ComputeUtil.computeAdd(cuMemberBonus.getPurRealSubtotal(), realIncome));
        cuMemberBonus.setRealIncomeTotal(ComputeUtil.computeAdd(cuMemberBonus.getRealIncomeTotal(), realIncome));
    }

    /**
     * @Description: 复购计算 扣项，小计，总计
     * @return: void
     * @Author: sui q
     * @Date: 2023/1/11 13:59
     */
    protected void setPurchaseTotal(BdBonusDeduct bdBonusDeduct, CuMemberBonus cuMemberBonus, Object bonusDetail) {
        setBonusDeduct(bdBonusDeduct, cuMemberBonus, bonusDetail);
        BigDecimal realIncome = ReflectUtils.invokeGetter(bonusDetail, BonusFieldConstants.REAL_INCOME);
        cuMemberBonus.setRepurRealSubtotal(ComputeUtil.computeAdd(cuMemberBonus.getRepurRealSubtotal(), realIncome));
        cuMemberBonus.setRealIncomeTotal(ComputeUtil.computeAdd(cuMemberBonus.getRealIncomeTotal(), realIncome));
    }

    /**
     * @param cuMemberDetail 奖金明细
     * @param orderAmount    订单金额
     * @param exchangeRate   入汇率
     * @Description: 设置奖金扣项，计算税前收益，扣税，实际收益, 设置明细表
     * @return: void
     * @Author: sui q
     * @Date: 2023/1/11 11:17
     */
    protected BdBonusDeduct setBonusDetailDeduct(BonusConfigDTO bonusConfigDTO, Object cuMemberDetail, BigDecimal orderAmount, BigDecimal exchangeRate) {
        Integer pkBonusItems = ReflectUtils.invokeGetter(cuMemberDetail, BonusFieldConstants.PK_BONUS_ITEMS);
        BdBonusDeduct bdBonusDeduct = bonusConfigDTO.getBonusDeductsMap().get(pkBonusItems);
        BigDecimal pretaxIncome = ReflectUtils.invokeGetter(cuMemberDetail, BonusFieldConstants.PRETAX_INCOME);
        BigDecimal incomeTax = BigDecimal.ZERO;
        if (bdBonusDeduct != null) {
            incomeTax = ComputeUtil.computeBonusMultiply(pretaxIncome, ComputeUtil.computeAdd(bdBonusDeduct.getPlatformRatio(), bdBonusDeduct.getBackRatio()));
        }
        BigDecimal realIncome = ComputeUtil.computeSubtract(pretaxIncome, incomeTax);
        ReflectUtils.invokeSetter(cuMemberDetail, BonusFieldConstants.INCOME_TAX, incomeTax);
        ReflectUtils.invokeSetter(cuMemberDetail, BonusFieldConstants.REAL_INCOME, realIncome);
        // 收益占比
        ReflectUtils.invokeSetter(cuMemberDetail, BonusFieldConstants.INCOME_RATIO, ComputeUtil.computeDivide(realIncome, ComputeUtil.computeDivide(orderAmount, exchangeRate)));
        return bdBonusDeduct;
    }

    protected void setCuMemberAchieve(SaOrderExt saOrderExt, Map<Long, CuMemberSettleExt> cuMemberSettleExtMap, BonusConfigDTO bonusConfigDTO) {
        CuMemberSettleExt cuMemberSettleExt = cuMemberSettleExtMap.get(saOrderExt.getPkMember());
        cuMemberSettleExt.setRegisterAmount(ComputeUtil.computeAdd(cuMemberSettleExt.getRegisterAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
        cuMemberSettleExt.setRegisterPv(ComputeUtil.computeAdd(cuMemberSettleExt.getRegisterPv(), saOrderExt.getOrderAchieve()));
        cuMemberSettleExt.setRegisterNewAmount(ComputeUtil.computeAdd(cuMemberSettleExt.getRegisterNewAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
        cuMemberSettleExt.setRegisterNewPv(ComputeUtil.computeAdd(cuMemberSettleExt.getRegisterNewPv(), saOrderExt.getOrderAchieve()));
    }

    /**
     * @Description: 根据订单分类，分为首购、复购、真实，获取新增业绩
     * @param orderExtList 订单列表
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/2 11:24
     */
    public void assortSaOrder(Map<Long, MemberAchieveParam> cuMemberAchieveHashMap, List<SaOrderExt> orderExtList, Boolean isFirst, BonusConfigDTO bonusConfigDTO) {
        // 注册+升级+云代注册+云代升级 首购  除（注册+升级）其他 复购  首购+复购 = 真实
        for (SaOrderExt saOrderExt : orderExtList) {
            MemberAchieveParam cuMemberAchieve;
            if (cuMemberAchieveHashMap.containsKey(saOrderExt.getPkMember())) {
                cuMemberAchieve = cuMemberAchieveHashMap.get(saOrderExt.getPkMember());
                // 所有的都算真实业绩
            }else{
                cuMemberAchieve = MemberAchieveParam.builder()
                        .pkRate(saOrderExt.getPkRate())
                        .pkMember(saOrderExt.getPkMember())
                        .newAmount(BigDecimal.ZERO)
                        .newPv(BigDecimal.ZERO)
                        .registerBloNewPv(BigDecimal.ZERO)
                        .repurchaseBloNewAmount(BigDecimal.ZERO)
                        .build();
                cuMemberAchieveHashMap.put(saOrderExt.getPkMember(), cuMemberAchieve);
            }
            if(isFirst) {
                cuMemberAchieve.setNewAmount(ComputeUtil.computeAdd(cuMemberAchieve.getNewAmount(), saOrderExt.getOrderAmount()));
                cuMemberAchieve.setNewPv(ComputeUtil.computeAdd(cuMemberAchieve.getNewPv(), saOrderExt.getOrderAchieve()));
                cuMemberAchieve.setRegisterBloNewPv(ComputeUtil.computeAdd(cuMemberAchieve.getRegisterBloNewPv(), saOrderExt.getOrderAchieve()));
            }else{
                cuMemberAchieve.setRepurchaseBloNewAmount(ComputeUtil.computeAdd(cuMemberAchieve.getRepurchaseBloNewAmount(), convertLocalCurrency(saOrderExt, bonusConfigDTO)));
            }

        }
    }

    protected BigDecimal convertLocalCurrency(SaOrder saOrderExt, BonusConfigDTO bonusConfigDTO) {
        Map<String, BdCurrencyDTO> currencyDtoMap = bonusConfigDTO.getCurrencyDtoMap();
        String key = saOrderExt.getPkCountry().toString() + saOrderExt.getPkRate();
        BigDecimal orderAmount = BigDecimal.ZERO;
        if (currencyDtoMap.containsKey(key)) {
            orderAmount = ComputeUtil.computeDivide(saOrderExt.getOrderAmount(), currencyDtoMap.get(key).getOutExchangeRate());
        }
        return orderAmount;
    }

    protected boolean validateExistBonus(CuMemberSettleExt targetMemberSettleExt, String settleDate){
        return targetMemberSettleExt.getExpireDate() == null || DateUtils.compareDateBefore(targetMemberSettleExt.getExpireDate(), DateUtils.parseStringToDate(settleDate));
    }
}
