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

import com.hzs.bonus.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.bonus.bonus.service.*;
import com.hzs.bonus.bonus.vo.BonusRecordDetailVO;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.member.bonus.*;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.system.config.IBonusItemsServiceApi;
import com.hzs.system.config.dto.BonusConfigDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
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
@Slf4j
public class BonusSettleServiceImpl implements IBonusSettleService {

    @DubboReference
    IBonusItemsServiceApi iBonusItemsServiceApi;

    @Autowired
    private ICuMemberSettlePeriodService iCuMemberSettlePeriodService;
    @Autowired
    private ICuMemberBonusService iCuMemberBonusService;
    @Autowired
    private ICuMemberBonusPushService iCuMemberBonusPushService;
    @Autowired
    private ICuMemberBonusDetailService iCuMemberBonusDetailService;
    @Autowired
    private ICuMemberBonusRangeService iCuMemberBonusRangeService;
    @Autowired
    private BonusSettleRangeHandle bonusSettleRangeHandle;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void calculateCuMemberBonus(String settleDate, List<SaOrderExt> saOrderExtList) {
        try {
            // 结算期间
            Integer period = iCuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(settleDate).getPkId();
            String yesterday = DateUtils.beforeDateStr(1, ChronoUnit.DAYS, DateUtils.YYYY_MM_DD, settleDate);
            // 结算期间前一天期间
            Integer yesterdayPeriod = iCuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(yesterday).getPkId();

            // 将删除的订单的点位变为死点
            //********************************* 更新当天最新的业绩*************************/
            // 获取所有国家的奖金项 key = 国家 + 奖金项的值
            BonusConfigDTO bonusConfigDTO = iBonusItemsServiceApi.queryBonusConfigDTO().getData();
            // 会员奖金map（key:会员ID，
            Map<Long, CuMemberBonus> cuMemberBonusMap = new HashMap<>();
            // 奖金明细（入库使用）
            BonusRecordDetailVO recordDetailVO = new BonusRecordDetailVO();
            // 今天和昨天是否同月
            Boolean isSameMonth = DateUtils.getMonth(settleDate).equals(DateUtils.getMonth(yesterday));

            // 计算新零售奖金
            bonusSettleRangeHandle.calculateRetailBonusByDay(settleDate, cuMemberBonusMap, bonusConfigDTO, recordDetailVO,
                    period, yesterdayPeriod, isSameMonth);

            // 保存当日计算的奖金
            insertCuMemberBonus(settleDate, period, cuMemberBonusMap, recordDetailVO);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 计算每天的奖金入库
     *
     * @param cuMemberBonusMap    奖金主表
     * @param bonusRecordDetailVO 奖金明细表
     */
    void insertCuMemberBonus(String settleDate, Integer period, Map<Long, CuMemberBonus> cuMemberBonusMap, BonusRecordDetailVO bonusRecordDetailVO) {
        iCuMemberBonusPushService.deleteCuMemberBonusPush(period);
        iCuMemberBonusDetailService.deleteCuMemberBonusDetail(period);
        iCuMemberBonusRangeService.deleteCuMemberBonusRange(period);
        iCuMemberBonusService.deleteCuMemberBonus(period);
        if (cuMemberBonusMap.size() == 0) {
            return;
        }
        List<CuMemberBonusPush> batchMemberBonusPushList = new ArrayList<>();
        List<CuMemberBonusDetail> batchMemberBonusDetailList = new ArrayList<>();
        List<CuMemberBonusRange> batchMemberBonusRangeList = new ArrayList<>();
        List<CuMemberBonus> cuMemberBonusList = setCuMemberBonusSeq(settleDate, cuMemberBonusMap);
        List<CuMemberBonusPush> cuMemberBonusPushList = bonusRecordDetailVO.getCuMemberBonusPushList();
        List<CuMemberBonusDetail> cuMemberBonusDetailList = bonusRecordDetailVO.getCuMemberBonusDetailList();
        List<CuMemberBonusRange> cuMemberBonusRangeList = bonusRecordDetailVO.getCuMemberBonusRangeList();
        if (cuMemberBonusPushList != null && cuMemberBonusPushList.size() > 0) {
            cuMemberBonusPushList.forEach(cuMemberBonusPush ->
                    cuMemberBonusPush.setPkBonus(cuMemberBonusMap.get(cuMemberBonusPush.getPkBonus()).getPkId()));
            batchMemberBonusPushList.addAll(cuMemberBonusPushList);
        }
        if (cuMemberBonusDetailList != null && cuMemberBonusDetailList.size() > 0) {
            cuMemberBonusDetailList.forEach(cuMemberBonusDetail ->
                    cuMemberBonusDetail.setPkBonus(cuMemberBonusMap.get(cuMemberBonusDetail.getPkBonus()).getPkId()));
            batchMemberBonusDetailList.addAll(cuMemberBonusDetailList);
        }
        if (cuMemberBonusRangeList != null && cuMemberBonusRangeList.size() > 0) {
            cuMemberBonusRangeList.forEach(cuMemberBonusRange ->
                    cuMemberBonusRange.setPkBonus(cuMemberBonusMap.get(cuMemberBonusRange.getPkBonus()).getPkId()));
            batchMemberBonusRangeList.addAll(cuMemberBonusRangeList);
        }
        // 插入奖金主表
        iCuMemberBonusService.batchInsertCuMemberBonus(cuMemberBonusList);
        Set<Long> memberIdSet = iCuMemberBonusService.queryMemberBonusByPeriod(period);
        iCuMemberBonusPushService.batchInsertCuMemberBonusPush(batchMemberBonusPushList, memberIdSet);
        iCuMemberBonusDetailService.batchInsertCuMemberBonusDetail(batchMemberBonusDetailList, memberIdSet);
        iCuMemberBonusRangeService.batchInsertCuMemberBonusRange(batchMemberBonusRangeList, memberIdSet);
    }

    private List<CuMemberBonus> setCuMemberBonusSeq(String settleDate, Map<Long, CuMemberBonus> cuMemberBonusMap) {
        List<Long> pkIdList = iCuMemberBonusService.batchQueryCuMemberBonusSeq(cuMemberBonusMap.size());
        int i = 0;
        // 判断时间，重算的时候直接是已公布
        Integer grantStatus = EGrantStatus.SETTLED.getValue();
        if (DateUtils.compareDate(DateUtils.parseStringToDate(settleDate), DateUtils.beforeDate(2, ChronoUnit.DAYS)) <= 0) {
            grantStatus = EGrantStatus.PUBLISHED.getValue();
        }
        List<CuMemberBonus> cuMemberBonusList = new ArrayList<>();
        for (CuMemberBonus cuMemberBonus : cuMemberBonusMap.values()) {
            cuMemberBonus.setPkId(pkIdList.get(i));
            cuMemberBonus.setGrantStatus(grantStatus);
            cuMemberBonusList.add(cuMemberBonus);
            i++;
        }
        return cuMemberBonusList;
    }

}
