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

import cn.hutool.core.collection.CollectionUtil;
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.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.TableNameConstants;
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.CuMemberSettleCountryExt;
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.bonus.achieve.mapper.CuMemberTreeMapper;
import com.hzs.bonus.achieve.param.MemberAchieveParam;
import com.hzs.bonus.achieve.param.MemberParentCountParam;
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
    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);
        }
        number = baseMapper.queryExistOrderTableCount(settleTableName);
        if (number == null || number <= 0) {
            // 初始化日表数据，将cu_member数据插入到最新的日表记录表
            baseMapper.insertCuMemberSettleByMember(settleTableName);
        }
        // 安置业绩明细表
        settleTableName = TableNameConstants.CU_MEMBER_SETTLE_D + period;
        number = baseMapper.queryExistOracleTable(settleTableName);
        if (number == null || number <= 0) {
            baseMapper.createCuMemberSettleDetailTable(settleTableName);
            baseMapper.createCuMemberTreeDeptOnlyIndex(settleTableName);
        }
        number = baseMapper.queryExistOrderTableCount(settleTableName);
        if (number == null || number <= 0) {
            String yesterday = DateUtils.beforeDateStr(1, ChronoUnit.DAYS, DateUtils.YYYY_MM_DD, date);
            Integer yesterdayPeriod = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(yesterday).getPkId();
            String yesSettleTableName = TableNameConstants.CU_MEMBER_SETTLE_D + yesterdayPeriod;
            // 初始化日表数据，将cu_member数据插入到最新的日表记录表
            baseMapper.insertCuMemberSettleDetailByMember(settleTableName, yesSettleTableName);
        }
        // 各国业绩明细表
        settleTableName = TableNameConstants.CU_MEMBER_SETTLE_C + period;
        number = baseMapper.queryExistOracleTable(settleTableName);
        if (number == null || number <= 0) {
            baseMapper.createCuMemberSettleCountryTable(settleTableName);
            baseMapper.createCuMemberTreeCountryOnlyIndex(settleTableName);
        }
        // 创建月表记录表
//        createMonthTreeTableName(date);
        // 创建月表业绩记录表
