package com.yd.csf.api.handler;

import com.xxl.job.core.handler.annotation.XxlJob;
import com.yd.common.enums.CommonEnum;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.csf.feign.enums.OprSourceEnum;
import com.yd.csf.service.dto.GradeQueryParam;
import com.yd.csf.service.model.AgentAccumulatedFyc;
import com.yd.csf.service.model.AgentAccumulatedFycLog;
import com.yd.csf.service.model.EvaluateRank;
import com.yd.csf.service.model.MemberGradeConfig;
import com.yd.csf.service.service.IAgentAccumulatedFycLogService;
import com.yd.csf.service.service.IAgentAccumulatedFycService;
import com.yd.csf.service.service.IEvaluateRankService;
import com.yd.csf.service.service.IMemberGradeConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 评定职级定时任务处理器 - XXL-Job定时任务执行器
 * 使用@XxlJob注解方式
 */
@Component
@Slf4j
public class EvaluateRankJobHandler {

    @Resource
    private IAgentAccumulatedFycService iAgentAccumulatedFycService;
    @Resource
    private IAgentAccumulatedFycLogService iAgentAccumulatedFycLogService;
    @Resource
    private IEvaluateRankService iEvaluateRankService;
    @Resource
    private IMemberGradeConfigService iMemberGradeConfigService;

