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

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.bonus.achieve.service.ICuMemberAchieveService;
import com.hzs.bonus.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.bonus.achieve.service.ICuMemberTreeService;
import com.hzs.bonus.bonus.param.BonusExpandParam;
import com.hzs.bonus.bonus.service.ICuBonusExpandService;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.TableNameConstants;
import com.hzs.common.core.enums.EAwardsType;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.member.achieve.CuMemberTree;
import com.hzs.common.domain.member.ext.CuMemberSettleExt;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.bonus.achieve.mapper.CuMemberTreeMapper;
import lombok.extern.slf4j.Slf4j;
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.*;

/**
 * 会员网体历史记录 服务实现类
 */
@Slf4j
@Service
public class CuMemberTreeServiceImpl extends ServiceImpl<CuMemberTreeMapper, CuMemberTree> implements ICuMemberTreeService {

    private ICuMemberAchieveService cuMemberAchieveService;

    private CuMemberBonusSettle cuMemberBonusSettle;

    private ICuMemberSettlePeriodService cuMemberSettlePeriodService;

    @Autowired
    private ICuBonusExpandService bonusExpandService;

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

    @Autowired
    public void setCuMemberBonusSettle(CuMemberBonusSettle cuMemberBonusSettle) {
        this.cuMemberBonusSettle = cuMemberBonusSettle;
    }

    @Autowired
    public void setCuMemberAchieveService(ICuMemberAchieveService cuMemberAchieveService) {
        this.cuMemberAchieveService = cuMemberAchieveService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createCuMemberTree(String date) {
        // 创建日表记录表
        int period = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(date).getPkId();
        String settleTableName = TableNameConstants.CU_MEMBER_SETTLE + period;
        Integer number = baseMapper.queryExistOracleTable(settleTableName);
        if (number == null || number <= 0) {
            baseMapper.createCuMemberSettleTable(settleTableName);
            baseMapper.createCuMemberTreeDayOnlyIndex(settleTableName);
            baseMapper.createCuMemberTreeParentIndex(settleTableName);
            baseMapper.createCuMemberTreePlaceIndex(settleTableName);
        }
        // 创建新零售极差结算记录表
        String retailRangeTableName = TableNameConstants.CU_MEMBER_RETAIL_RANGE + period;
        number = baseMapper.queryExistOracleTable(retailRangeTableName);
        if (number == null || number <= 0) {
            baseMapper.createCuMemberRetailRangeTable(retailRangeTableName);
            baseMapper.createCuMemberTreeDayOnlyIndex(retailRangeTableName);
            baseMapper.createCuMemberTreeParentIndex(retailRangeTableName);
        }
        number = baseMapper.queryExistOrderTableCount(retailRangeTableName);
        if (number == null || number <= 0) {
            baseMapper.insertCuMemberRetailRangeByMember(retailRangeTableName);
        }

        // 创建月表记录表
        createMonthTreeTableName(date);
        // 创建月表业绩记录表
        cuMemberAchieveService.createCuMemberAchieve(date);

        // 创建秒接表，秒结表只需要表结构，跟日表一模一样，秒结表期间是date+1期间
        Date tomorrowDate = DateUtils.afterDate(1, ChronoUnit.DAYS, DateUtils.parseStringToDate(date));
        String tomorrow = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, tomorrowDate);
        int nextPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(tomorrow).getPkId();
        String secondRetailRangeTableName = TableNameConstants.CU_MEMBER_RETAIL_S + nextPeriod;
        number = baseMapper.queryExistOracleTable(secondRetailRangeTableName);
        if (number == null || number <= 0) {
            baseMapper.createCuMemberRetailRangeSecondTable(secondRetailRangeTableName);
            baseMapper.createCuMemberTreeDayOnlyIndex(secondRetailRangeTableName);
            baseMapper.createCuMemberTreeParentIndex(secondRetailRangeTableName);
        }
        BonusExpandParam bonusExpandParam = BonusExpandParam.builder().settleDate(DateUtils.parseStringToDate(date)).build();
        bonusExpandService.firstSaveCuBonusExpand(bonusExpandParam);
    }

    private String createMonthTreeTableName(String date) {
        Integer number;
        String monthTableName = TableNameConstants.CU_MEMBER_TREE + DateUtils.getMonth(date);
        number = baseMapper.queryExistOracleTable(monthTableName);
        if (number == null || number <= 0) {
            baseMapper.createCuMemberTreeTable(monthTableName);
            baseMapper.createCuMemberTableUniqueIndex(monthTableName);
            baseMapper.createCuMemberTreeParentIndex(monthTableName);
            baseMapper.createCuMemberTreePlaceIndex(monthTableName);
            baseMapper.createCuMemberTableSequence(monthTableName, TableNameConstants.CU_MEMBER_TREE_SEQ);
        }
        return monthTableName;
    }

    @Override
    public void initCuMemberExpandTreeTable(String yesterdaySettleTableName, String currentSettleTableName) {
        cuMemberAchieveService.updateCuMemberExpandSettleAchieveByBeforeDay(yesterdaySettleTableName, currentSettleTableName);
    }

