package nckd.jxccl.hr.psms.helper;

import kd.bos.algo.Algo;
import kd.bos.algo.AlgoContext;
import kd.bos.algo.DataSet;
import kd.bos.algo.Row;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.psms.ScoreItemEnum;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.QueryFieldBuilder;
import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
import nckd.jxccl.hr.psms.business.AnnualAdjustmentService;
import nckd.jxccl.hr.psms.common.ContributionConstant;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 年度贡献积分辅助类
 * @author W.Y.C
 * @date 2025/10/26 13:34
 * @version 1.0
 */
public class ContributionHelper {

    protected final static Log logger = LogFactory.getLog(ContributionHelper.class);

    /**
     * 根据人员获取积分项目有效分数
     * 依据人员某年度已获得的积分（含在途单据）+积分配置的最高分计算出可获得的分数
     *
     * @param scoreItemValidScoreList 待计算列表（人员不能重复）
     * @param year 年份
     * @param excludeBillId 排除的单据ID（计算有效分数不含当前单据），可为空
     * @return: ScoreItemValidScore
     * @author W.Y.C
     * @date: 2025/10/26 13:38
     */
    public static List<ScoreItemValidScore> getScoreItemValidScore(List<ScoreItemValidScore> scoreItemValidScoreList, Date year, Long excludeBillId) {
        if (scoreItemValidScoreList == null || scoreItemValidScoreList.isEmpty()) {
            return scoreItemValidScoreList;
        }

        //获取积分项目分数配置
        Map<String, BigDecimal> scoreConfMap = getScoreConf();
        //统计人员各项目已累计积分
        Long[] personIdArray = scoreItemValidScoreList.stream()
                .map(ScoreItemValidScore::getPersonId)
                .filter(Objects::nonNull)
                .distinct()
                .toArray(Long[]::new);

        List<ScoreItemValidScore> scoreItemAccumulateScoreList = getScoreItemAccumulateScore(personIdArray, year, excludeBillId);

        //按人员分组已累计积分数据，提高查找效率
        Map<Long, List<ScoreItemValidScore>> personAccumulateScoreMap = scoreItemAccumulateScoreList.stream()
                .collect(Collectors.groupingBy(ScoreItemValidScore::getPersonId));

        for (ScoreItemValidScore scoreItemValidScore : scoreItemValidScoreList) {
            if (scoreItemValidScore == null) {
                continue;
            }

            Long personId = scoreItemValidScore.getPersonId();
            Long scoreItemId = scoreItemValidScore.getScoreItemId();
            Long scoreItemSubId = scoreItemValidScore.getScoreItemSubId();
            Long scoreItemRankId = scoreItemValidScore.getScoreItemRankId();

            //获取该人员的累计积分数据
            List<ScoreItemValidScore> personAccumulateScores = personAccumulateScoreMap.getOrDefault(personId, new ArrayList<>());

            //计算积分项目和具体项目累计分数
            BigDecimal scoreItemSumScore = BigDecimal.ZERO;
            BigDecimal scoreItemSubSumScore = BigDecimal.ZERO;
            BigDecimal scoreItemRankSumScore = BigDecimal.ZERO;

            for (ScoreItemValidScore accumulateScore : personAccumulateScores) {
                Long tempScoreItemId = accumulateScore.getScoreItemId();
                Long tempScoreItemSubId = accumulateScore.getScoreItemSubId();
                Long tempScoreItemRankId = accumulateScore.getScoreItemRankId();

                if (Objects.equals(tempScoreItemId, scoreItemId)) {
                    scoreItemSumScore = scoreItemSumScore.add(accumulateScore.getSumScore());
                    if (Objects.equals(tempScoreItemSubId, scoreItemSubId)) {
                        scoreItemSubSumScore = scoreItemSubSumScore.add(accumulateScore.getSumScore());
                    }
                    // 添加名次维度判断
                    if (Objects.equals(tempScoreItemRankId, scoreItemRankId)) {
                        scoreItemRankSumScore = scoreItemRankSumScore.add(accumulateScore.getSumScore());
                    }
                }
            }

            //根据配置决定使用哪种累计分数
            BigDecimal sumScore = determineSumScore(scoreConfMap, scoreItemId, scoreItemSubId, scoreItemRankId,
                    scoreItemSumScore, scoreItemSubSumScore, scoreItemRankSumScore);

            BigDecimal validScore = calculateAvailableScore(scoreConfMap, scoreItemId, scoreItemSubId, scoreItemRankId, sumScore);
            scoreItemValidScore.setValidScore(validScore);
            scoreItemValidScore.setSumScore(sumScore);
        }
        return scoreItemValidScoreList;
    }

