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

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.bonus.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.bonus.detail.service.ICuMemberAssessDetailService;
import com.hzs.bonus.detail.service.ICuMemberAssessService;
import com.hzs.common.core.constant.TableNameConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.member.achieve.CuMemberSettlePeriod;
import com.hzs.common.domain.member.detail.CuMemberAssess;
import com.hzs.bonus.detail.mapper.CuMemberAssessMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * 会员信息-会员考核记录 服务实现类
 */
@Service
public class CuMemberAssessServiceImpl extends ServiceImpl<CuMemberAssessMapper, CuMemberAssess> implements ICuMemberAssessService {

    private ICuMemberSettlePeriodService cuMemberSettlePeriodService;

    private ICuMemberAssessDetailService cuMemberAssessDetailService;

    @Autowired
    public void setCuMemberAssessDetailService(ICuMemberAssessDetailService cuMemberAssessDetailService) {
        this.cuMemberAssessDetailService = cuMemberAssessDetailService;
    }

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

    /**
     * 复购考核每月第一次考核调用此方法
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void calculationCuMemberAssess(Date currentDate) {
        // 查询当前时间的第一天跟最后一天
        // 需要验证考核国家是否有复购考核 分红考核
        // 考核日期不能跨越考核，只能当月考核，当月考核上月
        if (DateUtils.currentDay(currentDate) == 1) {
            String currentMonthFirstDate = DateUtils.currentMonthFirstDateStr(currentDate);
            Integer currentPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(currentMonthFirstDate).getPkId();
            String currentTableName = TableNameConstants.CU_MEMBER_ASSESS + DateUtils.getYear(currentMonthFirstDate);
            // 清空数据  根据期数清空cu_member_assess  cu_member_assess_detail表数据
            initCurrentAssess(currentDate, currentTableName, currentPeriod);
            // 初始化复购考核的上月结余
            initCurrentAssessByBeforeMonth(currentDate, currentTableName, currentPeriod, EAssessmentType.REPURCHASE_ASSESS.getValue());
            // 初始化分红考核的上月结余
//            initCurrentAssessByBeforeMonth(currentDate, currentTableName, currentPeriod, EAssessmentType.SHARE_ASSESS.getValue());
            // 更新当月结余 结余会同时更新复购跟分红，只需要更新一次
            // 1 有免考状态的 本月使用是 0，考核状态是免考通过，免考将所有的值更改一下期末 期末= 期初+本月
            // 注意 不修改考核状态为通过的值，可能存在之前考核通过，又手动免考的人
            baseMapper.updateAssessPeriodExemptBalanceByUsed(currentTableName, currentPeriod);
            // 2 需要扣除通过的，需要记录流水
            // 记录流水，新增或修改
            cuMemberAssessDetailService.updateCuMemberAssessDetailByPeriod(currentTableName, currentPeriod);
            baseMapper.updateAssessPeriodCheckBalanceByUsed(currentTableName, currentPeriod);
        }
    }

    /**
     * 奖金计算时重算考核 （复购考核、分红考核）,只重算免考的、撤单的
     *
     * @param currentDate 考核时间
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void retryCalculationAssess(Date currentDate, Boolean flag) {
        Integer currentPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, currentDate)).getPkId();
        Date startDate = DateUtils.beforeMonthFirstDate(currentDate);
//        // 结算日期后一天
        Date endDate = DateUtils.afterDate(1, ChronoUnit.DAYS, DateUtils.currentMonthLastDate(currentDate));
        String settleTableName = TableNameConstants.CU_MEMBER_SETTLE + currentPeriod;
//        // 首次晋升、首次升级都是当月加下月考核，查询出上月1号到考核日期的值，
//        // 等级看会员表支付时间，奖衔看奖衔变更表是否免考（分组取）,手动免考查看 最新的结算表手动考核
////        d)前一天不免考，后一天免考，需要做重新考核，直接变考核通过，原来考核通过的不回退考核金额，且考核状态为考核通过，不是免考通过
//        // 所有的海粉会员设置复购考核失败，存在任意订单的海粉会员复购考核成功
//        // 复购免考通过
        Integer startPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(DateUtils.parseDateToFormat(DateUtils.YYYY_MM_DD, startDate)).getPkId();
        Integer endPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(DateUtils.parseDateToFormat(DateUtils.YYYY_MM_DD, endDate)).getPkId();
//        baseMapper.updateAssessCuMemberToRepExempt(tableName, settleTableName, monthFirstPeriod, startDate, endDate, startPeriod, endPeriod);
//        // 奖金重算时更新结算表,flag=true代表奖金重算时，重算考核需要更新网体 flag=false 代表重算考核
        if (flag) {
            // 2024-09-09 所有人全部免考通过,之后的当月免考通过
            if (DateUtils.compareDateBefore(currentDate, DateUtils.parseStringToDate("2024-10-01"))) {
                baseMapper.updateAllCuMemberSettleToRepExempt(settleTableName);
            } else {
                baseMapper.updateCuMemberSettleToRepExempt(settleTableName, startDate, endDate, startPeriod, endPeriod);
            }
        }
    }

    private void initCurrentAssess(Date currentDate, String currentTableName, Integer currentPeriod) {
        // 获取上月最后一天
        String beforeLastDate = DateUtils.beforeMonthLastDateStr(currentDate);
        CuMemberSettlePeriod cuMemberSettlePeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(beforeLastDate);
        int period = cuMemberSettlePeriod.getPkId();
        String sourceTable = TableNameConstants.CU_MEMBER_SETTLE + period;
        String rangeSourceTable = TableNameConstants.CU_MEMBER_RANGE + period;
        // 清空子表、主表数据
        cuMemberAssessDetailService.deleteCuMemberAssessDetailByPeriod(currentTableName, currentPeriod);
        baseMapper.deleteCuMemberAssessByPeriod(currentTableName, currentPeriod);
        // 初始化复购考核
        String month = DateUtils.getMonth(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, currentDate));
        // 结算日期后一天
        baseMapper.insertRepCuMemberAssess(currentTableName, sourceTable, currentPeriod, month);
        baseMapper.insertRepCuMemberRangeAssess(currentTableName, rangeSourceTable, currentPeriod, month);

//        a)更新结算表会员前2部分会员免考状态 满足首次注册的会员 满足满足首次升级的会员
        String tableName = TableNameConstants.CU_MEMBER_ASSESS + DateUtils.currentYear(currentDate);
        String currentMonthFirstDateStr = DateUtils.currentMonthFirstDateStr(currentDate);
        Integer monthFirstPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(currentMonthFirstDateStr).getPkId();
        // 结算日期月份的第一天
        Date startDate = DateUtils.beforeMonthFirstDate(currentDate);
        // 结算日期后一天
        Date endDate = DateUtils.afterDate(1, ChronoUnit.DAYS, DateUtils.currentMonthLastDate(currentDate));
        String settleTableName = TableNameConstants.CU_MEMBER_SETTLE + currentPeriod;
        if (DateUtils.currentDay(DateUtils.currentDate()) == 1) {
            String currentMonthFirstDate = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, DateUtils.beforeDate(1, ChronoUnit.DAYS, currentDate));
            Integer yesterdayPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(currentMonthFirstDate).getPkId();
            settleTableName = TableNameConstants.CU_MEMBER_SETTLE + yesterdayPeriod;
        }
        // 首次晋升、首次升级都是当月加下月考核，查询出上月1号到考核日期的值，
        // 等级看会员表支付时间，奖衔看奖衔变更表是否免考（分组取）,手动免考查看 最新的结算表手动考核
//        d)前一天不免考，后一天免考，需要做重新考核，直接变考核通过，原来考核通过的不回退考核金额，且考核状态为考核通过，不是免考通过
        // 复购免考通过
        Integer startPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(DateUtils.parseDateToFormat(DateUtils.YYYY_MM_DD, startDate)).getPkId();
        Integer endPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(DateUtils.parseDateToFormat(DateUtils.YYYY_MM_DD, endDate)).getPkId();
        baseMapper.updateAssessCuMemberToRepExempt(tableName, settleTableName, monthFirstPeriod, startDate, endDate, startPeriod, endPeriod);

        // 初始化订单数据，将当月新增加入数据库
        // 上月第一天，上月最后一天
        Date beforeFirstDate = DateUtils.beforeMonthFirstDate(currentDate);
        Date currentFirstDate = DateUtils.currentMonthFirstDate(currentDate);
        cuMemberAssessDetailService.insertCuMemberAssesDetailByOrder(currentTableName, currentPeriod, beforeFirstDate, currentFirstDate);
    }

    /**
     * 初始化期初数据，将上月结余作为本月期初，更新当月新增
     *
     * @param currentDate      结算日期
     * @param currentTableName 当前月结算表
     * @param currentPeriod    当前结算期间
     * @param assessmentType   考核类型 0=复购考核 1=分红考核
     */
    private void initCurrentAssessByBeforeMonth(Date currentDate, String currentTableName, Integer currentPeriod, Integer assessmentType) {
        List<Integer> orderTypeList = new ArrayList<>();
        if (EAssessmentType.REPURCHASE_ASSESS.getValue() == assessmentType) {
            orderTypeList.add(EOrderType.REPURCHASE_ORDER.getValue());
            orderTypeList.add(EOrderType.MALL_ORDER.getValue());
        }
        // 更新考核值，期初是上月考核表的当月剩余业绩
        // 获取结算日月初第一天，获取期间
        // 获取结算日上月最后一天，获取期间
        Date beforeMonthFirstDate = DateUtils.beforeMonthFirstDate(currentDate);
        String beforeMonthFirstDateStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, beforeMonthFirstDate);
        Integer beforePeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(beforeMonthFirstDateStr).getPkId();
        String beforeTableName = TableNameConstants.CU_MEMBER_ASSESS + DateUtils.getYear(beforeMonthFirstDateStr);
        Date currentMonthFirstDate = DateUtils.currentMonthFirstDate(currentDate);
        // 初始化复购考核的上月结余 // 更新当月结余
        baseMapper.updateAssessPeriodBeginByBeforeMonth(beforeTableName, currentTableName, beforePeriod, currentPeriod, assessmentType);
        // 更新当月新增
        baseMapper.updateAssessPeriodAddBySaOrder(currentTableName, currentPeriod, assessmentType,
                beforeMonthFirstDate, currentMonthFirstDate, orderTypeList);
    }

}