//        cuMemberAchieveService.createCuMemberAchieve(date);
    }

    @Override
    public void initCuMemberTreeTable(String yesterdaySettleTableName, String currentSettleTableName, String yesterdayTableNameDetail, String currentTableNameDetail,
                                      Integer period, Integer endPeriod, String sourceCountryTable, String targetCountryTable) {
        // 更新所有值为0
        cuMemberAchieveService.updateCuMemberSettleInitAchieve(currentSettleTableName, currentTableNameDetail, targetCountryTable);
        // 初始化结算日的数据，将日期-1的数据作为当天的数据
        cuMemberAchieveService.updateCuMemberSettleAchieveByBeforeDay(yesterdaySettleTableName, currentSettleTableName, yesterdayTableNameDetail, currentTableNameDetail, endPeriod,
                sourceCountryTable, targetCountryTable);
        // 还原复销剩余次数 复销剩余奖金
        cuMemberAchieveService.mergeBackCuMemberReSaleDate(currentSettleTableName, period);
    }

    @Override
    public void updateCuMemberSettle(Map<Long, MemberAchieveParam> cuMemberAchieveHashMap, String currentSettleTableName, String settleTableNameDetail) {
        cuMemberAchieveService.updateCuMemberAchieveEveryDay(cuMemberAchieveHashMap, currentSettleTableName, settleTableNameDetail);
    }

    @Override
    public void updateCuMemberBackSettle(Map<Long, MemberAchieveParam> cuMemberAchieveHashMap, String currentSettleTableName, String settleTableNameDetail) {
        cuMemberAchieveService.updateCuMemberBackOldAchieveEveryDay(cuMemberAchieveHashMap, currentSettleTableName, settleTableNameDetail);
    }

    @Override
    public void updateCuMemberTreeByCancelOrder(List<SaOrderExt> revokeRegSaOrderList, List<SaOrderExt> revokeUpdSaOrderList, String settleDate, String settleTableName) {
        // 更新网体，将撤单的注册订单，会员数据修改为死点
        if (revokeRegSaOrderList.size() > 0) {
            List<List<?>> revokeSaOrderList = cuMemberBonusSettle.handleCutList(revokeRegSaOrderList);
            revokeSaOrderList.forEach(saOrderList -> {
                baseMapper.updateCuMemberTreeByCancelOrder(saOrderList, settleTableName);
            });
        }
        // 更新网体，将撤销的升级订单，会员等级降级
        if (revokeRegSaOrderList.size() > 0) {
            Date tomorrow = DateUtils.afterDate(1, ChronoUnit.DAYS, DateUtils.parseStringToDate(settleDate));
            List<List<?>> revokeSaOrderList = cuMemberBonusSettle.handleCutList(revokeRegSaOrderList);
            revokeSaOrderList.forEach(saOrderList ->
                    baseMapper.updateCuMemberTreeGradeByCancelOrder(saOrderList, tomorrow, settleTableName));
        }
    }

    @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, String settleTableNameDetail) {
        return baseMapper.queryCuMemberSettleEnoughAwardAchieve(settleTableName, settleTableNameDetail);
    }

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

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

    @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 List<Integer> queryCuMemberSettlePlaceDeptUnderUmbrella(String settleTableName, Long pkMember) {
        return baseMapper.queryCuMemberSettlePlaceDeptUnderUmbrella(settleTableName, pkMember);
    }

    @Override
    public void updateCuMemberSettleByPeriod(Integer currentPeriod) {
//        monthSet.forEach(month -> {
//            String updateTableName = TableNameConstants.CU_MEMBER_TREE + month;
//            baseMapper.updateCuMemberSettleMonthByPeriod(updateTableName, currentPeriod);
//        });
        String updateTableName = TableNameConstants.CU_MEMBER_SETTLE + currentPeriod;
        baseMapper.updateCuMemberSettleByPeriod(updateTableName);
    }

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

    @Override
    public List<CuMemberSettleExt> queryMemberSettleTenParentBySaOrder(String settleTableName, List<SaOrderExt> saOrderExtList) {
        List<CuMemberSettleExt> cuMemberSettleExtList = new ArrayList<>();
        if (saOrderExtList.size() > 0) {
            List<List<?>> listList = cuMemberBonusSettle.handleCutList(saOrderExtList);
            listList.forEach(list ->
                    cuMemberSettleExtList.addAll(baseMapper.batchQueryMemberSettleParentBySaOrder(settleTableName, list)));
        }
        return cuMemberSettleExtList;
    }

    private List<CuMemberSettleExt> getCuMemberSettleExtList(String settleTableName, String settleTableNameDetail, 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, settleTableNameDetail, list)));
        }
        return cuMemberSettleExtList;
    }

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

    @Override
    public Map<Long, List<CuMemberSettleExt>> batchQueryCuMemberSettlePlaceParent(String settleTableName, String settleTableNameDetail, List<SaOrderExt> firPurchaseOrderList) {
        // 查询出所有父级安置人
        List<List<?>> listList = cuMemberBonusSettle.handleCutList(firPurchaseOrderList, MagicNumberConstants.DELETE_DATA_BATCH_UPDATE_NUM);
        List<CuMemberSettleExt> cuMemberSettleExtList = new ArrayList<>();
        listList.forEach(list ->
                cuMemberSettleExtList.addAll(baseMapper.batchQueryCuMemberSettlePlaceParent(settleTableName, settleTableNameDetail, list)));
        return getLongListMap(firPurchaseOrderList, cuMemberSettleExtList);
    }

    private static Map<Long, List<CuMemberSettleExt>> getLongListMap(List<?> firPurchaseOrderList, List<CuMemberSettleExt> cuMemberSettleExtList) {
        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, String settleTableNameDetail, 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.batchQueryCuMemberSettleParent(settleTableName, settleTableNameDetail, list)));
        return cuMemberSettleExtList;
    }

    @Override
    public List<CuMemberSettleExt> batchCuMemberSettlePlaceParent(String settleTableName, String settleTableNameDetail, 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.batchCuMemberSettlePlaceParent(settleTableName, settleTableNameDetail, list)));
        return cuMemberSettleExtList;
    }

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

    @Override
    public void updateCuMemberSettle(String settleTableName, String settleTableNameDetail, String settleTableCountry, Map<Long, CuMemberSettleExt> cuMemberTreeMap) {
        List<CuMemberSettleExt> cuMemberTreeList = getCuMemberSettleExtList(cuMemberTreeMap);
        if (CollectionUtil.isEmpty(cuMemberTreeList)) {
            return;
        }
        List<List<?>> treeList = setUpdCuMemberTreeLists(cuMemberTreeList);
        treeList.forEach(list -> {
            baseMapper.updateCuMemberSettle(settleTableName, list);
        });
        List<CuMemberSettleDetailExt> cuMemberSettleDetailExtList = new ArrayList<>();
        List<CuMemberSettleCountryExt> cuMemberSettleCountryExtList = new ArrayList<>();
        for (CuMemberSettleExt cuMemberSettleExt : cuMemberTreeList) {
            if (CollectionUtil.isNotEmpty(cuMemberSettleExt.getCuMemberSettleDetailExtList())) {
                for (CuMemberSettleDetailExt cuMemberSettleDetailExt : cuMemberSettleExt.getCuMemberSettleDetailExtList()) {
                    if (cuMemberSettleDetailExt.getPkMember() == null) {
                        cuMemberSettleDetailExt.setPkMember(cuMemberSettleExt.getPkMember());
                    }
                }
                cuMemberSettleDetailExtList.addAll(cuMemberSettleExt.getCuMemberSettleDetailExtList());
            }
            if (CollectionUtil.isNotEmpty(cuMemberSettleExt.getCuMemberSettleCountryExtList())) {
                for (CuMemberSettleCountryExt cuMemberSettleCountryExt : cuMemberSettleExt.getCuMemberSettleCountryExtList()) {
                    if (cuMemberSettleCountryExt.getPkMember() == null) {
                        cuMemberSettleCountryExt.setPkMember(cuMemberSettleExt.getPkMember());
                    }
                }
                cuMemberSettleCountryExtList.addAll(cuMemberSettleExt.getCuMemberSettleCountryExtList());
            }
        }
        if (cuMemberSettleDetailExtList.size() > 0) {
            List<List<?>> detailList = cuMemberBonusSettle.handleCutList(cuMemberSettleDetailExtList);
            detailList.forEach(list -> {
                baseMapper.updateCuMemberSettleDetail(settleTableNameDetail, list);
            });
        }
        if (cuMemberSettleCountryExtList.size() > 0) {
            List<List<?>> detailList = cuMemberBonusSettle.handleCutList(cuMemberSettleCountryExtList);
            detailList.forEach(list -> {
                baseMapper.updateCuMemberSettleCountry(settleTableCountry, list);
            });
        }
    }

    @Override
    public List<MemberParentCountParam> queryByMemberParentSumPv(String settleTableName, List<Long> memberIds) {
        return baseMapper.queryByMemberParentSumPv(settleTableName, memberIds);
    }

    private List<List<?>> setUpdCuMemberTreeLists(List<CuMemberSettleExt> cuMemberTreeList) {
        return cuMemberBonusSettle.handleCutList(cuMemberTreeList);
    }

    private static List<CuMemberSettleExt> getCuMemberSettleExtList(Map<Long, CuMemberSettleExt> cuMemberTreeMap) {
        List<CuMemberSettleExt> cuMemberTreeList = new ArrayList<>();
        cuMemberTreeMap.forEach((key, value) -> cuMemberTreeList.add(value));
        return 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);
    }

}