    /**
     * 根据人员、年度、积分项目、具体积分项目获取有效分数
     * 依据人员某年度已获得的积分（含在途单据）+积分配置的最高分计算出可获得的分数
     *
     * @param scoreItemValidScore 待计算积分信息
     * @param year                年份
     * @param excludeBillId       排除的单据ID（计算有效分数不含当前单据），可为空
     * @author W.Y.C
     * @date: 2025/10/26 13:38
     */
    public static void getScoreItemValidScore(ScoreItemValidScore scoreItemValidScore, Date year, Long excludeBillId) {
        if (scoreItemValidScore == null) {
            return;
        }

        //复用批量处理方法
        List<ScoreItemValidScore> inputList = new ArrayList<>();
        inputList.add(scoreItemValidScore);
        List<ScoreItemValidScore> result = getScoreItemValidScore(inputList, year, excludeBillId);
    }


    /**
     * 根据人员和年度获取积分项目已累计分数
     * @param personIds 人员
     * @param year 年度
     * @param excludeBillId 排除的单据ID（计算有效分数不含当前单据），可为空
     * @param approvedOnly 是否只查询已审批通过的记录
     * @return: List<ScoreItemValidScore> 积分项目已累计分数
     * @author W.Y.C
     * @date: 2025/10/26 16:20
     */
    public static List<ScoreItemValidScore> getScoreItemAccumulateScore(Long[] personIds, Date year, Long excludeBillId, boolean approvedOnly) {
        if (personIds == null || personIds.length == 0) {
            return new ArrayList<>();
        }

        LocalDateTime yearStarDateTime = DateUtil.beginOfYear(DateUtil.toLocalDateTime(year));
        QueryFieldBuilder scoreItemConfFieldBuilder = QueryFieldBuilder.create()
                .add(ContributionConstant.NCKD_YEAR)
                .addIdNumberName(ContributionConstant.NCKD_SCOREITEM)
                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMSUB)
                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMRANK) // 添加积分项目名次字段
                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON},FormConstant.ID_KEY)
                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, ContributionConstant.NCKD_SCORE, ContributionConstant.NCKD_ORISCORE);

        //构建查询条件
        QFilter filter;
        if (approvedOnly) {
            //只查询"已审批通过"年度贡献积分
            filter = QFilterCommonHelper.getBillStatusFilter();
        } else {
            //查询非"审批不通过"、"已废弃"年度贡献积分
            filter = new QFilter(FormConstant.BILL_STATUS_KEY, QCP.not_in, new String[]{"E", "F"});
        }

        filter.and(ContributionConstant.NCKD_YEAR,QCP.large_equals,DateUtil.beginOfDay(yearStarDateTime))
                .and(ContributionConstant.NCKD_YEAR,QCP.less_equals, DateUtil.endOfDay(yearStarDateTime))
                .and(String.join( ".",FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON),QCP.in,personIds);

        if(excludeBillId != null && excludeBillId > 0){
            filter.and(FormConstant.ID_KEY,QCP.not_equals,excludeBillId);
        }

        List<ScoreItemValidScore> scoreItemValidScoreList = new ArrayList<>();
        try(AlgoContext context = Algo.newContext()) {
            DataSet dateSet = QueryServiceHelper.queryDataSet(ContributionHelper.class.getName(),
                    ContributionConstant.CONTRIBBILL_ENTITYID,
                    scoreItemConfFieldBuilder.buildSelect(),
                    new QFilter[]{filter}, null, 5000);

            DataSet sumDateSet = dateSet.copy()
                    // 按人员、积分项目、积分项目子项、积分项目名次进行分组
                    .groupBy(new String[]{String.join(".", ContributionConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON, FormConstant.ID_KEY),
                            String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY),
                            String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY),
                            String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.ID_KEY),
                            String.join(".", ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.ID_KEY)
                    })
                    .sum(String.join(".", ContributionConstant.NCKD_ENTRYENTITY, FormConstant.NCKD_SCORE),"sumScore").finish();

            while (sumDateSet.hasNext()) {
                Row row = sumDateSet.next();
                Long personId = row.getLong(String.join(".", ContributionConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON, FormConstant.ID_KEY));
                Long scoreItemId = row.getLong(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY));
                String scoreItemNumber = row.getString(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY));
                Long scoreItemSubId = row.getLong(String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.ID_KEY));
                Long scoreItemRankId = row.getLong(String.join(".", ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.ID_KEY)); // 获取名次ID
                //已获得的累计积分
                BigDecimal sumScore = row.getBigDecimal("sumScore");
                ScoreItemValidScore scoreItemValidScore = new ScoreItemValidScore(personId, scoreItemId,scoreItemNumber, scoreItemSubId, scoreItemRankId, sumScore);
                scoreItemValidScoreList.add(scoreItemValidScore);
            }
        }
        return scoreItemValidScoreList;
    }


    /**
     * 根据人员和年度获取积分项目已累计分数
     * @param personIds 人员
     * @param year 年度
     * @return: List<ScoreItemValidScore> 积分项目已累计分数
     * @author W.Y.C
     * @date: 2025/10/26 16:20
     */
    public static List<ScoreItemValidScore> sumScoreItemAccumulateScore(Long[] personIds, Date year) {
        if (personIds == null || personIds.length == 0) {
            return new ArrayList<>();
        }

        LocalDateTime yearStarDateTime = DateUtil.beginOfYear(DateUtil.toLocalDateTime(year));
        QueryFieldBuilder scoreItemConfFieldBuilder = QueryFieldBuilder.create()
                .add(ContributionConstant.NCKD_YEAR)
                .addIdNumberName(ContributionConstant.NCKD_SCOREITEM)
                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMSUB)
                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMRANK) // 添加积分项目名次字段
                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON},FormConstant.ID_KEY)
                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, ContributionConstant.NCKD_SCORE, ContributionConstant.NCKD_ORISCORE);

        //只查询"已审批通过"年度贡献积分
        QFilter filter = QFilterCommonHelper.getBillStatusFilter()
                .and(ContributionConstant.NCKD_YEAR,QCP.large_equals,DateUtil.beginOfDay(yearStarDateTime))
                .and(ContributionConstant.NCKD_YEAR,QCP.less_equals, DateUtil.endOfDay(yearStarDateTime))
                .and(String.join( ".",FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON),QCP.in,personIds);

        List<ScoreItemValidScore> scoreItemValidScoreList = new ArrayList<>();
        try(AlgoContext context = Algo.newContext()) {
            DataSet dateSet = QueryServiceHelper.queryDataSet(ContributionHelper.class.getName(),
                    ContributionConstant.CONTRIBBILL_ENTITYID,
                    scoreItemConfFieldBuilder.buildSelect(),
                    new QFilter[]{filter}, null, 5000);

            DataSet sumDateSet = dateSet.copy()
                    // 按人员、积分项目、积分项目子项、积分项目名次进行分组
                    .groupBy(new String[]{String.join(".", ContributionConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON, FormConstant.ID_KEY),
                            String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY),
                            String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY)
                    })
                    .sum(String.join(".", ContributionConstant.NCKD_ENTRYENTITY, FormConstant.NCKD_SCORE),"sumScore").finish();

            while (sumDateSet.hasNext()) {
                Row row = sumDateSet.next();
                Long personId = row.getLong(String.join(".", ContributionConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON, FormConstant.ID_KEY));
                Long scoreItemId = row.getLong(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY));
                String scoreItemNumber = row.getString(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY));
                //已获得的累计积分
                BigDecimal sumScore = row.getBigDecimal("sumScore");
                ScoreItemValidScore scoreItemValidScore = new ScoreItemValidScore(personId, scoreItemId,scoreItemNumber, null, null, sumScore);
                scoreItemValidScoreList.add(scoreItemValidScore);
            }
        }
        return scoreItemValidScoreList;
    }




    /**
     * 根据人员和年度获取积分项目已累计分数（包含所有未废弃记录）
     * @param personIds 人员
     * @param year 年度
     * @param excludeBillId 排除的单据ID（计算有效分数不含当前单据），可为空
     * @return: List<ScoreItemValidScore> 积分项目已累计分数
     * @author W.Y.C
     * @date: 2025/10/26 16:20
     */
    public static List<ScoreItemValidScore> getScoreItemAccumulateScore(Long[] personIds, Date year, Long excludeBillId) {
        return getScoreItemAccumulateScore(personIds, year, excludeBillId, false);
    }

    /**
     * 根据人员和年度获取已审批通过的积分项目累计分数
     * @param personIds 人员
     * @param year 年度
     * @return: List<ScoreItemValidScore> 积分项目已累计分数（仅包含已审批通过的记录）
     * @author W.Y.C
     * @date: 2025/10/26 16:20
     */
    public static List<ScoreItemValidScore> getApprovedScoreItemAccumulateScore(Long[] personIds, Date year) {
        return getScoreItemAccumulateScore(personIds, year, null, true);
    }


    /**
     * 计算可获得的有效分数
     * 基于累计总分和限制分数，计算还可以获得多少分数（不超过限制）
     *
     * @param scoreConfMap 分数配置映射表，key为配置ID，value为限分数值
     * @param scoreItemId 积分项目ID
     * @param scoreItemSubId 具体积分项目ID
     * @param scoreItemRankId 积分项目名次ID
     * @param accumulatedScore 已累计总分
     * @return 可获得的有效分数
     *         如果没有任何限制返回null
     *         如果已超过限制返回BigDecimal.ZERO
     *         否则返回剩余可加分数
     * @author W.Y.C
     * @date: 2025/10/26 16:53
     */
    private static BigDecimal calculateAvailableScore(Map<String, BigDecimal> scoreConfMap, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId, BigDecimal accumulatedScore) {
        // 积分项目限分 - 如果没有找到则不限分
        String scoreItemKey = scoreItemId + "";
        BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemKey);

        // 具体积分项目限分 - 如果没有找到则不限分
        String scoreItemSubKey = null;
        BigDecimal scoreItemSubMaxScore = null;
        if (scoreItemSubId != null && scoreItemSubId > 0) {
            scoreItemSubKey = scoreItemId + "-" + scoreItemSubId;
            scoreItemSubMaxScore = scoreConfMap.get(scoreItemSubKey);
        }

        // 积分项目名次限分 - 如果没有找到则不限分
        String scoreItemRankKey = null;
        BigDecimal scoreItemRankMaxScore = null;
        if (scoreItemRankId != null && scoreItemRankId > 0) {
            scoreItemRankKey = scoreItemId + "-" + scoreItemSubId + "-" + scoreItemRankId;
            scoreItemRankMaxScore = scoreConfMap.get(scoreItemRankKey);
        }

        // 处理累计分数的空值
        BigDecimal actualAccumulatedScore = accumulatedScore == null ? BigDecimal.ZERO : accumulatedScore;

        // 计算实际的最大限制
        BigDecimal actualMaxScore = null;

        // 检查积分项目名次限分是否存在且大于0（最高优先级）
        if (scoreItemRankMaxScore != null && scoreItemRankMaxScore.compareTo(BigDecimal.ZERO) > 0) {
            actualMaxScore = scoreItemRankMaxScore;
        }

        // 检查具体积分项目限分是否存在且大于0
        if (scoreItemSubMaxScore != null && scoreItemSubMaxScore.compareTo(BigDecimal.ZERO) > 0) {
            if (actualMaxScore == null) {
                actualMaxScore = scoreItemSubMaxScore;
            } else {
                // 多重限制，取较小值
                actualMaxScore = actualMaxScore.min(scoreItemSubMaxScore);
            }
        }

        // 检查积分项目限分是否存在且大于0
        if (scoreItemMaxScore != null && scoreItemMaxScore.compareTo(BigDecimal.ZERO) > 0) {
            if (actualMaxScore == null) {
                actualMaxScore = scoreItemMaxScore;
            } else {
                // 多重限制，取较小值
                actualMaxScore = actualMaxScore.min(scoreItemMaxScore);
            }
        }

        // 如果没有限制，返回null
        if (actualMaxScore == null) {
            return null;
        }

        // 计算可获得的有效分数
        BigDecimal availableScore;
        if (actualAccumulatedScore.compareTo(actualMaxScore) >= 0) {
            // 已经超过限制，不能再获得分数
            availableScore = BigDecimal.ZERO;
        } else {
            // 计算剩余可加分数
            availableScore = actualMaxScore.subtract(actualAccumulatedScore);
        }

        return availableScore;
    }

    public static void main(String[] args) {
        List<ScoreItemValidScore> list = new ArrayList<>();
        list.add(new ScoreItemValidScore(1L, 11L, "1", 111L, 1111L, BigDecimal.valueOf(6)));
        list.add(new ScoreItemValidScore(1L, 11L, "1", 121L, null, BigDecimal.valueOf(10)));
        list.add(new ScoreItemValidScore(1L, 11L, "1", 131L, null, BigDecimal.valueOf(10)));
        list.add(new ScoreItemValidScore(1L, 11L, "1", 141L, null, BigDecimal.valueOf(20)));
        List<ScoreItemValidScore> scoreItemValidScores = calculateMaxAllowedScore(list);
        System.out.println();
    }

    /**
     * 计算最多可得的分数
     * 根据累计积分和分数配置映射表，如果超过配置的限制分数则返回限制分最大分数，
     * 计算每个积分大项在考虑三重限制条件下的最大可获得分数：
     * 1. 名次限制：每个积分项目名次可能有分数上限（最高优先级）
     * 2. 子项限制：每个具体积分项目子项可能有分数上限
     * 3. 大项限制：整个积分大项可能有总分上限
     *
     * @param scoreItemValidScoreList 某个人员所有积分项目的累计积分（personId、scoreItemId、scoreItemSubId、scoreItemRankId、sumScore有值）
     * @return 最多可得的分数列表（按大项维度聚合）
     * @author W.Y.C
     * @date: 2025/10/27
     */
    public static List<ScoreItemValidScore> calculateMaxAllowedScore(List<ScoreItemValidScore> scoreItemValidScoreList) {

        //获取积分限分配置
        Map<String, BigDecimal> scoreConfMap = ContributionHelper.getScoreConf();
        /*Map<String, BigDecimal> scoreConfMap = Maps.newConcurrentMap();
         scoreConfMap.put("11-111-1111",new BigDecimal(2));
         scoreConfMap.put("11-121",new BigDecimal(5));
         scoreConfMap.put("11",new BigDecimal(20));*/

        List<ScoreItemValidScore> result = new ArrayList<>();

        // 按大类分组
        Map<Long, List<ScoreItemValidScore>> groupedByScoreItemId = scoreItemValidScoreList.stream()
                .collect(Collectors.groupingBy(ScoreItemValidScore::getScoreItemId));

        for (Map.Entry<Long, List<ScoreItemValidScore>> entry : groupedByScoreItemId.entrySet()) {
            Long scoreItemId = entry.getKey();
            List<ScoreItemValidScore> valueList = entry.getValue();

            // 获取大项限制分数
            BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemId + "");

            // 按具体项目分组
            Map<Long, List<ScoreItemValidScore>> groupedBySubItemId = valueList.stream()
                    .collect(Collectors.groupingBy(ScoreItemValidScore::getScoreItemSubId));

            BigDecimal totalAllowedScore = BigDecimal.ZERO;
            BigDecimal actualTotalScore = BigDecimal.ZERO;

            // 遍历每个具体项目
            for (Map.Entry<Long, List<ScoreItemValidScore>> subEntry : groupedBySubItemId.entrySet()) {
                Long subItemId = subEntry.getKey();
                List<ScoreItemValidScore> subItemList = subEntry.getValue();

                // 获取子项限制分数
                BigDecimal scoreItemSubMaxScore = null;
                if (subItemId != null && subItemId > 0) {
                    scoreItemSubMaxScore = scoreConfMap.get(scoreItemId + "-" + subItemId);
                }

                // 按名次分组
                Map<Long, BigDecimal> rankSumMap = new HashMap<>();
                for (ScoreItemValidScore item : subItemList) {
                    Long rankItemId = item.getScoreItemRankId();
                    BigDecimal score = item.getSumScore() == null ? BigDecimal.ZERO : item.getSumScore();
                    rankSumMap.merge(rankItemId, score, BigDecimal::add);
                    actualTotalScore = actualTotalScore.add(score);
                }

                BigDecimal subItemAllowedScore = BigDecimal.ZERO;

                // 处理每个名次的分数限制
                for (Map.Entry<Long, BigDecimal> rankEntry : rankSumMap.entrySet()) {
                    Long rankItemId = rankEntry.getKey();
                    BigDecimal rankSumScore = rankEntry.getValue();

                    // 获取名次限制分数
                    BigDecimal scoreItemRankMaxScore = null;
                    if (rankItemId != null && rankItemId > 0) {
                        scoreItemRankMaxScore = scoreConfMap.get(scoreItemId + "-" + subItemId + "-" + rankItemId);
                    }

                    // 名次限制后的分数
                    BigDecimal allowedRankScore = rankSumScore;
                    if (scoreItemRankMaxScore != null && scoreItemRankMaxScore.compareTo(BigDecimal.ZERO) > 0) {
                        allowedRankScore = rankSumScore.min(scoreItemRankMaxScore);
                    }

                    subItemAllowedScore = subItemAllowedScore.add(allowedRankScore);
                }

                // 应用子项限制（如果设置了子项限制）
                if (scoreItemSubMaxScore != null && scoreItemSubMaxScore.compareTo(BigDecimal.ZERO) > 0) {
                    subItemAllowedScore = subItemAllowedScore.min(scoreItemSubMaxScore);
                }

                totalAllowedScore = totalAllowedScore.add(subItemAllowedScore);
            }

            // 应用大项限制（如果设置了大项限制）
            if (scoreItemMaxScore != null && scoreItemMaxScore.compareTo(BigDecimal.ZERO) > 0) {
                totalAllowedScore = totalAllowedScore.min(scoreItemMaxScore);
            }

            // 创建结果对象，只包含scoreItemId和validScore
            ScoreItemValidScore resultItem = new ScoreItemValidScore(null, scoreItemId, null, null);
            String scoreItemNumber = null;
            if (!valueList.isEmpty() && valueList.get(0) != null) {
                scoreItemNumber = valueList.get(0).getScoreItemNumber();
            }
            resultItem.setScoreItemNumber(scoreItemNumber);
            resultItem.setValidScore(totalAllowedScore);
            resultItem.setSumScore(actualTotalScore);
            result.add(resultItem);
        }

        return result;
    }


    /**
     * 计算最多可得的分数
     * 根据累计积分和分数配置映射表，如果超过配置的限制分数则返回限制分最大分数，
     * 计算每个积分大项在考虑三重限制条件下的最大可获得分数：
     * 1. 名次限制：每个积分项目名次可能有分数上限（最高优先级）
     * 2. 子项限制：每个具体积分项目子项可能有分数上限
     * 3. 大项限制：整个积分大项可能有总分上限
     *
     * @param scoreItemValidScoreList 某个人员所有积分项目的累计积分（personId、scoreItemId、scoreItemSubId、scoreItemRankId、sumScore有值）
     * @return 最多可得的分数列表（按大项维度聚合）
     * @author W.Y.C
     * @date: 2025/10/27
     */
    public static List<ScoreItemValidScore> calculateMaxAllowedScore1(List<ScoreItemValidScore> scoreItemValidScoreList) {

        //获取积分限分配置
        Map<String, BigDecimal> scoreConfMap = ContributionHelper.getScoreConf();
        /*Map<String, BigDecimal> scoreConfMap = Maps.newConcurrentMap();
         scoreConfMap.put("11-111-1111",new BigDecimal(2));
         scoreConfMap.put("11-121",new BigDecimal(5));
         scoreConfMap.put("11",new BigDecimal(20));*/

        List<ScoreItemValidScore> result = new ArrayList<>();

        // 按大类分组
        Map<Long, List<ScoreItemValidScore>> groupedByScoreItemId = scoreItemValidScoreList.stream()
                .collect(Collectors.groupingBy(ScoreItemValidScore::getScoreItemId));

        for (Map.Entry<Long, List<ScoreItemValidScore>> entry : groupedByScoreItemId.entrySet()) {
            Long scoreItemId = entry.getKey();
            List<ScoreItemValidScore> valueList = entry.getValue();

            // 获取大项限制分数
            BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemId + "");

            BigDecimal totalAllowedScore = BigDecimal.ZERO;
            for (ScoreItemValidScore item : valueList) {
                BigDecimal score = item.getSumScore() == null ? BigDecimal.ZERO : item.getSumScore();
                // 应用大项限制（如果设置了大项限制）
                if (scoreItemMaxScore != null && scoreItemMaxScore.compareTo(BigDecimal.ZERO) >= 0) {
                    totalAllowedScore = scoreItemMaxScore.min(score);
                }else{
                    //没有配置限制，则直接使用录入的分数
                    ScoreItemEnum scoreItemEnum = ScoreItemEnum.getByCode(item.getScoreItemNumber());
                    logger.warn("积分【{}】没有配置积分项限制，使用实际录入的分数：{}",scoreItemEnum.getName() ,score);
                    totalAllowedScore = score;
                }
                // 创建结果对象，只包含scoreItemId和validScore
                ScoreItemValidScore resultItem = new ScoreItemValidScore(item.getPersonId(), scoreItemId, null, null);
                resultItem.setScoreItemNumber(item.getScoreItemNumber());
                resultItem.setValidScore(totalAllowedScore);
                resultItem.setSumScore(score);
                result.add(resultItem);
            }
        }
        return result;
    }

    /**
     * 决定使用哪种累计分数
     * @param scoreConfMap 分数配置映射
     * @param scoreItemId 积分项目ID
     * @param scoreItemSumScore 积分项目累计分数
     * @param scoreItemSubSumScore 积分项目具体项目累计分数
     * @param scoreItemRankSumScore 积分项目名次累计分数
     * @return 应该使用的累计分数
     */
    private static BigDecimal determineSumScore(Map<String, BigDecimal> scoreConfMap, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId,
                                                BigDecimal scoreItemSumScore, BigDecimal scoreItemSubSumScore,
                                                BigDecimal scoreItemRankSumScore) {
        // 按照优先级判断使用哪个维度的累计分数
        // 优先级：名次 > 子项 > 大类

        // 如果设置了积分项目名次限制，使用名次的累计积分
        if (scoreItemRankSumScore != null && scoreItemRankSumScore.compareTo(BigDecimal.ZERO) > 0) {
            String key = scoreItemId + "-" + scoreItemSubId + "-" + scoreItemRankId;
            if (scoreConfMap.containsKey(key)) {
                return scoreItemRankSumScore;
            }
        }

        // 如果设置了积分项目子项限制，使用子项的累计积分
        if (scoreItemSubSumScore != null && scoreItemSubSumScore.compareTo(BigDecimal.ZERO) > 0) {
            String key = scoreItemId + "-" + scoreItemSubId;
            if (scoreConfMap.containsKey(key)) {
                return scoreItemSubSumScore;
            }
        }

        // 默认使用大类的累计积分
        return scoreItemSumScore;
    }

    public static Map<String, BigDecimal> getScoreConf() {
        return getScoreConf(null);
    }

    public static Map<String, BigDecimal> getScoreConfByPersonMaxScore(QFilter otherFilter) {
        return getScoreConf(otherFilter,2);
    }
    public static Map<String, BigDecimal> getScoreConf(QFilter otherFilter) {
        return getScoreConf(otherFilter,1);
    }

    /**
     * 获取积分配置
     * @return: java.util.Map<java.lang.String, java.math.BigDecimal>；key：根据配置的完整程度生成不同格式的字符串，
     *          仅配置积分项目时为"scoreItemId"，
     *          配置积分项目和具体积分项目时为"scoreItemId-scoreItemSubId"，
     *          配置积分项目、具体积分项目和积分项目名次时为"scoreItemId-scoreItemSubId-scoreItemRankId"，
     *          value为积分项目对应的最大分数
     * @author W.Y.C
     * @date: 2025/10/26 13:38
     */
    public static Map<String, BigDecimal> getScoreConf(QFilter otherFilter,Integer type) {
        //查询积分项目分数配置
        QueryFieldBuilder scoreItemConfFieldBuilder = QueryFieldBuilder.create()
                .addIdNumberName(FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEM)
                .addIdNumberName(FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMSUB)
                .addIdNumberName(FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMRANK)
                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, ContributionConstant.NCKD_MAXSCORE,ContributionConstant.NCKD_PERSONMAXSCORE);
        QFilter filter = QFilterCommonHelper.getEnableFilter()
                .and(QFilterCommonHelper.getValidDateFilter(FormConstant.NCKD_STARTDATE,FormConstant.NCKD_ENDDATE));
        if(otherFilter != null){
            filter = filter.and(otherFilter);
        }

        DynamicObjectCollection scoreItemConfQuery = QueryServiceHelper.query(ContributionConstant.SCOREITEMCONF_ENTITYID,
                scoreItemConfFieldBuilder.buildSelect(),
                new QFilter[]{filter});

        //scoreMap：key为积分配置维度ID，value为积分项目对应的最大分数
        //优先级顺序：NCKD_SCOREITEMRANK > NCKD_SCOREITEMSUB > NCKD_SCOREITEM
        Map<String, BigDecimal> scoreMap = scoreItemConfQuery.stream().collect(Collectors.toMap(
                item -> {
                    long scoreItemRankId = item.getLong(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.ID_KEY));
                    long scoreItemSubId = item.getLong(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.ID_KEY));
                    long scoreItemId = item.getLong(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY));

                    // 按优先级顺序确定key值
                    if (scoreItemRankId > 0) {
                        // 优先使用NCKD_SCOREITEMRANK作为key
                        return scoreItemId+"-"+scoreItemSubId+"-"+scoreItemRankId;
                    } else if (scoreItemSubId > 0) {
                        // 当NCKD_SCOREITEMRANK为空时，使用NCKD_SCOREITEMSUB作为key
                        return scoreItemId+"-"+scoreItemSubId;
                    } else {
                        // 当NCKD_SCOREITEMRANK和NCKD_SCOREITEMSUB都为空时，使用NCKD_SCOREITEM作为key
                        return scoreItemId+"";
                    }
                },
                item -> {
                    if(type == 1){
                        return item.getBigDecimal(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_MAXSCORE));
                    }else{
                        return item.getBigDecimal(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSONMAXSCORE));
                    }
                },
                //处理重复key的情况，取最大值
                (existing, replacement) -> existing.max(replacement)
        ));
        return scoreMap;
    }

    public static class ScoreItemValidScore{
        private Long personId;
        private Long scoreItemId;
        private String scoreItemNumber;
        private Long scoreItemSubId;
        private Long scoreItemRankId;
        /**本次积分*/
        private BigDecimal currentScore;
        private BigDecimal sumScore;
        /** 可获得的有效分数（如果没有任何限制返回null,如果已超过限制返回0，否则返回剩余可加分数） */
        private BigDecimal validScore;
        //没有业务含义，只用来记录分录索引号；
        private int rowIndex;

        public ScoreItemValidScore(Long personId, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId) {
            this.personId = personId;
            this.scoreItemId = scoreItemId;
            this.scoreItemSubId = scoreItemSubId;
            this.scoreItemRankId = scoreItemRankId;
        }

        public ScoreItemValidScore(Long personId, Long scoreItemId,String scoreItemNumber, Long scoreItemSubId, Long scoreItemRankId, BigDecimal sumScore) {
            this.personId = personId;
            this.scoreItemId = scoreItemId;
            this.scoreItemNumber = scoreItemNumber;
            this.scoreItemSubId = scoreItemSubId;
            this.scoreItemRankId = scoreItemRankId;
            this.sumScore = sumScore;
        }

        public ScoreItemValidScore(Long personId, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId, BigDecimal sumScore, BigDecimal validScore) {
            this.personId = personId;
            this.scoreItemId = scoreItemId;
            this.scoreItemSubId = scoreItemSubId;
            this.scoreItemRankId = scoreItemRankId;
            this.sumScore = sumScore;
            this.validScore = validScore;
        }

        public Long getPersonId() {
            return personId;
        }

        public void setPersonId(Long personId) {
            this.personId = personId;
        }

        public Long getScoreItemId() {
            return scoreItemId;
        }

        public void setScoreItemId(Long scoreItemId) {
            this.scoreItemId = scoreItemId;
        }

        public String getScoreItemNumber() {
            return scoreItemNumber;
        }
        public void setScoreItemNumber(String scoreItemNumber) {
            this.scoreItemNumber = scoreItemNumber;
        }

        public Long getScoreItemSubId() {
            return scoreItemSubId;
        }

        public void setScoreItemSubId(Long scoreItemSubId) {
            this.scoreItemSubId = scoreItemSubId;
        }

        public Long getScoreItemRankId() {
            return scoreItemRankId;
        }

        public void setScoreItemRankId(Long scoreItemRankId) {
            this.scoreItemRankId = scoreItemRankId;
        }

        public BigDecimal getSumScore() {
            return sumScore;
        }

        public void setSumScore(BigDecimal sumScore) {
            this.sumScore = sumScore;
        }

        public BigDecimal getValidScore() {
           /* //为空时说明不限制分数
            BigDecimal trulyValidScore = this.currentScore;
            if(this.validScore != null && this.currentScore != null){
                //如果可使用分数超过录入分数则使用录入分数（oriScore），否则使用可使用分数
                trulyValidScore = this.validScore.min(this.currentScore);
            }else{
                return BigDecimal.ZERO;
            }
            return trulyValidScore;*/
            return this.validScore;
        }

        public void setValidScore(BigDecimal validScore) {
            this.validScore = validScore;
        }

        public BigDecimal getCurrentScore() {
            return currentScore;
        }

        public void setCurrentScore(BigDecimal currentScore) {
            this.currentScore = currentScore;
        }

        public int getRowIndex() {
            return rowIndex;
        }

        public void setRowIndex(int rowIndex) {
            this.rowIndex = rowIndex;
        }
    }
}
