package com.kingdee.eas.custom.perfweb.portal.handler;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.metadata.entity.EntityViewInfo;
import com.kingdee.bos.metadata.entity.FilterInfo;
import com.kingdee.bos.metadata.entity.FilterItemInfo;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.base.syssetting.app.filter.HRFilterUtils;
import com.kingdee.shr.base.syssetting.context.SHRContext;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
import com.kingdee.shr.perfweb.app.base.distribution.*;
import com.kingdee.shr.perfweb.app.base.evalplan.IPerfPeriod;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfPeriodFactory;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfPeriodInfo;
import com.kingdee.shr.perfweb.app.base.evalrule.PerformanceRuleInfo;
import com.kingdee.shr.perfweb.app.base.perfmancescore.*;
import com.kingdee.shr.perfweb.app.exception.SHRPerfWebBizException;
import com.kingdee.shr.perfweb.portal.handler.PerfBatchScoreHandler;
import com.kingdee.util.NumericExceptionSubItem;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.util.*;

public class PerfBatchScoreHandlerEx extends PerfBatchScoreHandler {

    public static final NumericExceptionSubItem LOADNODATAISTRIBUTIONINFOERR =
            new NumericExceptionSubItem("715", "\u5f53\u524d\u9875\u9762\u65e0\u6570\u636e");
    public void getDistributionInfoAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
        Context ctx = SHRContext.getInstance().getContext();
        HashMap resultMap = new HashMap();

        try {
            String periodId = request.getParameter("periodId");
            Assert.notNull(periodId);
            IPerfPeriod iPerfPeriod = PerfPeriodFactory.getLocalInstance(ctx);
            PerfPeriodInfo perfPeriodInfo = iPerfPeriod.getPerfPeriodInfo("select id,name,perfPlan.id,perfPlan.name,perfRule.id,perfRule.name,perfRule.*  where id ='" + periodId + "' ");
            Map<String, PerfScorLevelDefineInfo> leveMap = new LinkedHashMap();
            Map<String, Integer> leveStrMap = new LinkedHashMap();
            if (perfPeriodInfo != null) {
                PerformanceRuleInfo perfRule = perfPeriodInfo.getPerfRule();
                if (perfRule != null) {
                    PerfScoreLevelInfo perfRate = perfRule.getPerfRate();
                    if (perfRate != null) {
                        PerfScorLevelDefineCollection perfLevelDefInfoCol = perfRate.getPerfLevelDefInfo();
                        if (perfLevelDefInfoCol == null || perfLevelDefInfoCol.size() <= 0) {
                            IPerfScorLevelDefine iPerfScorLevelDefine = PerfScorLevelDefineFactory.getLocalInstance(ctx);
                            perfLevelDefInfoCol = iPerfScorLevelDefine.getPerfScorLevelDefineCollection("  where perfScoreLevel='" + perfRate.getId().toString() + "' order by showNumber ASC ");
                        }

                        if (perfLevelDefInfoCol != null && perfLevelDefInfoCol.size() > 0) {
                            for (int i = 0; i < perfLevelDefInfoCol.size(); ++i) {
                                PerfScorLevelDefineInfo perfScorLevelDefineInfo = perfLevelDefInfoCol.get(i);
                                leveMap.put(perfScorLevelDefineInfo.getId().toString(), perfScorLevelDefineInfo);
                            }
                        }
                    }
                }
            }

            Set<Map.Entry<String, PerfScorLevelDefineInfo>> entries = leveMap.entrySet();
            Iterator var21 = entries.iterator();

            while (var21.hasNext()) {
                Map.Entry<String, PerfScorLevelDefineInfo> entry = (Map.Entry) var21.next();
                leveStrMap.put(((PerfScorLevelDefineInfo) entry.getValue()).getPerfLevelName(), 0);
            }

            String personId = HRFilterUtils.getCurrentPersonId(ctx);
            StringBuffer selectBuf = new StringBuffer("SELECT t.fid as taskNodeId, FEvaobjId,FScoreStatus, FNODEGRADE  FROM T_EVA_GradeTaskNodeInst t INNER JOIN T_EVA_PerfevaObject o ON ");
            selectBuf.append(" t.FEvaobjId=o.FID ").append(" WHERE t.FNodeHandlerID='").append(personId).append("'").append(" AND t.FIsEffective='").append("1").append("'").append(" AND t.FScoreStatus not in ('").append("3").append("') ").append(" AND t.FPeriodID ='").append(periodId).append("'").append(" AND t.FIsSelf=").append(0);
            IRowSet rowSet = DbUtil.executeQuery(ctx, selectBuf.toString());
            if (perfPeriodInfo != null) {
                resultMap.put("perfPeriod", perfPeriodInfo.getName());
            }

            if (perfPeriodInfo.getPerfPlan() != null) {
                resultMap.put("perfPlan", perfPeriodInfo.getPerfPlan().getName());
            }

            resultMap.put("all", rowSet.size());
            HashSet scoredSet = new HashSet();

            try {
                while (rowSet.next()) {
                    String status = rowSet.getString("FScoreStatus");
                    if ("1".equalsIgnoreCase(status) ||"2".equalsIgnoreCase(status) || "5".equalsIgnoreCase(status)) {
                        scoredSet.add(rowSet.getString("taskNodeId"));
                        String grade = rowSet.getString("FNODEGRADE");
                        if (StringUtils.isNotBlank(grade)) {
                            leveStrMap.put(grade, leveStrMap.get(grade) == null ? 0 : (Integer) leveStrMap.get(grade) + 1);
                        }
                    }
                }
            } catch (SQLException var18) {
                throw new BOSException(var18);
            }


            IDistribution iDistribution = DistributionFactory.getLocalInstance(ctx);
            DistributionInfo distributionInfo = iDistribution.getDistributionInfo("select * where number ='01' ");
            IDistributionDefine iDistributionDefine = DistributionDefineFactory.getLocalInstance(ctx);
            FilterInfo filterInfo = new FilterInfo();
            filterInfo.getFilterItems().add(new FilterItemInfo("distribution.number", "01"));
//            SelectorItemCollection sic = new SelectorItemCollection();
//            sic.add("");
            EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, null, null);
            // coll = iDistributionDefine.getDistributionDefineCollection("select *,refDefine.id,refDefine.name,refDefine.number, distribution.perfScoreLevel.perfScoreInfo.* where distribution ='" + id + "' order by index asc");
            DistributionDefineCollection defineCollection = iDistributionDefine.getDistributionDefineCollection(viewInfo);
            // 获取总数（从resultMap中获取）
            int total = (Integer) resultMap.get("all");