    @Override
    public Integer queryExistOracleTable(String tableName) {
        return baseMapper.queryExistOracleTable(tableName);
    }

    @Override
    public void createCuMemberTableUniqueIndex(String tableName) {
        baseMapper.createCuMemberTableUniqueIndex(tableName);
    }

    @Override
    public void createCuMemberTableSequence(String tableName, String tableNameSeq) {
        baseMapper.createCuMemberTableSequence(tableName, tableNameSeq);
    }

    @Override
    public List<CuMemberSettleExt> queryCuMemberSettleEnoughAwardAchieve(String settleTableName) {
        return baseMapper.queryCuMemberSettleEnoughAwardAchieve(settleTableName);
    }

    @Override
    public void updateBackCuMemberSettleAward(String settleTableName, Integer period) {
        baseMapper.updateBackCuMemberSettleAward(settleTableName, period);
    }

    @Override
    public void updateBackCuMemberSettleRangeAward(String rangeTableName, Integer period) {
        baseMapper.updateBackCuMemberSettleRangeAward(rangeTableName, period);
    }

    @Override
    public void updateBackCuMemberRetailRangeAward(String rangeTableName, Integer period) {
        baseMapper.updateBackCuMemberRetailRangeAward(rangeTableName, period, EAwardsType.RANGE_TYPE.getValue());
        baseMapper.updateBackCuMemberRetailRangeAward(rangeTableName, period, EAwardsType.SHARE_TYPE.getValue());
    }

    @Override
    public void updateCuMemberRetailRangeAwardByDate(String rangeTableName, Date settleDate) {
        baseMapper.updateCuMemberRetailRangeAwardByDate(rangeTableName, settleDate, EAwardsType.RANGE_TYPE.getValue());
        baseMapper.updateCuMemberRetailRangeAwardByDate(rangeTableName, settleDate, EAwardsType.SHARE_TYPE.getValue());
    }

    @Override
    public void updateCuMemberRetailRangeInitAward(String rangeTableName) {
        baseMapper.updateCuMemberRetailRangeInitAward(rangeTableName);
        baseMapper.updateCuMemberRetailRangeInitV5Award(rangeTableName);
    }

    @Override
    public Boolean queryCuMemberSettlePlaceUnderUmbrella(String settleTableName, Integer awardsValue, Integer placeDept, Long pkMember) {
        return baseMapper.queryCuMemberSettlePlaceUnderUmbrella(settleTableName, awardsValue, placeDept, pkMember) > 0;
    }

    @Override
    public Boolean queryCuMemberSettleBloodUnderUmbrella(String settleTableName, Integer awardsValue, Integer placeDept, Long pkMember) {
        return baseMapper.queryCuMemberSettleBloodUnderUmbrella(settleTableName, awardsValue, placeDept, pkMember) > 0;
    }

    @Override
    public void updateCuMemberSettleByPeriod(List<Integer> periodList) {
        periodList.forEach(period -> {
            String updateTableName = TableNameConstants.CU_MEMBER_SETTLE + period;
            baseMapper.updateCuMemberSettleByPeriod(updateTableName, period);
        });
    }

    @Override
    public List<CuMemberSettleExt> batchQueryMemberSettleBySaOrder(String settleTableName, List<SaOrderExt> saOrderExtList) {
        // 查询出推荐人
        Set<Long> serviceMemberSet = new HashSet<>();
        saOrderExtList.forEach(saOrderExt -> {
            serviceMemberSet.add(saOrderExt.getPkReference());
            // 查出自己跟推荐人
            serviceMemberSet.add(saOrderExt.getPkMember());
        });
        return getCuMemberSettleExtList(settleTableName, serviceMemberSet);
    }

    private List<CuMemberSettleExt> getCuMemberSettleExtList(String settleTableName, Set<Long> serviceMemberSet) {
        List<CuMemberSettleExt> cuMemberSettleExtList = new ArrayList<>();
        if (serviceMemberSet.size() > 0) {
            List<Long> memberPkList = Arrays.asList(serviceMemberSet.toArray(new Long[]{}));
            List<List<?>> listList = cuMemberBonusSettle.handleCutList(memberPkList);
            listList.forEach(list ->
                    cuMemberSettleExtList.addAll(baseMapper.queryMemberSettleBySaOrder(settleTableName, list)));
        }
        return cuMemberSettleExtList;
    }

    @Override
    public List<CuMemberSettleExt> batchQueryMemberSettleByMemberPk(String settleTableName, Set<Long> serviceMemberSet) {
        return getCuMemberSettleExtList(settleTableName, serviceMemberSet);
    }

    @Override
    public List<CuMemberSettleExt> queryMemberSettleByAwards(String settleTableName, String rangeTableName, Integer startPeriod, Integer endPeriod) {
        return baseMapper.queryMemberSettleByAwards(settleTableName, rangeTableName, startPeriod, endPeriod);
    }

