package com.hdkj.lt.mq.service.base.impl;

import com.hdkj.lt.base.enums.ScoreIndicatorEnum;
import com.hdkj.lt.base.exception.BusinessException;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultTransferScheme;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultTransferSchemeEvaluationIndex;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultTransferSchemeStrategyScore;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanTransferScheme;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanTransferSchemeEvaluationIndex;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanTransferSchemeStrategyScore;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanTransferStrategyConfigDetail;
import com.hdkj.lt.mq.service.base.FhzgSchemeScoreService;
import com.hdkj.lt.mq.service.fault.FaultTransferSchemeEvaluationIndexService;
import com.hdkj.lt.mq.service.fault.FhzgFaultTransferSchemeStrategyScoreService;
import com.hdkj.lt.mq.service.fault.impl.FaultTransferSchemeServiceImpl;
import com.hdkj.lt.mq.service.plan.FhzgPlanTransferSchemeStrategyScoreService;
import com.hdkj.lt.mq.service.plan.IPlanTransferStrategyConfigDetailService;
import com.hdkj.lt.mq.service.plan.PlanTransferSchemeEvaluationIndexService;
import com.hdkj.lt.mq.service.plan.impl.PlanTransferSchemeServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * @author rj
 * @date 2025/5/28 10:04
 * @description
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FhzgPlanSchemeScoreServiceImpl2 implements FhzgSchemeScoreService {

    private final PlanTransferSchemeServiceImpl planTransferSchemeServiceImpl;

    private final IPlanTransferStrategyConfigDetailService planTransferStrategyConfigDetailServiceImpl;

    private final PlanTransferSchemeEvaluationIndexService planTransferSchemeEvaluationIndexService;

    private final FhzgPlanTransferSchemeStrategyScoreService planTransferSchemeStrategyScoreService;

    private final FhzgFaultTransferSchemeStrategyScoreService faultTransferSchemeStrategyScoreService;

    private final FaultTransferSchemeEvaluationIndexService faultTransferSchemeEvaluationIndexService;

    private final FaultTransferSchemeServiceImpl faultTransferSchemeServiceImpl;


    @Override
    public void planScore(Long planId) {
        //保存计算评分所需指标数据
        List<FhzgPlanTransferSchemeEvaluationIndex> schemeEvaluationIndexList = planTransferSchemeEvaluationIndexService.saveSchemeEvaluationIndex(planId);
        //获取对应启用的指标评分规则（优先级）
        //计划停电
        List<FhzgPlanTransferStrategyConfigDetail> configDetailList = planTransferStrategyConfigDetailServiceImpl.getConfigDetailListByPlanType(0);
        if (configDetailList == null || configDetailList.isEmpty()) {
            log.error("方案评分异常-当前未配置评分策略");
            throw new BusinessException("方案评分异常-当前未配置评分策略");
        } else if (configDetailList.stream().anyMatch(k -> k.getIndicatorCode() == null)) {
            log.error("方案评分异常-当前配置的评分策略异常");
            throw new BusinessException("方案评分异常-当前配置的评分策略异常");
        }
        //计算评分
        List<FhzgPlanTransferScheme> scoreResult;
        try {
            scoreResult = processPlanScore(schemeEvaluationIndexList, configDetailList);
        } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
            log.error("计算得分时异常", e);
            throw new BusinessException("计算得分时异常");
        }
        //结果入库
        planTransferSchemeServiceImpl.updateBatchById(scoreResult);
        log.info("方案评分-总分评分保存成功：{}", scoreResult);
    }

    private List<FhzgPlanTransferScheme> processPlanScore(List<FhzgPlanTransferSchemeEvaluationIndex> schemeEvaluationIndexList, List<FhzgPlanTransferStrategyConfigDetail> configDetailList) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        HashMap<Long, Integer> scoreMap = new HashMap<>();

        int indicators = configDetailList.size();
        int maxScore = indicators * 10;
        int totalScore = 5 * indicators * (indicators + 1);
        HashMap<Long, FhzgPlanTransferSchemeStrategyScore> schemeStrategyScoreHashMap = new HashMap<>();
        for (FhzgPlanTransferStrategyConfigDetail fhzgPlanTransferStrategyConfigDetail : configDetailList) {
            String indicatorCode = fhzgPlanTransferStrategyConfigDetail.getIndicatorCode();
            sort(schemeEvaluationIndexList, indicatorCode);
            //保证null值被正常处理
            Object lastValue = fhzgPlanTransferStrategyConfigDetail;
            int currentRank = 0;
            for (FhzgPlanTransferSchemeEvaluationIndex schemeEvaluation : schemeEvaluationIndexList) {
                if (!Objects.equals(PropertyUtils.getProperty(schemeEvaluation, indicatorCode), lastValue)) {
                    currentRank++;
                }
                currentRank = getCurrentRank(schemeEvaluation, indicatorCode, currentRank, maxScore, indicators);
                int curScore = maxScore - currentRank * indicators;
                saveTheScore(schemeEvaluation, schemeStrategyScoreHashMap, indicatorCode, curScore);
                scoreMap.compute(schemeEvaluation.getSchemeId(), (k, v) -> v == null ? curScore : v + curScore);
                lastValue = PropertyUtils.getProperty(schemeEvaluation, indicatorCode);
            }
            maxScore -= 10;
            indicators--;
        }
        //保存单项分数
        List<FhzgPlanTransferSchemeStrategyScore> fhzgPlanTransferSchemeStrategyScoreList = new ArrayList<>();
        for (Long l : schemeStrategyScoreHashMap.keySet()) {
            FhzgPlanTransferSchemeStrategyScore fhzgPlanTransferSchemeStrategyScore = schemeStrategyScoreHashMap.get(l);
            fhzgPlanTransferSchemeStrategyScore.setSchemeId(l);
            fhzgPlanTransferSchemeStrategyScore.setStrategyId(configDetailList.get(0).getStrategyId());
            fhzgPlanTransferSchemeStrategyScoreList.add(fhzgPlanTransferSchemeStrategyScore);
        }
        planTransferSchemeStrategyScoreService.saveBatch(fhzgPlanTransferSchemeStrategyScoreList);
        log.info("方案评分-各项评分保存成功:{}", fhzgPlanTransferSchemeStrategyScoreList);

        List<FhzgPlanTransferScheme> result = new ArrayList<>();
        for (Long l : scoreMap.keySet()) {
            FhzgPlanTransferScheme fhzgPlanTransferScheme = new FhzgPlanTransferScheme();
            fhzgPlanTransferScheme.setId(l);
            fhzgPlanTransferScheme.setEvaluationScore(new BigDecimal(scoreMap.get(l)).divide(new BigDecimal(totalScore), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
            result.add(fhzgPlanTransferScheme);
        }
        return result;
    }

    private static void saveTheScore(FhzgPlanTransferSchemeEvaluationIndex schemeEvaluation, HashMap<Long, FhzgPlanTransferSchemeStrategyScore> schemeStrategyScoreHashMap, String indicatorCode, int curScore) {
        schemeStrategyScoreHashMap.compute(schemeEvaluation.getSchemeId(), (k, v) -> {
            if (v == null) {
                v = new FhzgPlanTransferSchemeStrategyScore();
                v.setEvaluationIndexId(schemeEvaluation.getId());
            }
            try {
                PropertyUtils.setProperty(v, indicatorCode, curScore);
            } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                throw new BusinessException("记录单项分数异常");
            }
            return v;
        });
    }

    private static int getCurrentRank(FhzgPlanTransferSchemeEvaluationIndex SchemeEvaluation, String indicatorCode, int currentRank, int maxScore, int indicators) {
        //处理特殊情况
        if (ScoreIndicatorEnum.LOSS_USERS.getIndicatorCode().equals(indicatorCode) && SchemeEvaluation.getLossUsers() != null && SchemeEvaluation.getLossUsers() == 0) {
            currentRank = 0;
        } else if (ScoreIndicatorEnum.OPPOSITE_LINE_MAX_LOAD_RATE.getIndicatorCode().equals(indicatorCode) && SchemeEvaluation.getOppositeLineMaxLoadRate() != null && SchemeEvaluation.getOppositeLineMaxLoadRate().compareTo(new BigDecimal("80.00")) >= 0) {
            //得分为0
            currentRank = maxScore / indicators;
        } else if (ScoreIndicatorEnum.SWITCH_OPERATION_TIMES.getIndicatorCode().equals(indicatorCode) && SchemeEvaluation.getSwitchOperationTimes() != null && SchemeEvaluation.getSwitchOperationTimes() <= 1) {
            currentRank = 0;
        }
        return currentRank;
    }

    private void sort(List<?> schemeEvaluationIndexList, String indicatorCode) {
        if (ScoreIndicatorEnum.LOSS_USERS.getIndicatorCode().equals(indicatorCode) ||
                ScoreIndicatorEnum.OPPOSITE_LINE_MAX_LOAD_RATE.getIndicatorCode().equals(indicatorCode) ||
                ScoreIndicatorEnum.NON_AUTO_SWITCH_OPERATION_TIMES.getIndicatorCode().equals(indicatorCode) ||
                ScoreIndicatorEnum.SWITCH_OPERATION_TIMES.getIndicatorCode().equals(indicatorCode) ||
                ScoreIndicatorEnum.DISTRIBUTION_TRANSFORMER_VOLTAGE.getIndicatorCode().equals(indicatorCode) ||
                ScoreIndicatorEnum.LOSS_POWER_SECURED_USERS.getIndicatorCode().equals(indicatorCode)
        ) {
            schemeEvaluationIndexList.sort(new BeanComparator<>(indicatorCode, new NullSafeComparator()));
        } else if (ScoreIndicatorEnum.TRANSFER_LOAD_RATIO.getIndicatorCode().equals(indicatorCode)) {
            schemeEvaluationIndexList.sort(new BeanComparator<>(indicatorCode, new NullSafeReverseComparator()));
        } else {
            throw new BusinessException("未知指标属性:" + indicatorCode);
        }
    }

    private static class NullSafeComparator implements Comparator<Object> {
        @Override
        public int compare(Object o1, Object o2) {
            if (o1 == o2) return 0;
            if (o1 == null) return 1;
            if (o2 == null) return -1;
            return ((Comparable) o1).compareTo(o2);
        }
    }

    private static class NullSafeReverseComparator implements Comparator<Object> {
        @Override
        public int compare(Object o1, Object o2) {
            if (o1 == o2) return 0;
            if (o1 == null) return 1;
            if (o2 == null) return -1;
            return ((Comparable) o2).compareTo(o1);
        }
    }

    @Override
    public void repairScore(Long planId) {
        //保存计算评分所需指标数据
        List<FaultTransferSchemeEvaluationIndex> schemeEvaluationIndexList = faultTransferSchemeEvaluationIndexService.saveSchemeEvaluationIndex(planId);
        //获取对应启用的指标评分规则（优先级）
        List<FhzgPlanTransferStrategyConfigDetail> configDetailList = planTransferStrategyConfigDetailServiceImpl.getConfigDetailListByPlanType(1);
        if (configDetailList == null || configDetailList.isEmpty()) {
            log.error("方案评分异常-当前未配置评分策略");
            throw new BusinessException("方案评分异常-当前未配置评分策略");
        } else if (configDetailList.stream().anyMatch(k -> k.getIndicatorCode() == null)) {
            log.error("方案评分异常-当前配置的评分策略异常");
            throw new BusinessException("方案评分异常-当前配置的评分策略异常");
        }

        //计算评分
        List<FaultTransferScheme> scoreResult;
        try {
            scoreResult = processFaultScore(schemeEvaluationIndexList, configDetailList);
        } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
            log.error("计算得分时异常", e);
            throw new BusinessException("计算得分时异常");
        }

        //结果入库
        faultTransferSchemeServiceImpl.updateBatchById(scoreResult);
        log.info("方案评分-总分评分保存成功：{}", scoreResult);

    }

    private List<FaultTransferScheme> processFaultScore(List<FaultTransferSchemeEvaluationIndex> schemeEvaluationIndexList, List<FhzgPlanTransferStrategyConfigDetail> configDetailList) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        HashMap<Long, Integer> scoreMap = new HashMap<>();

        int indicators = configDetailList.size();
        int maxScore = indicators * 10;
        int totalScore = 5 * indicators * (indicators + 1);
        HashMap<Long, FaultTransferSchemeStrategyScore> schemeStrategyScoreHashMap = new HashMap<>();
        for (FhzgPlanTransferStrategyConfigDetail fhzgPlanTransferStrategyConfigDetail : configDetailList) {
            String indicatorCode = fhzgPlanTransferStrategyConfigDetail.getIndicatorCode();
            sort(schemeEvaluationIndexList, indicatorCode);
            //保证null值被正常处理
            Object lastValue = fhzgPlanTransferStrategyConfigDetail;
            int currentRank = 0;
            for (FaultTransferSchemeEvaluationIndex schemeEvaluation : schemeEvaluationIndexList) {
                if (!Objects.equals(PropertyUtils.getProperty(schemeEvaluation, indicatorCode), lastValue)) {
                    currentRank++;
                }
                currentRank = getCurrentRank(schemeEvaluation, indicatorCode, currentRank, maxScore, indicators);
                int curScore = maxScore - currentRank * indicators;
                saveTheScore(schemeEvaluation, schemeStrategyScoreHashMap, indicatorCode, curScore);
                scoreMap.compute(schemeEvaluation.getSchemeId(), (k, v) -> v == null ? curScore : v + curScore);
                lastValue = PropertyUtils.getProperty(schemeEvaluation, indicatorCode);
            }
            maxScore -= 10;
            indicators--;
        }
        //保存单项分数
        List<FaultTransferSchemeStrategyScore> faultTransferSchemeStrategyScores = new ArrayList<>();
        for (Long l : schemeStrategyScoreHashMap.keySet()) {
            FaultTransferSchemeStrategyScore fhzgPlanTransferSchemeStrategyScore = schemeStrategyScoreHashMap.get(l);
            fhzgPlanTransferSchemeStrategyScore.setSchemeId(l);
            fhzgPlanTransferSchemeStrategyScore.setStrategyId(configDetailList.get(0).getStrategyId());
            faultTransferSchemeStrategyScores.add(fhzgPlanTransferSchemeStrategyScore);
        }
        faultTransferSchemeStrategyScoreService.saveBatch(faultTransferSchemeStrategyScores);
        log.info("方案评分-各项评分保存成功:{}", faultTransferSchemeStrategyScores);

        List<FaultTransferScheme> result = new ArrayList<>();
        for (Long l : scoreMap.keySet()) {
            FaultTransferScheme faultTransferScheme = new FaultTransferScheme();
            faultTransferScheme.setId(l);
            faultTransferScheme.setEvaluationScore(new BigDecimal(scoreMap.get(l)).divide(new BigDecimal(totalScore), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
            result.add(faultTransferScheme);
        }
        return result;
    }

    private static int getCurrentRank(FaultTransferSchemeEvaluationIndex SchemeEvaluation, String indicatorCode, int currentRank, int maxScore, int indicators) {
        //处理特殊情况
        if (ScoreIndicatorEnum.LOSS_USERS.getIndicatorCode().equals(indicatorCode) && SchemeEvaluation.getLossUsers() != null && SchemeEvaluation.getLossUsers() == 0) {
            currentRank = 0;
        } else if (ScoreIndicatorEnum.OPPOSITE_LINE_MAX_LOAD_RATE.getIndicatorCode().equals(indicatorCode) && SchemeEvaluation.getOppositeLineMaxLoadRate() != null && SchemeEvaluation.getOppositeLineMaxLoadRate().compareTo(new BigDecimal("80.00")) >= 0) {
            //得分为0
            currentRank = maxScore / indicators;
        } else if (ScoreIndicatorEnum.SWITCH_OPERATION_TIMES.getIndicatorCode().equals(indicatorCode) && SchemeEvaluation.getSwitchOperationTimes() != null && SchemeEvaluation.getSwitchOperationTimes() <= 1) {
            currentRank = 0;
        }
        return currentRank;
    }


    private static void saveTheScore(FaultTransferSchemeEvaluationIndex schemeEvaluation, HashMap<Long, FaultTransferSchemeStrategyScore> schemeStrategyScoreHashMap, String indicatorCode, int curScore) {
        schemeStrategyScoreHashMap.compute(schemeEvaluation.getSchemeId(), (k, v) -> {
            if (v == null) {
                v = new FaultTransferSchemeStrategyScore();
                v.setEvaluationIndexId(schemeEvaluation.getId());
            }
            try {
                PropertyUtils.setProperty(v, indicatorCode, curScore);
            } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                throw new BusinessException("记录单项分数异常");
            }
            return v;
        });
    }
}
