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

import com.hzs.bonus.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.bonus.achieve.service.ICuMemberTreeService;
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.reflect.ReflectUtils;
import com.hzs.common.domain.bonus.BdBonusDeduct;
import com.hzs.common.domain.member.achieve.ext.CuMemberRetailRangeExt;
import com.hzs.common.domain.member.bonus.*;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.order.SaOrder;
import com.hzs.common.domain.system.config.ext.BdBonusItemsExt;
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 abstract class BonusSettleHandle {

    @Autowired
    protected ICuMemberTreeService cuMemberTreeService;
    @Autowired
    private ICuMemberSettlePeriodService cuMemberSettlePeriodService;

    public ICuMemberSettlePeriodService getCuMemberSettlePeriodService() {
        return cuMemberSettlePeriodService;
    }

    /**
     * 获得奖项主键，验证该国是否有该奖项
     *
     * @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 null == bdBonusItemsExt || null == bdBonusItemsExt.getPkId();
    }

    /**
     * 获得奖项主键
     *
     * @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 saOrder                 订单编号
     * @param cuMemberBonusCoach      培育津贴
     * @param sourceCuMemberRetailExt 提供奖金的人
     * @param targetCuMemberRetailExt 获得奖金的人
     */
    protected void retailCoachRemark(SaOrder saOrder, CuMemberBonusCoach cuMemberBonusCoach,
                                     CuMemberRetailRangeExt sourceCuMemberRetailExt, CuMemberRetailRangeExt targetCuMemberRetailExt) {
        String remark = String.format(BonusMsgConstants.RETAIL_COACH, cuMemberBonusCoach.getCurrentGeneration(), saOrder.getOrderCode(),
                sourceCuMemberRetailExt.getMemberCode() + sourceCuMemberRetailExt.getMemberName(),
                targetCuMemberRetailExt.getMemberCode() + targetCuMemberRetailExt.getMemberName(),
                cuMemberBonusCoach.getCalAchieve(), cuMemberBonusCoach.getCalValue());
        cuMemberBonusCoach.setRemark(remark);
    }

    /**
     * 获得 直推级差收益的备注
     *
     * @param saOrderExt           订单编号
     * @param cuMemberBonusRange   报单服务费
     * @param sourceMemberRangeExt 提供奖金的人
     * @param targetMemberRangeExt 获得奖金的人
     */
    protected void rangeRetailRemark(SaOrderExt saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberRetailRangeExt sourceMemberRangeExt,
                                     CuMemberRetailRangeExt targetMemberRangeExt) {
        String remark = String.format(BonusMsgConstants.RANGE, saOrderExt.getOrderCode(),
                sourceMemberRangeExt.getMemberCode() + sourceMemberRangeExt.getMemberName(),
                targetMemberRangeExt.getMemberCode() + targetMemberRangeExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), sourceMemberRangeExt.getGradeName(), targetMemberRangeExt.getGradeName());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * 获得 福利极差收益 备注
     *
     * @param saOrderExt           订单编号
     * @param cuMemberBonusRange   报单服务费
     * @param sourceMemberRangeExt 提供奖金的人
     * @param targetMemberRangeExt 获得奖金的人
     */
    protected void rangeBenefitRetailRemark(SaOrder saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberRetailRangeExt sourceMemberRangeExt,
                                            CuMemberRetailRangeExt targetMemberRangeExt) {
        String remark = String.format(BonusMsgConstants.RETAIL_RANGE, saOrderExt.getOrderCode(),
                sourceMemberRangeExt.getMemberCode() + sourceMemberRangeExt.getMemberName(),
                targetMemberRangeExt.getMemberCode() + targetMemberRangeExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), sourceMemberRangeExt.getAwardsName(), targetMemberRangeExt.getAwardsName());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * 获得 复购极差收益 备注
     *
     * @param saOrderExt           订单编号
     * @param cuMemberBonusRange   报单服务费
     * @param sourceMemberRangeExt 提供奖金的人
     * @param targetMemberRangeExt 获得奖金的人
     */
    protected void rangeMonthRepurchaseRetailRemark(SaOrder saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberRetailRangeExt sourceMemberRangeExt,
                                                    CuMemberRetailRangeExt targetMemberRangeExt) {
        String remark = String.format(BonusMsgConstants.RETAIL_MONTH_REPURCHASE_INCOME, saOrderExt.getOrderCode(),
                sourceMemberRangeExt.getMemberCode() + sourceMemberRangeExt.getMemberName(),
                targetMemberRangeExt.getMemberCode() + targetMemberRangeExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), sourceMemberRangeExt.getAwardsName(), targetMemberRangeExt.getAwardsName());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * 获得 平级收益的备注
     *
     * @param saOrderExt           订单编号
     * @param cuMemberBonusRange   报单服务费
     * @param sourceMemberRangeExt 提供奖金的人
     * @param targetMemberRangeExt 获得奖金的人
     */
    protected void oriRetailRangeRemark(SaOrderExt saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberRetailRangeExt sourceMemberRangeExt,
                                        CuMemberRetailRangeExt targetMemberRangeExt) {
        String remark = String.format(BonusMsgConstants.ORI_RANGE, saOrderExt.getOrderCode(),
                sourceMemberRangeExt.getMemberCode() + sourceMemberRangeExt.getMemberName(),
                targetMemberRangeExt.getMemberCode() + targetMemberRangeExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), targetMemberRangeExt.getGradeName());
        cuMemberBonusRange.setRemark(remark);
    }

    /**
     * 获得 复购极差收益 备注
     *
     * @param saOrderExt           订单编号
     * @param cuMemberBonusRange   报单服务费
     * @param sourceMemberRangeExt 提供奖金的人
     * @param targetMemberRangeExt 获得奖金的人
     */
    protected void rangeRepurchaseRetailRemark(SaOrder saOrderExt, CuMemberBonusRange cuMemberBonusRange, CuMemberRetailRangeExt sourceMemberRangeExt,
                                                    CuMemberRetailRangeExt targetMemberRangeExt) {
        String remark = String.format(BonusMsgConstants.RETAIL_REPURCHASE_INCOME, saOrderExt.getOrderCode(),
                sourceMemberRangeExt.getMemberCode() + sourceMemberRangeExt.getMemberName(),
                targetMemberRangeExt.getMemberCode() + targetMemberRangeExt.getMemberName(),
                cuMemberBonusRange.getCalAchieve(), targetMemberRangeExt.getGradeName());
        cuMemberBonusRange.setRemark(remark);
    }

    protected CuMemberBonus getCuMemberBonus(Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap,
                                             Long pkMember, Integer incomeStatus, Integer pkCountry, Integer pkRate) {
        if (cuMemberBonusMap.containsKey(pkMember)) {
            return cuMemberBonusMap.get(pkMember);
        } else {
            CuMemberBonus cuMemberBonus = CuMemberBonus.builder()
                    // 暂时赋值一个long，暂时把主子表关联起来，计算后，从数据库获得索引，在修改
                    .pkId(pkMember)
                    .pkMember(pkMember)
                    .period(period)
                    .pkRate(pkRate)
                    .incomeStatus(incomeStatus)
                    .directIncome(BigDecimal.ZERO)
                    .expandIncome(BigDecimal.ZERO)
                    .expandNoCapping(BigDecimal.ZERO)
                    .expandCapping(BigDecimal.ZERO)
                    .coachIncome(BigDecimal.ZERO)
                    .shareIncome(BigDecimal.ZERO)
                    .serviceIncome(BigDecimal.ZERO)
                    .backPoints(BigDecimal.ZERO)
                    .serviceSpend(BigDecimal.ZERO)
                    .purRealSubtotal(BigDecimal.ZERO)
                    .repurPushIncome(BigDecimal.ZERO)
                    .repurRangeIncome(BigDecimal.ZERO)
                    .repurExpandIncome(BigDecimal.ZERO)
                    .repurRealSubtotal(BigDecimal.ZERO)
                    .cloudDirectIncome(BigDecimal.ZERO)
                    .cloudPurIncome(BigDecimal.ZERO)
                    .cloudRepurIncome(BigDecimal.ZERO)
                    .cloudRealSubtotal(BigDecimal.ZERO)
                    .repurCoupon(BigDecimal.ZERO)
                    .repurCouponShare(BigDecimal.ZERO)
                    .repurCouponSubtotal(BigDecimal.ZERO)
                    .globalPoints(BigDecimal.ZERO)
                    .carAwardPoints(BigDecimal.ZERO)
                    .hiFunIncome(BigDecimal.ZERO)
                    .haiFunIncome(BigDecimal.ZERO)
                    .storeIncome(BigDecimal.ZERO)
                    .makerDirectIncome(BigDecimal.ZERO)
                    .makerShareIncome(BigDecimal.ZERO)
                    .makerRealSubtotal(BigDecimal.ZERO)
                    .realIncomeTotal(BigDecimal.ZERO)
                    .retailRangeIncome(BigDecimal.ZERO)
                    .retailSameLevelIncome(BigDecimal.ZERO)
                    .retailAreaIncome(BigDecimal.ZERO)
                    .retailBenefitRangeIncome(BigDecimal.ZERO)
                    .retailMonthRepurchaseIncome(BigDecimal.ZERO)
                    .retailBenefitAvgIncome(BigDecimal.ZERO)
                    .retailBenefitIncome(BigDecimal.ZERO)
                    .retailRealSubtotal(BigDecimal.ZERO)
                    .build();
            cuMemberBonus.setPkCreator(MagicNumberConstants.PK_ADMIN);
            cuMemberBonus.setPkCountry(pkCountry);
            cuMemberBonus.setGrantStatus(EGrantStatus.SETTLED.getValue());
            cuMemberBonusMap.put(pkMember, cuMemberBonus);
            return cuMemberBonus;
        }
    }

    /**
     * 设置奖金扣项，计算税前收益，扣税，实际收益, 设置主表
     *
     * @param cuMemberBonus 奖金明细
     * @param bonusDetail   奖金明细表
     */
    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)));
    }

    /**
     * 扣项，小计，总计
     */
    protected void setRetailTotal(BdBonusDeduct bdBonusDeduct, CuMemberBonus cuMemberBonus, Object bonusDetail) {
        setBonusDeduct(bdBonusDeduct, cuMemberBonus, bonusDetail);
        BigDecimal realIncome = ReflectUtils.invokeGetter(bonusDetail, BonusFieldConstants.REAL_INCOME);
        cuMemberBonus.setRetailRealSubtotal(ComputeUtil.computeAdd(cuMemberBonus.getRetailRealSubtotal(), realIncome));
        cuMemberBonus.setRealIncomeTotal(ComputeUtil.computeAdd(cuMemberBonus.getRealIncomeTotal(), realIncome));
    }

    /**
     * 设置奖金扣项，计算税前收益，扣税，实际收益, 设置明细表
     *
     * @param cuMemberDetail 奖金明细
     * @param orderAmount    订单金额
     * @param exchangeRate   入汇率
     */
    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;
    }

}