    /**
     * 评定职级定时任务，每月1号0点执行（XXL-Job任务执行入口方法）
     */
    @XxlJob("evaluateRankJobHandler")
    public void execute() throws Exception {
        //查询积分总表记录（所有转介人积分总表记录）
        List<AgentAccumulatedFyc> allList = iAgentAccumulatedFycService.queryAll();
        if (CollectionUtils.isEmpty(allList)) {
            return;
        }
        //过滤出转介人唯一业务ID列表
        List<String> agentIdList = allList.stream()
                .map(AgentAccumulatedFyc::getAgentId)
                .collect(Collectors.toList());
        // 构建批量查询参数列表（业务员ID和晋升职级累计积分入参）
        List<GradeQueryParam> paramList = allList.stream()
                .map(fyc -> new GradeQueryParam(fyc.getAgentId(), fyc.getPromotion()))
                .collect(Collectors.toList());
        // 最新评定记录（用于获取上一次的 afterGrade / afterPromotion）
        Map<String, EvaluateRank> latestRankMap = iEvaluateRankService.getLatestByBrokerBizIds(agentIdList);
        //查询每个业务员已有的评定记录数量
        Map<String, Long> rankCountMap = iEvaluateRankService.countGroupByBrokerBizId(agentIdList);
        // 批量查询各业务员对应的等级配置
        Map<String, MemberGradeConfig> gradeConfigMap = iMemberGradeConfigService.batchGetGradeByPromotion(paramList);
        List<EvaluateRank> toSaveList = new ArrayList<>();
        for (AgentAccumulatedFyc fyc : allList) {
            String agentId = fyc.getAgentId();
            Long existingCount = rankCountMap.getOrDefault(agentId, 0L);
            //最新评定记录
            EvaluateRank latestRank = latestRankMap.get(agentId);
            //查询当前业务员的晋升职级累计积分对应的职级对象
            MemberGradeConfig gradeConfig = gradeConfigMap.get(agentId);
            EvaluateRank evaluateRank = new EvaluateRank();
            evaluateRank.setBrokerBizId(fyc.getAgentId());
            evaluateRank.setBrokerName(fyc.getAgentName());
            //评定职级表唯一业务ID
            evaluateRank.setEvaluateRankBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_EVALUATE_RANK.getCode()));
            if (existingCount == 0) {
                //首次评级：评定前职级和评定前累计已生效积分 = 初始化职级和已生效积分
                //评定前职级 = 初始化等级
                evaluateRank.setBeforeGrade(fyc.getInitGrade());
                //评定前晋升职级累计积分 = 初始化已生效积分
                evaluateRank.setBeforePromotion(fyc.getInitEffect());
                //评定后职级 = 晋升职级累计积分对应职级
                evaluateRank.setAfterGrade(gradeConfig != null ? gradeConfig.getGradeCode() : "G1001");
                //评定后晋升职级累计积分
                evaluateRank.setAfterPromotion(fyc.getPromotion());
                //查询评定结果
                evaluateRank.setResult(getResult(evaluateRank.getBeforeGrade(),evaluateRank.getAfterGrade()));
                //评定来源 1-每月1号0点定时评级
                evaluateRank.setSource(1);
            } else {
                // 非首次评级
                //评定前职级 = 当前业务员评定职级记录最新一条记录的评定后的职级
                evaluateRank.setBeforeGrade(latestRank.getAfterGrade());
                //评定前晋升职级累计积分 = 当前业务员评定职级记录最新一条记录的评定后的晋升职级累计积分
                evaluateRank.setBeforePromotion(latestRank.getAfterPromotion());
                //评定后职级 = 积分总表的晋升职级累计积分对应职级
                evaluateRank.setAfterGrade(gradeConfig != null ? gradeConfig.getGradeCode() : "G1001");
                //评定后晋升职级累计积分 = 积分总表的晋升职级累计积分
                evaluateRank.setAfterPromotion(fyc.getPromotion());
                //查询评定结果
                evaluateRank.setResult(getResult(evaluateRank.getBeforeGrade(),evaluateRank.getAfterGrade()));
                //评定来源 1-每月1号0点定时评级
                evaluateRank.setSource(1);
            }
            //当前等级
            fyc.setCurrentGradeCode(evaluateRank.getAfterGrade());
            toSaveList.add(evaluateRank);
        }

        // 批量保存评定职级记录
        if (CollectionUtils.isNotEmpty(toSaveList)) {
            iEvaluateRankService.saveBatch(toSaveList);
        }

        //更新积分总表的当前等级
        iAgentAccumulatedFycService.saveOrUpdateBatch(allList);

        //新增积分总表操作日志表
        List<AgentAccumulatedFycLog> addLogList = allList.stream().map(dto -> {
            AgentAccumulatedFycLog log = new AgentAccumulatedFycLog();
            BeanUtils.copyProperties(dto,log);
            log.setId(null);
            log.setFycBizId(dto.getFycBizId());
            log.setFycLogBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_AGENT_ACCUMULATED_FYC_LOG.getCode()));
            //操作来源
            log.setSourceType(OprSourceEnum.CALM_TASK_EVALUATE_RANK.getItemValue());
            return log;
        }).collect(Collectors.toList());
        iAgentAccumulatedFycLogService.saveOrUpdateBatch(addLogList);
    }

    /**
     * 查询评定结果（1-平级 2-升级 3-降级）
     * @param beforeGrade 评定前职级
     * @param afterGrade 评定后职级
     * @return 1-平级 2-升级 3-降级
     */
    public Integer getResult(String beforeGrade, String afterGrade) {
        // 若任一参数为空，视为无法比较，默认返回平级（可根据业务调整）
        if (beforeGrade == null || afterGrade == null) {
            return 1;
        }

        // 提取职级代码中的数字部分，例如 "G1001" -> 1001
        int beforeLevel = extractLevel(beforeGrade);
        int afterLevel = extractLevel(afterGrade);

        if (beforeLevel == afterLevel) {
            return 1; // 平级
        } else if (beforeLevel < afterLevel) {
            return 2; // 升级
        } else {
            return 3; // 降级
        }
    }

    /**
     * 从职级代码中提取等级数值
     * @param gradeCode 职级代码，如 "G1001"
     * @return 数字部分，若格式异常则返回 0
     */
    private int extractLevel(String gradeCode) {
        if (gradeCode == null || gradeCode.length() < 2) {
            return 0;
        }
        try {
            // 去掉首字母 'G'，解析剩余数字
            return Integer.parseInt(gradeCode.substring(1));
        } catch (NumberFormatException e) {
            log.warn("Invalid grade code format: {}", gradeCode, e);
            return 0;
        }
    }

}