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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.bonus.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.bonus.achieve.service.ICuMemberTreeService;
import com.hzs.bonus.detail.service.ICuMemberAwardsService;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.MemberFieldConstants;
import com.hzs.common.core.constant.SaOrderFieldConstants;
import com.hzs.common.core.constant.SystemFieldConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.member.detail.CuMemberAwards;
import com.hzs.common.domain.member.ext.CuMemberSettleExt;
import com.hzs.common.domain.system.config.BdAwards;
import com.hzs.bonus.base.service.ICuMemberService;
import com.hzs.bonus.detail.mapper.CuMemberAwardsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 会员信息-奖衔升级记录 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2022-08-31
 */
@Service
public class CuMemberAwardsServiceImpl extends ServiceImpl<CuMemberAwardsMapper, CuMemberAwards> implements ICuMemberAwardsService {

    private ICuMemberTreeService cuMemberTreeService;

    private ICuMemberService cuMemberService;

    private ICuMemberSettlePeriodService cuMemberSettlePeriodService;

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

    @Autowired
    public void setCuMemberService(ICuMemberService cuMemberService) {
        this.cuMemberService = cuMemberService;
    }

    @Autowired
    public void setCuMemberTreeService(ICuMemberTreeService cuMemberTreeService) {
        this.cuMemberTreeService = cuMemberTreeService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void calculateCuMemberAwards(String setDate, Map<String, BdAwards> countryAwardsMap, String settleTableName, String settleTableNameDetail) {
        // 查询结算日当天奖衔发生过变动的会员，本期
        Date settleDate = DateUtils.parseStringToDate(setDate);
        Integer period = cuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(setDate).getPkId();
        //删除当天奖衔升级记录，自动升级的
        // 更新奖衔，回退奖衔
        List<CuMemberAwards> cuMemberAwards = queryCuMemberAwardsByPeriod(period);
        cuMemberTreeService.updateBackCuMemberSettleAward(settleTableName, period);
        cuMemberService.updateBackCuMemberAward(cuMemberAwards, period);
        // 回退业绩表奖衔
        baseMapper.deleteCuMemberAwards(period);
        while (true) {
            List<CuMemberSettleExt> cuMemberSettleExtList = cuMemberTreeService.queryCuMemberSettleEnoughAwardAchieve(settleTableName, settleTableNameDetail);
            if (!calculateAwards(countryAwardsMap, settleTableName, settleTableNameDetail, period, cuMemberSettleExtList)) {
                break;
            }
        }
    }

    private Boolean calculateAwards(Map<String, BdAwards> countryAwardsMap, String settleTableName,  String settleTableNameDetail, Integer period, List<CuMemberSettleExt> cuMemberSettleExtList) {
        if (cuMemberSettleExtList.size() > 0) {
            List<CuMemberSettleExt> enoughAwardsMemberList = new ArrayList<>();
            List<CuMemberSettleExt> placeAwardsMemberList = new ArrayList<>();
            List<CuMemberSettleExt> bloodAwardsMemberList = new ArrayList<>();
            // 用于记录原来的奖衔
            Map<Long, CuMemberSettleExt> originalCuMemberSettleMap = new HashMap<>(ComputeUtil.mapInitCapacity(cuMemberSettleExtList.size()));
            cuMemberSettleExtList.forEach(cuMemberSettleExt -> {
                BdAwards bdAwards = getBdAwards(countryAwardsMap, originalCuMemberSettleMap, cuMemberSettleExt);
                // 验证关系
                if (null == bdAwards.getRelationType()) {
                    enoughAwardsMemberList.add(cuMemberSettleExt);
                } else if (ERelationType.BLOOD_KINSHIP_CHECK.getValue() == bdAwards.getRelationType()) {
                    bloodAwardsMemberList.add(cuMemberSettleExt);
                } else if (ERelationType.PLACE_CHECK.getValue() == bdAwards.getRelationType()) {
                    placeAwardsMemberList.add(cuMemberSettleExt);
                } else {
                    enoughAwardsMemberList.add(cuMemberSettleExt);
                }
            });
            // 当天奖衔发生过变动的人, 只要发生过变动，就要进行更新 降奖衔或者不变
            // 更新奖衔，更新会员表，更新奖衔变动记录表
            // 只满足业绩的
            List<CuMemberAwards> cuMemberAwardsList = new ArrayList<>();
            List<CuMemberAwards> memberAwardsList = updateAwardsRecord(countryAwardsMap, enoughAwardsMemberList, originalCuMemberSettleMap, period, settleTableName);
            if (memberAwardsList != null && memberAwardsList.size() > 0) {
                cuMemberAwardsList.addAll(memberAwardsList);
            }
            // 需要验证安置的
            if (placeAwardsMemberList.size() > 0) {
                List<CuMemberSettleExt> updateAwardsMemberList = new ArrayList<>();
                placeAwardsMemberList.forEach(cuMemberSettleExt -> {
                    BdAwards bdAwards = getBdAwards(countryAwardsMap, originalCuMemberSettleMap, cuMemberSettleExt);
                    // 验证安置 验证左右区是否存在满足等级的 考核
                    // 先验证左区
                    if (validateCuMemberPlaceRelation(settleTableName, bdAwards, cuMemberSettleExt.getPkMember())) {
                        updateAwardsMemberList.add(cuMemberSettleExt);
                    }
                });
                List<CuMemberAwards> awardsList = updateAwardsRecord(countryAwardsMap, updateAwardsMemberList, originalCuMemberSettleMap, period, settleTableName);
                if (updateAwardsMemberList.size() > 0) {
                    enoughAwardsMemberList.addAll(updateAwardsMemberList);
                }
                if (awardsList != null && awardsList.size() > 0) {
                    cuMemberAwardsList.addAll(awardsList);
                }
            }
            // 需要验证血缘的
            if (bloodAwardsMemberList.size() > 0) {
                List<CuMemberSettleExt> updateAwardsMemberList = new ArrayList<>();
                bloodAwardsMemberList.forEach(cuMemberSettleExt -> {
                    BdAwards bdAwards = getBdAwards(countryAwardsMap, originalCuMemberSettleMap, cuMemberSettleExt);
                    // 验证血缘
                    // 1 先验证安置，验证左右区是否存在满足等级的 考核
                    // 2 在验证血缘，验证满足等级的会员是否在他的血缘线上
                    if (validateBloodRelation(settleTableName, cuMemberSettleExt, bdAwards)) {
                        updateAwardsMemberList.add(cuMemberSettleExt);
                    }
                });
                List<CuMemberAwards> awardsList = updateAwardsRecord(countryAwardsMap, updateAwardsMemberList, originalCuMemberSettleMap, period, settleTableName);
                if (updateAwardsMemberList.size() > 0) {
                    enoughAwardsMemberList.addAll(updateAwardsMemberList);
                }
                if (awardsList != null && awardsList.size() > 0) {
                    cuMemberAwardsList.addAll(awardsList);
                }
            }
            // 插入记录
            if (cuMemberAwardsList.size() > 0) {
                baseMapper.saveBatchCuMemberAwards(cuMemberAwardsList);
                baseMapper.insertTmpCuMemberAward(cuMemberAwardsList);
                // 将变动值插入临时表中
                // 更新会员表
                cuMemberService.updateCuMemberByTemp(enoughAwardsMemberList);
                // 更新结算网体表(月表、日表)
                // 根据结算日期获得所有需要更新的周期
                cuMemberTreeService.updateCuMemberSettleByPeriod(period);
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    @Override
    public void deleteCuMemberAwards(Long pkOrder, Long pkApprove, Date currentDateTime) {
        UpdateWrapper<CuMemberAwards> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(SystemFieldConstants.DEL_FLAG, EYesNo.NO.getIntValue());
        updateWrapper.set(SystemFieldConstants.PK_MODIFIED, pkApprove);
        updateWrapper.set(SystemFieldConstants.MODIFIED_TIME, currentDateTime);
        updateWrapper.eq(SaOrderFieldConstants.PK_ORDER, pkOrder);
        update(updateWrapper);
    }


    private BdAwards getBdAwards(Map<String, BdAwards> countryAwardsMap, Map<Long, CuMemberSettleExt> originalCuMemberSettleMap, CuMemberSettleExt cuMemberSettleExt) {
        originalCuMemberSettleMap.put(cuMemberSettleExt.getPkMember(), cuMemberSettleExt);
        String key = cuMemberSettleExt.getPkSettleCountry().toString() + cuMemberSettleExt.getPkAwards().toString();
        return countryAwardsMap.get(key);
    }

    /**
     * 更新奖衔记录
     *
     * @param oldEnoughwardsMemberList  满足业绩
     * @param originalCuMemberSettleMap 原来的map
     * @param period                    期间
     * @return: void
     * @Author: sui q
     * @Date: 2023/2/23 17:44
     */
    private List<CuMemberAwards> updateAwardsRecord(Map<String, BdAwards> countryAwardsMap, List<CuMemberSettleExt> oldEnoughwardsMemberList, Map<Long, CuMemberSettleExt> originalCuMemberSettleMap,
                                                    Integer period, String settleTableName) {
        if (oldEnoughwardsMemberList.size() == 0) {
            return null;
        }
        List<CuMemberSettleExt> enoughAwardsMemberList = new ArrayList<>();
        List<CuMemberSettleExt> bloodEnoughAwardsMemberList = new ArrayList<>();
        oldEnoughwardsMemberList.forEach(cuMemberSettleExt -> {
            BdAwards bdAwards = getBdAwards(countryAwardsMap, originalCuMemberSettleMap, cuMemberSettleExt);
            // 验证血缘业绩
            if (ComputeUtil.compareValue(BigDecimal.ZERO, bdAwards.getBloCommunityCheck())) {
                enoughAwardsMemberList.add(cuMemberSettleExt);
            } else {
                bloodEnoughAwardsMemberList.add(cuMemberSettleExt);
            }
        });
        // 验证血缘业绩
        if (bloodEnoughAwardsMemberList.size() > 0) {
            List<CuMemberSettleExt> cuMemberSettleExtList = cuMemberTreeService.queryCuMemberSettleBloodEnoughAwardAchieve(settleTableName, bloodEnoughAwardsMemberList);
            if (cuMemberSettleExtList.size() > 0) {
                enoughAwardsMemberList.addAll(cuMemberSettleExtList);
            }
        }
        List<CuMemberAwards> cuMemberAwardsList = new ArrayList<>();
        // 记录要入库的，为了验证是否首次晋升
        enoughAwardsMemberList.forEach(enoughAwardsMember -> getCuMemberAwards(originalCuMemberSettleMap, period, cuMemberAwardsList, enoughAwardsMember));
        // 更新奖衔记录变动
        // 增加奖衔记录表
        // 更新升奖衔的会员，插入升衔记录
        return cuMemberAwardsList;

    }

    private void getCuMemberAwards(Map<Long, CuMemberSettleExt> originalCuMemberSettleMap, Integer period, List<CuMemberAwards> cuMemberAwardsList, CuMemberSettleExt enoughAwardsMember) {
        CuMemberAwards cuMemberAwards = CuMemberAwards.builder()
                .pkMember(enoughAwardsMember.getPkMember())
                .period(period)
                .upType(EUpgradeType.AUTO_UPGRADE.getValue())
                // 原等级
                .oldLevel(originalCuMemberSettleMap.get(enoughAwardsMember.getPkMember()).getPkOriAwards())
                .newLevel(enoughAwardsMember.getPkAwards())
                // 默认不免考
                .purchaseStatus(EYesNo.NO.getIntValue())
                .build();
        cuMemberAwards.setPkCreator(MagicNumberConstants.PK_ADMIN);
        cuMemberAwards.setPkCountry(enoughAwardsMember.getPkSettleCountry());
        cuMemberAwardsList.add(cuMemberAwards);
    }

    /**
     * @param period             期间
     * @param changeAwardsList   降低奖衔的人
     * @param cuMemberAwardsList 所有变动记录的数据
     * @Description: 更新降衔的会员，把升衔记录删除
     * @return: void
     * @Author: sui q
     * @Date: 2022/11/5 16:23
     */
    private void reduceCuMemberAwards(List<CuMemberAwards> changeAwardsList, Integer period, List<CuMemberAwards> cuMemberAwardsList) {
        // 验证是否有降奖衔的，降奖衔的也要更新
        if (changeAwardsList.size() > 0) {
            // 更新奖衔表，将奖衔升级记录修改为删除状态
            QueryWrapper<CuMemberAwards> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(MemberFieldConstants.PERIOD, period);
            baseMapper.updateBatchCuMemberAwards(changeAwardsList, period);
            // 根据 changeAwardsList 查找到这群人的历史奖衔升级记录
            List<CuMemberAwards> hisCuMemberAwardsList = baseMapper.queryLastCuMemberAwards(changeAwardsList);
            Map<Long, CuMemberAwards> cuMemberAwardsMap = new HashMap<>();
            hisCuMemberAwardsList.forEach(cuMemberAwards -> cuMemberAwardsMap.put(cuMemberAwards.getPkMember(), cuMemberAwards));
            // 用于更新网体，将原有奖衔还原
            changeAwardsList.forEach(cuMemberAwards -> {
                if (cuMemberAwardsMap.containsKey(cuMemberAwards.getPkMember())) {
                    // 原有奖衔
                    cuMemberAwards.setNewLevel(cuMemberAwardsMap.get(cuMemberAwards.getPkMember()).getNewLevel());
                } else {
                    // 没有值的变为会员
                    cuMemberAwards.setNewLevel(EAwards.MEMBER.getValue());
                }
            });
            cuMemberAwardsList.addAll(changeAwardsList);
        }
    }

    /**
     * @param period 奖金期
     * @Description: 查询某一期变动的奖衔
     * @return: List<CuMemberAwards>
     * @Author: sui q
     * @Date: 2022/11/5 14:21
     */
    private List<CuMemberAwards> queryCuMemberAwardsByPeriod(Integer period) {
        QueryWrapper<CuMemberAwards> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(MemberFieldConstants.PERIOD, period);
        queryWrapper.eq(MemberFieldConstants.UP_TYPE, EUpgradeType.AUTO_UPGRADE.getValue());
        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 验证血缘关系
     *
     * @param settleTableName   结算表
     * @param cuMemberSettleExt 会员结算表
     * @param bdAwards          等级
     */
    private Boolean validateBloodRelation(String settleTableName, CuMemberSettleExt cuMemberSettleExt, BdAwards bdAwards) {
        List<Integer> list = cuMemberTreeService.queryCuMemberSettlePlaceDeptUnderUmbrella(settleTableName, cuMemberSettleExt.getPkMember());
        // 存在3个区满足血缘奖衔，且满足血缘
        int awardsNum = 0;
        for (int i = 0; i < list.size(); i++) {
            int deptDept = list.get(i);
            if(cuMemberTreeService.queryCuMemberSettleBloodUnderUmbrella(settleTableName, bdAwards.getPkCheckAwardsLeft(), deptDept, cuMemberSettleExt.getPkMember())){
                awardsNum +=1;
            }
        }
        if(awardsNum >= bdAwards.getAwardsNum()){
            return true;
        }
        return false;
    }

    /**
     * 验证左右区安置关系
     *
     * @param settleTableName 结算表
     * @param bdAwards        等级
     * @param pkMember        会员
     */
    private Boolean validateCuMemberPlaceRelation(String settleTableName, BdAwards bdAwards, Long pkMember) {
        // 验证左区
        if (cuMemberTreeService.queryCuMemberSettlePlaceUnderUmbrella(settleTableName, bdAwards.getPkCheckAwardsLeft(), EPlaceDept.LEFT_DEPT.getValue(), pkMember)) {
            // 在验证右区
            return cuMemberTreeService.queryCuMemberSettlePlaceUnderUmbrella(settleTableName, bdAwards.getPkCheckAwardsRight(), EPlaceDept.RIGHT_DEPT.getValue(), pkMember);
        }
        return false;
    }
}