            // 创建分布规则集合（改为Map结构）
            Map<String, Integer> distributionRules = new LinkedHashMap<>();

            // 已分配的人数
            int allocatedCount = 0;

            for (int i = 0; i < defineCollection.size(); i++) {
                DistributionDefineInfo defineInfo = defineCollection.get(i);

                // 获取上下限并转换为整数百分比
                BigDecimal upLimit = defineInfo.getScaleUpLimit().setScale(0, RoundingMode.HALF_UP);
                BigDecimal downLimit = defineInfo.getScaleDownLimit().setScale(0, RoundingMode.HALF_UP);

                // 计算比例范围
                BigDecimal range = downLimit.subtract(upLimit);

                // 计算推荐人数
                int recommendCount = Math.round(total * range.divide(BigDecimal.valueOf(100)).floatValue());

                // 防止推荐人数超过剩余人数
                int remaining = total - allocatedCount;
                recommendCount = Math.min(recommendCount, remaining);

                // 确保推荐人数非负
                recommendCount = Math.max(0, recommendCount);

                // 更新已分配人数
                allocatedCount += recommendCount;

                // 构建规则数据
                String levelName = defineInfo.getPerfLevel();
                distributionRules.put(levelName, recommendCount); // 使用绩效等级作为键，推荐人数作为值
            }

            // 处理最后一个等级的剩余人数
            if (allocatedCount < total) {
                String lastLevel = distributionRules.keySet().iterator().next(); // 获取最后一个等级
                int lastRecommendCount = distributionRules.get(lastLevel);
                distributionRules.put(lastLevel, lastRecommendCount + (total - allocatedCount)); // 补足剩余人数
            }

            // 按照leveStrMap的顺序重新排序distributionRules
            Map<String, Integer> sortedDistributionRules = new LinkedHashMap<>();
            // 遍历leveStrMap的键，按照顺序构建新的Map
            for (String level : leveStrMap.keySet()) {
                if (distributionRules.containsKey(level)) {
                    sortedDistributionRules.put(level, distributionRules.get(level));
                }
            }

            // 将结果放入响应
            resultMap.put("distributionRules", sortedDistributionRules);

            resultMap.put("scored", scoredSet.size());
            resultMap.put("unScored", rowSet.size() - scoredSet.size());
            resultMap.put("leveStrMap", leveStrMap);
            JSONUtils.writeJson(response, resultMap);
        }
        catch (Exception e) {
            e.printStackTrace();
            //throw new SHRWebException(new SHRPerfWebBizException(SHRPerfWebBizException.LOADNORMALDISTRIBUTIONINFOERR));

            //throw new SHRWebException(new SHRPerfWebBizException(LOADNODATAISTRIBUTIONINFOERR));
        }
    }


}