    @Override
    public List<CuMemberSettleExt> batchQueryMemberSettleParentByMemberPk(String settleTableName, Set<Long> serviceMemberSet) {
        List<CuMemberSettleExt> cuMemberSettleExtList = new ArrayList<>();
        if (serviceMemberSet.size() > 0) {
            List<Long> memberPkList = Arrays.asList(serviceMemberSet.toArray(new Long[]{}));
            List<List<?>> listList = cuMemberBonusSettle.handleCutList(memberPkList);
            listList.forEach(list ->
                    cuMemberSettleExtList.addAll(baseMapper.batchQueryMemberSettleParentByMemberPk(settleTableName, list)));
        }
        return cuMemberSettleExtList;
    }

    @Override
    public Map<Long, List<CuMemberSettleExt>> batchQueryCuMemberSettlePlaceParent(String settleTableName, List<SaOrderExt> firPurchaseOrderList) {
        // 查询出所有父级安置人
        List<CuMemberSettleExt> cuMemberSettleExtList = new ArrayList<>();
        List<List<?>> listList = cuMemberBonusSettle.handleCutList(firPurchaseOrderList, MagicNumberConstants.DELETE_DATA_BATCH_UPDATE_NUM);
        listList.forEach(list ->
                cuMemberSettleExtList.addAll(baseMapper.batchQueryCuMemberSettlePlaceParent(settleTableName, list)));
        Map<Long, List<CuMemberSettleExt>> memberSettleMap = new HashMap<>(ComputeUtil.mapInitCapacity(firPurchaseOrderList.size()));
        cuMemberSettleExtList.forEach(cuMemberSettleExt -> {
            if (memberSettleMap.containsKey(cuMemberSettleExt.getPkOrder())) {
                memberSettleMap.get(cuMemberSettleExt.getPkOrder()).add(cuMemberSettleExt);
            } else {
                List<CuMemberSettleExt> cuMemberSettles = new ArrayList<>();
                cuMemberSettles.add(cuMemberSettleExt);
                memberSettleMap.put(cuMemberSettleExt.getPkOrder(), cuMemberSettles);
            }
        });
        return memberSettleMap;
    }

    @Override
    public List<CuMemberSettleExt> batchQueryCuMemberSettleParent(String settleTableName, Set<Long> expandMemberSet) {
        List<CuMemberSettleExt> cuMemberSettleExtList = new ArrayList<>();
        if (expandMemberSet == null || expandMemberSet.size() == 0) {
            return cuMemberSettleExtList;
        }
        List<Long> memberPkList = Arrays.asList(expandMemberSet.toArray(new Long[]{}));
        List<List<?>> listList = cuMemberBonusSettle.handleCutList(memberPkList, MagicNumberConstants.DELETE_DATA_BATCH_UPDATE_NUM);
        listList.forEach(list ->
                cuMemberSettleExtList.addAll(baseMapper.batchQueryCuMemberSettleParent(settleTableName, list)));
        return cuMemberSettleExtList;
    }

    @Override
    public List<CuMemberSettleExt> batchQueryCuMemberSettleParentForSpecial(String settleTableName, Set<Long> expandMemberSet) {
        List<CuMemberSettleExt> cuMemberSettleExtList = new ArrayList<>();
        List<Long> memberPkList = Arrays.asList(expandMemberSet.toArray(new Long[]{}));
        List<List<?>> listList = cuMemberBonusSettle.handleCutList(memberPkList, MagicNumberConstants.DELETE_DATA_BATCH_UPDATE_NUM);
        listList.forEach(list ->
                cuMemberSettleExtList.addAll(baseMapper.batchQueryCuMemberSettleParentForSpecial(settleTableName, list)));
        return cuMemberSettleExtList;
    }

    @Override
    public void updateCuMemberExpandSettle(String settleTableName, Map<Long, CuMemberSettleExt> cuMemberTreeMap) {
        List<List<?>> treeList = setUpdCuMemberTreeLists(cuMemberTreeMap);
        treeList.forEach(list -> baseMapper.updateCuMemberExpandSettle(settleTableName, list));
    }

    private List<List<?>> setUpdCuMemberTreeLists(Map<Long, CuMemberSettleExt> cuMemberTreeMap) {
        List<CuMemberSettleExt> cuMemberTreeList = new ArrayList<>();
        cuMemberTreeMap.forEach((key, value) -> cuMemberTreeList.add(value));
        return cuMemberBonusSettle.handleCutList(cuMemberTreeList);
    }

    @Override
    public void truncateCuMemberTreeTable(String tableName) {
        baseMapper.truncateCuMemberTreeTable(tableName);
    }

    @Override
    public void createCuMemberTreeDayOnlyIndex(String tableName) {
        baseMapper.createCuMemberTreeDayOnlyIndex(tableName);
    }

    @Override
    public void createCuMemberTreeParentIndex(String tableName) {
        baseMapper.createCuMemberTreeParentIndex(tableName);
    }

    @Override
    public void createCuMemberTreePlaceIndex(String tableName) {
        baseMapper.createCuMemberTreePlaceIndex(tableName);
    }

}
