package nckd.jxccl.opmc.pm.plugin.operate.salary;

import kd.bos.bd.pojo.CtrlStrategyEnum;
import kd.bos.common.enums.EnableEnum;
import kd.bos.consts.PermItemConst;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.ObjectUtils;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.operate.OperateOptionConst;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
import kd.bos.entity.validate.BillStatus;
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.BusinessDataServiceHelper;
import kd.bos.servicehelper.DispatchServiceHelper;
import kd.bos.servicehelper.MetadataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import kd.hr.hbp.common.model.OrgSubInfo;
import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.AppraisalResultEnum;
import nckd.jxccl.base.common.exception.ValidationException;
import nckd.jxccl.base.common.utils.ConvertUtil;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.QueryFieldBuilder;
import nckd.jxccl.base.common.utils.StrFormatter;
import nckd.jxccl.base.entity.helper.EntityHelper;
import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
import nckd.jxccl.opmc.pm.common.SalAdjTrackerConstant;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * 生成调薪情况
 * 实体标识：nckd_saladjtracker
 * @author W.Y.C
 * @date 2025/11/24 13:14
 * @version 1.0
 */
public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements Plugin {

    private static final Log logger = LogFactory.getLog(SalaryAdjOpPlugin.class);

    // 调薪类型常量
    /**不及格降档*/
    private static final int TYPE_DEMOTE_FOR_FAIL = -1;
    /**及格升档*/
    private static final int TYPE_NO_CHANGE = 0;
    /**双优升档*/
    private static final int TYPE_PROMOTE_FOR_TWO_EXCELLENT = 1;
    /**三及格升档*/
    private static final int TYPE_PROMOTE_FOR_THREE_PASS = 2;
    /**双优以及三及格升档*/
    private static final int TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS = 3;
    /**连续两年考核结果为优秀且另一年考核结果为合格及以上*/
    private static final int TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS_FOR_TWO_YEARS = 4;


    int passYear = 2018;

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {


        Long currUserId = RequestContext.get().getCurrUserId();
        DynamicObject currUser = UserServiceHelper.getUserInfoByID(currUserId, FormConstant.ID_KEY);

        // 构建考核周期查询条件
        QFilter perfManagerFilter = buildPerfManagerFilter();
        perfManagerFilter.and(PerfManagerFormConstant.NCKD_SALARYADJUSTGENFLAG,QCP.not_equals,EnableEnum.YES.getCode());
        QueryFieldBuilder perfManagerQueryFieldBuilder = buildPerfManagerQueryFieldBuilder();
        DynamicObjectCollection perfManagerList = QueryServiceHelper.query(PerfManagerFormConstant.PERFMANAGER_ENTITYID, perfManagerQueryFieldBuilder.buildSelect(), new QFilter[]{perfManagerFilter});

        List<Long> perfManagerIds = perfManagerList.stream()
                .map(perfManager -> perfManager.getLong(FormConstant.ID_KEY))
                .collect(Collectors.toList());

        QFilter qFilter = new QFilter(SalAdjTrackerConstant.NCKD_PERFMANAGER,QCP.in,perfManagerIds);
        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                .add(FormConstant.ID_KEY)
                .addIdNumberName(SalAdjTrackerConstant.NCKD_PERFMANAGER);
        DynamicObjectCollection query = QueryServiceHelper.query(SalAdjTrackerConstant.SALADJTRACKER_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
        Map<Long, Long> perfManagerToSalaryAdjMap = query.stream()
                .collect(Collectors.toMap(
                        item -> item.getLong(String.join(".", SalAdjTrackerConstant.NCKD_PERFMANAGER, FormConstant.ID_KEY)),
                        item -> item.getLong(FormConstant.ID_KEY)
                ));

        List<SalaryAdjustmentResult> salaryAdjustmentResultList = new ArrayList<>();
        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
        for (DynamicObject perfManager : perfManagerList) {
            long id = perfManager.getLong(FormConstant.ID_KEY);
            if(perfManagerToSalaryAdjMap.get(id) == null) {
                long personId = perfManager.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
                String personName = perfManager.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY));
                LocalDateTime beginDate = DateUtil.toLocalDateTime(perfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
                int beginYear = beginDate.getYear();
                LocalDateTime endDate = DateUtil.toLocalDateTime(perfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
                int endYear = endDate.getYear();
                Date actEndDate = perfManager.getDate(PerfManagerFormConstant.NCKD_ACTENDYEAR);
                LocalDateTime actEndLocalDateTime = actEndDate != null ? DateUtil.toLocalDateTime(actEndDate) : endDate;
                int actEndYear = actEndLocalDateTime.getYear();
                String theStatus = perfManager.getString(PerfManagerFormConstant.NCKD_THESTATUS);


                if (actEndYear <= passYear) {
                    logger.info(">>>周期开始时间在上线前!PASS!!");
                    continue;
                }
                if (theStatus != null && !"1".equals(theStatus)) {
                    logger.info(">>>周期状态非正常!PASS!!");
                    continue;
                }
                int nowYear = Calendar.getInstance().get(Calendar.YEAR);
                if (nowYear < beginYear) {
                    logger.info(">>>还未到周期开始时间!PASS!!");
                    continue;
                }
                //第一年考核结果
                String firstYearResultNumber = perfManager.getString(String.join(".", PerfManagerFormConstant.NCKD_FIRSTYEARRESULT, FormConstant.NUMBER_KEY));
                AppraisalResultEnum firstYearResult = AppraisalResultEnum.getByCode(firstYearResultNumber);
                //第二年考核结果
                String secondYearResultNumber = perfManager.getString(String.join(".", PerfManagerFormConstant.NCKD_SECONDYEARRESULT, FormConstant.NUMBER_KEY));
                AppraisalResultEnum secondYearResult = AppraisalResultEnum.getByCode(secondYearResultNumber);
                //第三年考核结果
                String thirdYearResultNumber = perfManager.getString(String.join(".", PerfManagerFormConstant.NCKD_THIRDYEARRESULT, FormConstant.NUMBER_KEY));
                AppraisalResultEnum thirdYearResult = AppraisalResultEnum.getByCode(thirdYearResultNumber);

                //校验当前考核周期是否已经在调薪列表中
                // 计算调薪档次
                SalaryAdjustmentResult result = calculateSalaryAdjustmentLevel(firstYearResult, secondYearResult, thirdYearResult, beginYear, endYear);
                logger.info("人员ID: {} 的调薪档次为: {}，调薪类型: {}，调薪说明: {}", personId, result.level, result.type, result.reason);
                if (result.level != 0) {
                    long companyId = perfManager.getLong(String.join(".", FormConstant.NCKD_DEP, FormConstant.NCKD_SECONDORG, FormConstant.ID_KEY));
                    long empPosOrgRelId = perfManager.getLong(String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.ID_KEY));
                    long depId = perfManager.getLong(String.join(".", FormConstant.NCKD_DEP, FormConstant.ID_KEY));
                    long positionId = perfManager.getLong(String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.POSITION_KEY, FormConstant.ID_KEY));
                    result.id = id;
                    result.companyId = personId;
                    result.depId = depId;
                    result.positionId = positionId;
                    result.empPosOrgRelId = empPosOrgRelId;
                    result.personId = personId;
                    result.personName = personName;
                    result.beginDate = beginDate;
                    result.endDate = endDate;
                    salaryAdjustmentResultList.add(result);
                }
            }
        }
        StringJoiner msgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
        if(!salaryAdjustmentResultList.isEmpty()) {
            //判断有没有同一人员存在多条正常状态的考核周期
            Map<Long, List<SalaryAdjustmentResult>> personGroups = salaryAdjustmentResultList.stream()
                    .collect(Collectors.groupingBy(result -> result.personId));
            StringJoiner duplicateMsgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
            for (Map.Entry<Long, List<SalaryAdjustmentResult>> entry : personGroups.entrySet()) {
                if (entry.getValue().size() > 1) {
                    // 存在重复的personId
                    SalaryAdjustmentResult firstResult = entry.getValue().get(0);
                    String personName = firstResult.personName;
                    StringJoiner periodJoiner = new StringJoiner("，");
                    for (SalaryAdjustmentResult result : entry.getValue()) {
                        String period = String.format("%d~%d",
                                result.beginDate.getYear(),
                                result.endDate.getYear());
                        periodJoiner.add(period);
                    }
                    String message = StrFormatter.format("【{}】存在多个状态【正常】的周期；{}",
                            personName, periodJoiner.toString());
                    duplicateMsgJoiner.add(message);
                }
            }
            if (duplicateMsgJoiner.length() > 0) {
                throw new ValidationException(duplicateMsgJoiner.toString());
            }

            if (!salaryAdjustmentResultList.isEmpty()) {
                List<Long> allPersonIds = salaryAdjustmentResultList.stream()
                        .map(result -> result.personId)
                        .collect(Collectors.toList());
                List<Long> allEmpPosOrgRelIds = salaryAdjustmentResultList.stream()
                        .map(result -> result.empPosOrgRelId)
                        .collect(Collectors.toList());

                DynamicObject standardItem = EntityHelper.newEntity(FormConstant.HSBS_STANDARDITEM);
                standardItem.set(FormConstant.ID_KEY, salaryItemId);
                Map<String, Object> adjFileParams = new HashMap<>();
                adjFileParams.put("employees", allPersonIds);
                List<String> status = new ArrayList<>();
                status.add(BillStatus.C.toString());
                adjFileParams.put("status", status);
                //获取人员定薪档案
                Map<String, Object> adjFileResult = DispatchServiceHelper.invokeBizService("swc", "hcdm", "IAdjFileInfoService", "queryAdjFileBoByEmp", adjFileParams);
                if (ConvertUtil.toBoolean(adjFileResult.get("success"))) {
                    List<Map> list = ConvertUtil.toList(adjFileResult.get("data"), ArrayList::new);
                    List<Long> adjFileIds = new ArrayList<>();
                    for (Map map : list) {
                        Long id = ConvertUtil.toLong(map.get(FormConstant.ID_KEY));
                        //根据员工任职匹配
                        Long empPosOrgRelId = ConvertUtil.toLong(map.get("empposorgrel_id"));
                        if (allEmpPosOrgRelIds.contains(empPosOrgRelId)) {
                            adjFileIds.add(id);
                        }
                    }
                    //构建定调薪记录查询条件
                    Map<String, Object> adjRecordParams = new HashMap<>();
                    List<Map<String, Object>> dataList = new ArrayList<>();
                    for (Long adjFileId : adjFileIds) {
                        Map<String, Object> dataItem = new HashMap<>();
                        // 调薪档案ID
                        dataItem.put("adjfile", adjFileId);
                        // 调薪项目ID
                        dataItem.put("standarditem", salaryItemId);
                        // 查询基准日期
                        dataItem.put("startdate", new Date());
                        // 唯一标识
                        dataItem.put("_uniquecode", "unique" + adjFileId);
                        dataList.add(dataItem);
                    }


                    adjRecordParams.put("data", dataList);
                    adjRecordParams.put("selprops", "salarystdv.rankentry.rank.id,salarystdv.rankentry.rank.name,salarystdv.rankentry.rank.number,salarystdv.rankentry.rank.index,salarystdv.rankentry.frankindex,company.id,company.name,");
                    //查询定调薪记录
                    Map<String, Object> lastDecAdjRecordMap = DispatchServiceHelper.invokeService("nckd.jxccl.swc.hcdm.servicehelper", "hcdm", "ISwcService", "getLastDecAdjRecords", adjRecordParams);
                    if (ConvertUtil.toBoolean(lastDecAdjRecordMap.get("success"))) {
                        List<Map> datas = ConvertUtil.toList(lastDecAdjRecordMap.get("data"), ArrayList::new);
                        for (Map data : datas) {
                            if (ConvertUtil.toBoolean(data.get("success"))) {
                                List<DynamicObject> adjRecordList = ConvertUtil.toList(data.get("data"), ArrayList::new);
                                for (DynamicObject dynamicObject : adjRecordList) {
                                    // 人员
                                    DynamicObject employee = dynamicObject.getDynamicObject("adjfile").getDynamicObject("employee");
                                    SalaryAdjustmentResult salaryAdjustmentResult = null;
                                    for (SalaryAdjustmentResult result : salaryAdjustmentResultList) {
                                        if (result.personId == employee.getLong(FormConstant.ID_KEY)) {
                                            salaryAdjustmentResult = result;
                                        }
                                    }
                                    if (salaryAdjustmentResult != null) {
                                        //薪酬标准表版本
                                        DynamicObject salaryStDv = dynamicObject.getDynamicObject("salarystdv");
                                        //薪等（01岗、02岗）
                                        DynamicObject salaryGrade = dynamicObject.getDynamicObject("salarygrade");
                                        //薪档（1档、2档）
                                        DynamicObject salaryRank = dynamicObject.getDynamicObject("salaryrank");
                                        //金额
                                        BigDecimal amount = dynamicObject.getBigDecimal("amount");
                                        salaryAdjustmentResult.adjFileInfo = dynamicObject.getDynamicObject("adjfile");
                                        salaryAdjustmentResult.salaryStDv = salaryStDv;
                                        salaryAdjustmentResult.oldStandardItem = standardItem;
                                        salaryAdjustmentResult.oldSalaryGrade = salaryGrade;
                                        salaryAdjustmentResult.oldSalaryRank = salaryRank;
                                        salaryAdjustmentResult.oldAmount = amount;
                                    }
                                }
                            }
                        }
                    } else {
                        logger.error("查询定调薪记录失败");
                        this.operationResult.setSuccess(false);
                        this.operationResult.setMessage("查询定调薪记录失败");
                    }
                } else {
                    logger.error("获取人员定薪档案失败");
                    this.operationResult.setSuccess(false);
                    this.operationResult.setMessage("获取人员定薪档案失败");
                }


                Set<Long> salarystandarId = new HashSet(salaryAdjustmentResultList.size());
                for (SalaryAdjustmentResult result : salaryAdjustmentResultList) {
                    if (result.salaryStDv != null) {
                        DynamicObject salaryStDv = result.salaryStDv;
                        long stdTableId = salaryStDv.getLong(FormConstant.ID_KEY);
                        salarystandarId.add(stdTableId);
                    }
                }
                //重新加载薪酬标准表（不然超过三级限制取不到薪档序号）
                QueryFieldBuilder salaryStandFieldBuilder = QueryFieldBuilder.create()
                        .add(FormConstant.ID_KEY)
                        .addIdNumberNameWithExtras(new String[]{"rankentry", "rank", FormConstant.INDEX_KEY});
                DynamicObject[] salaryStandardArray = BusinessDataServiceHelper.load("hcdm_salarystandard", salaryStandFieldBuilder.buildSelect(), new QFilter[]{new QFilter(FormConstant.ID_KEY, QCP.in, salarystandarId)});
                Map<Long, DynamicObject> salaryStandardMap = Arrays.stream(salaryStandardArray)
                        .collect(Collectors.toMap(
                                obj -> obj.getLong(FormConstant.ID_KEY),
                                obj -> obj
                        ));


                msgJoiner.add(StrFormatter.format("调档成功，以下是本次调档的人员："));
                for (SalaryAdjustmentResult result : salaryAdjustmentResultList) {
                    if (result.salaryStDv == null || result.oldStandardItem == null || result.oldSalaryRank == null) {
                        msgJoiner.add(StrFormatter.format("【{}】没有定调薪档案或没有定薪项目【岗位工资标准】，无法调档", result.personName));
                    } else {
                        long salaryStDvId = result.salaryStDv.getLong(FormConstant.ID_KEY);
                        DynamicObject salaryStandard = salaryStandardMap.get(salaryStDvId);

                        //薪酬标准中薪档（薪档名称不等于档差和等差）
                        DynamicObjectCollection rankEntry = salaryStandard.getDynamicObjectCollection("rankentry");
                        Map<Integer, DynamicObject> rankMap = rankEntry.stream().filter(rank -> !rank.getDynamicObject("rank").getString(FormConstant.NAME_KEY).contains("差"))
                                .collect(Collectors.toMap(
                                        rank -> rank.getDynamicObject("rank").getInt(FormConstant.INDEX_KEY),
                                        rank -> rank.getDynamicObject("rank"),
                                        (existing, replacement) -> replacement // 处理重复键，保留后来的值
                                ));
                        Optional<DynamicObject> diffRecord = rankEntry.stream()
                                .filter(rank -> rank.getDynamicObject("rank").getString(FormConstant.NAME_KEY).contains("档差"))
                                .findFirst();

                        DynamicObject diffRank = null;
                        if (diffRecord.isPresent()) {
                            diffRank = diffRecord.get().getDynamicObject("rank");
                        }
                        if (!rankMap.isEmpty()) {
                            //原薪档
                            DynamicObject oldSalaryRank = result.oldSalaryRank;
                            int oldIndex = oldSalaryRank.getInt(FormConstant.INDEX_KEY);
                            //调整后薪档序号
                            int finalRankIndex = oldIndex + result.level;
                            DynamicObject newSalaryRank;
                            //判断是否超过薪档的最大序号或最小序号，如果超过则取最小或最大
                            int maxRankIndex = Collections.max(rankMap.keySet());
                            int minRankIndex = Collections.min(rankMap.keySet());
                            if (finalRankIndex > maxRankIndex) {
                                // 超过最大值，取最大值
                                newSalaryRank = rankMap.get(maxRankIndex);
                            } else if (finalRankIndex < minRankIndex) {
                                // 低于最小值，取最小值
                                newSalaryRank = rankMap.get(minRankIndex);
                            } else {
                                newSalaryRank = rankMap.get(finalRankIndex);
                            }
                            result.salaryRank = newSalaryRank;
                            result.reason += StrFormatter.format("；{}->{}", oldSalaryRank.getString(FormConstant.NAME_KEY), newSalaryRank.getString(FormConstant.NAME_KEY));
                            List<Map<String,Object>> matchParams = new ArrayList<>();
                            Map<String,Object> stdTableDataMatchParam = new HashMap<>();
                            stdTableDataMatchParam.put("stdTableId", result.salaryStDv.getLong(FormConstant.ID_KEY));
                            stdTableDataMatchParam.put("stdItemId", salaryItemId);
                            stdTableDataMatchParam.put("gradeId", result.oldSalaryGrade.getLong(FormConstant.ID_KEY));
                            stdTableDataMatchParam.put("rankId", newSalaryRank.getLong(FormConstant.ID_KEY));
                            matchParams.add(stdTableDataMatchParam);
                            //获取薪酬项目、薪等、薪档对应金额
                            List<Map<String,Object>> stdTableDataMatchResults = DispatchServiceHelper.invokeService("nckd.jxccl.swc.hcdm.servicehelper", "hcdm", "ISwcService", "matchStdTableData", matchParams);
                            if (!stdTableDataMatchResults.isEmpty()) {
                                result.amount = ConvertUtil.toBigDecimal(stdTableDataMatchResults.get(0).get("amount"));
                            }
                            msgJoiner.add(StrFormatter.format("【{}】{}", result.personName, result.reason));
                        }
                    }
                }
                List<DynamicObject> addSalAdjTrackerList = new ArrayList<>();
                List<Long> ids = new ArrayList<>(salaryAdjustmentResultList.size());
                for (SalaryAdjustmentResult result : salaryAdjustmentResultList) {
                    if (result.salaryStDv != null && result.oldStandardItem != null && result.oldSalaryRank != null) {
                        DynamicObject newSalAdjTracker = EntityHelper.newEntity(SalAdjTrackerConstant.SALADJTRACKER_ENTITYID);
                        newSalAdjTracker.set(FormConstant.NAME_KEY, StrFormatter.format("{}的调薪", result.personName));
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_PERFMANAGER, EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID, result.id));
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_ADJFILEINFO, result.adjFileInfo);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_OLDSALARYGRADE, result.oldSalaryGrade);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_OLDSALARYRANK, result.oldSalaryRank);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_OLDMONEY, result.oldAmount);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_SALARYGRADE, result.oldSalaryGrade);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_SALARYRANK, result.salaryRank);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_MONEY, result.amount);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_WAGEEXPLAIN, result.reason);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_APPRAISALTYPE, result.type);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_WAGESTATUS, "1");
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_ADJUSTDIFF, result.level);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_OLDSTANDARDITEM, result.oldStandardItem);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_STANDARDITEM, result.oldStandardItem);
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_ADJMONEY, result.amount.subtract(result.oldAmount));
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_DEP, EntityHelper.newEntity(FormConstant.ADMINORG_ENTITYID, result.depId));
                        newSalAdjTracker.set(SalAdjTrackerConstant.NCKD_POSITION, EntityHelper.newEntity(PerfManagerFormConstant.HBPM_POSITIONHR, result.positionId));
                        newSalAdjTracker.set(SalAdjTrackerConstant.CREATOR_KEY, UserServiceHelper.getCurrentUserId());
                        ids.add(result.id);
                        addSalAdjTrackerList.add(newSalAdjTracker);
                    }
                }
                MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
                DynamicObject[] perfManagerArray = BusinessDataServiceHelper.load(ids.toArray(new Long[0]), dataEntityType);
                List<DynamicObject> addPerfManagerList = new ArrayList<>();
                for (DynamicObject perfManager : perfManagerArray) {
                    perfManager.set(PerfManagerFormConstant.NCKD_WHYEND, "调档后结束");
                    perfManager.set(PerfManagerFormConstant.NCKD_THESTATUS, "2");
                    perfManager.set(PerfManagerFormConstant.NCKD_LOCKUSER, currUser);
                    perfManager.set(PerfManagerFormConstant.NCKD_SALARYADJUSTGENFLAG, EnableEnum.YES.getCode());
                    LocalDateTime beginDate = DateUtil.toLocalDateTime(perfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
                    LocalDateTime endDate = DateUtil.toLocalDateTime(perfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
                    //第一年考核结果
                    String firstYearResultNumber = null;
                    DynamicObject firstYearResultObj = perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT);
                    if (firstYearResultObj != null) {
                        firstYearResultNumber = firstYearResultObj.getString(FormConstant.NUMBER_KEY);
                    }
                    AppraisalResultEnum firstYearResult = AppraisalResultEnum.getByCode(firstYearResultNumber);
                    //第二年考核结果
                    String secondYearResultNumber = null;
                    DynamicObject secondYearResultObj = perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_SECONDYEARRESULT);
                    if (secondYearResultObj != null) {
                        secondYearResultNumber = secondYearResultObj.getString(FormConstant.NUMBER_KEY);
                    }
                    AppraisalResultEnum secondYearResult = AppraisalResultEnum.getByCode(secondYearResultNumber);
                    //第三年考核结果
                    String thirdYearResultNumber = null;
                    DynamicObject thirdYearResultObj = perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_THIRDYEARRESULT);
                    if (thirdYearResultObj != null) {
                        thirdYearResultNumber = thirdYearResultObj.getString(FormConstant.NUMBER_KEY);
                    }
                    AppraisalResultEnum thirdYearResult = AppraisalResultEnum.getByCode(thirdYearResultNumber);

                    //根据年份考核结果计算实际结束年份
                    LocalDateTime actEndYear = null;
                    if (isAppraisalResult(firstYearResult) && isAppraisalResult(secondYearResult) && !isAppraisalResult(thirdYearResult)) {
                        actEndYear = DateUtil.minusYears(endDate, 1);
                    } else if (isAppraisalResult(firstYearResult) && !isAppraisalResult(secondYearResult) && !isAppraisalResult(thirdYearResult)) {
                        actEndYear = DateUtil.minusYears(endDate, 2);
                    }else {
                        actEndYear = endDate;
                    }
                    perfManager.set(PerfManagerFormConstant.NCKD_ACTENDYEAR, DateUtil.toDate(actEndYear));

                    DynamicObject newPerfManager = EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
                    DynamicObject person = perfManager.getDynamicObject(FormConstant.NCKD_PERSON);
                    String personName = person.getString(FormConstant.NAME_KEY);
                    newPerfManager.set(FormConstant.CREATEORG_KEY, perfManager.get(FormConstant.CREATEORG_KEY));
                    newPerfManager.set(PerfManagerFormConstant.CTRLSTRATEGY_KEY, CtrlStrategyEnum.GLOBAL_SHARE.getCtrlStrategy());
                    newPerfManager.set(FormConstant.NCKD_EMPPOSORGREL, perfManager.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL));
                    newPerfManager.set(FormConstant.NCKD_DEP, perfManager.getDynamicObject(FormConstant.NCKD_DEP));
                    newPerfManager.set(FormConstant.NCKD_PERSON, person);
                    LocalDateTime newBeginDate = DateUtil.addYears(actEndYear, 1);
                    LocalDateTime newEndDate = DateUtil.addYears(actEndYear, 3);
                    newPerfManager.set(PerfManagerFormConstant.NCKD_BEGINYEAR, DateUtil.toDate(newBeginDate));
                    newPerfManager.set(PerfManagerFormConstant.NCKD_ENDYEAR, DateUtil.toDate(newEndDate));
                    newPerfManager.set(PerfManagerFormConstant.DESCRIPTION_KEY, "调档后生成新周期");
                    newPerfManager.set(PerfManagerFormConstant.NCKD_LASTPERFMANAGER, perfManager);
                    newPerfManager.set(FormConstant.NAME_KEY, StrFormatter.format("【{}】{}~{}的考核周期", personName, newBeginDate.getYear(), newEndDate.getYear()));
                    addPerfManagerList.add(newPerfManager);
                }
                OperateOption option = OperateOption.create();
                option.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE + "");
                option.setVariableValue("isUpdate", Boolean.TRUE + "");
                //保存当前考核周期
                OperationResult operationResult = SaveServiceHelper.saveOperate(FormConstant.SAVE_OP, PerfManagerFormConstant.PERFMANAGER_ENTITYID, perfManagerArray, option);
                if (!operationResult.isSuccess()) {
                    StringJoiner errorMsgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
                    for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
                        errorMsgJoiner.add(error.getMessage());
                    }
                    String errorMsg = errorMsgJoiner.toString();
                    if (StringUtils.isBlank(errorMsg)) {
                        errorMsg = operationResult.getMessage();
                    }
                    throw new ValidationException("保存考核周期失败，原因：" + errorMsg);
                } else {
                    //生成新周期
                    OperateOption addPerfManagerOption = OperateOption.create();
                    addPerfManagerOption.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE + "");
                    addPerfManagerOption.setVariableValue("cyclegenerate", Boolean.TRUE + "");
                    OperationResult addPerfManagerResult = SaveServiceHelper.saveOperate(FormConstant.SAVE_OP, PerfManagerFormConstant.PERFMANAGER_ENTITYID, addPerfManagerList.toArray(new DynamicObject[0]), addPerfManagerOption);

                    if (!addPerfManagerResult.isSuccess()) {
                        StringJoiner errorMsg = new StringJoiner(StrFormatter.LINE_SEPARATOR);
                        for (IOperateInfo error : addPerfManagerResult.getAllErrorOrValidateInfo()) {
                            errorMsg.add(error.getMessage());
                        }
                        throw new ValidationException(errorMsg.toString());
                    } else {
                        //生成调薪情况
                        OperationResult salAdjTrackerResult = SaveServiceHelper.saveOperate(FormConstant.SAVE_OP, SalAdjTrackerConstant.SALADJTRACKER_ENTITYID, addSalAdjTrackerList.toArray(new DynamicObject[0]), OperateOption.create());
                        if (!salAdjTrackerResult.isSuccess()) {
                            StringJoiner errorMsgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
                            for (IOperateInfo error : salAdjTrackerResult.getAllErrorOrValidateInfo()) {
                                errorMsgJoiner.add(error.getMessage());
                            }
                            String errorMsg = errorMsgJoiner.toString();
                            if (StringUtils.isBlank(errorMsg)) {
                                errorMsg = salAdjTrackerResult.getMessage();
                            }
                            throw new ValidationException("保存调薪情况失败，原因：" + errorMsg);
                        }
                    }
                }
                this.operationResult.setSuccess(true);
                this.operationResult.setMessage(msgJoiner.toString());
            }
        }else{
            this.operationResult.setSuccess(true);
            this.operationResult.setMessage("没有需要调档的人员！");
        }


        //周期生成
        OperateOption option = OperateOption.create();
        option.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE+"");
        DynamicObject perfManager = EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
        OperationResult operationResult =  OperationServiceHelper.executeOperate("cyclegenerate", PerfManagerFormConstant.PERFMANAGER_ENTITYID, new DynamicObject[]{perfManager}, option);
        if (!operationResult.isSuccess()) {
            StringJoiner errorMsg = new StringJoiner("；");
            for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
                errorMsg.add(error.getMessage());
            }
            if (!ObjectUtils.isEmpty(operationResult.getMessage())) {
                errorMsg.add(operationResult.getMessage());
            }
            throw new ValidationException("周期生成失败，原因：" + errorMsg.toString());
        }else{
            msgJoiner.add(operationResult.getMessage());
        }

    }

    /**
     * 根据三年的考核结果计算调薪档次
     * 1. 考核结果三年合格及以上-上调一档；
     * 2. 考核结果连续两年优秀-上调一档；
     * 3. 考核结果为不合格-下降一档；
     * 4. 连续两年考核结果为优秀且另一年考核结果为合格及以上-上调两档；
     *
     * @param firstYear  第一年考核结果
     * @param secondYear 第二年考核结果
     * @param thirdYear  第三年考核结果
     * @param beginYear  考核周期开始年份
     * @param endYear    考核周期结束年份
     * @return 调薪结果对象，包含调薪档次和说明
     */
    private SalaryAdjustmentResult calculateSalaryAdjustmentLevel(AppraisalResultEnum firstYear, AppraisalResultEnum secondYear, AppraisalResultEnum thirdYear, int beginYear, int endYear) {
        // 定义考核等级常量组
        final Set<AppraisalResultEnum> EXCELLENT_LEVELS = new HashSet<>(Arrays.asList(AppraisalResultEnum.EXCELLENT, AppraisalResultEnum.DEEMED_EXCELLENT));
        final Set<AppraisalResultEnum> QUALIFIED_LEVELS = new HashSet<>(Arrays.asList(AppraisalResultEnum.EXCELLENT, AppraisalResultEnum.DEEMED_EXCELLENT,
                AppraisalResultEnum.QUALIFIED, AppraisalResultEnum.DEEMED_QUALIFIED, AppraisalResultEnum.NONE));
        final Set<AppraisalResultEnum> UNQUALIFIED_LEVELS = new HashSet<>(Arrays.asList(AppraisalResultEnum.UN_QUALIFIED, AppraisalResultEnum.DEEMED_UNQUALIFIED));


        // 判断各年份是否存在并获取相应值
        boolean isFirstYearPresent = isAppraisalResult(firstYear);
        boolean isSecondYearPresent = isAppraisalResult(secondYear);
        boolean isThirdYearPresent = isAppraisalResult(thirdYear);

        // 判断是否为优秀（包括视同优秀）
        boolean isFirstYearExcellent = isFirstYearPresent && EXCELLENT_LEVELS.contains(firstYear);
        boolean isSecondYearExcellent = isSecondYearPresent && EXCELLENT_LEVELS.contains(secondYear);
        boolean isThirdYearExcellent = isThirdYearPresent && EXCELLENT_LEVELS.contains(thirdYear);

        // 判断是否为合格及以上（包括合格、视同合格、无、优秀、视同优秀）
        boolean isFirstYearQualifiedOrAbove = isFirstYearPresent && QUALIFIED_LEVELS.contains(firstYear);
        boolean isSecondYearQualifiedOrAbove = isSecondYearPresent && QUALIFIED_LEVELS.contains(secondYear);
        boolean isThirdYearQualifiedOrAbove = isThirdYearPresent && QUALIFIED_LEVELS.contains(thirdYear);

        // 判断是否为不合格（包括视同不合格）
        boolean isFirstYearUnqualified = isFirstYearPresent && UNQUALIFIED_LEVELS.contains(firstYear);
        boolean isSecondYearUnqualified = isSecondYearPresent && UNQUALIFIED_LEVELS.contains(secondYear);
        boolean isThirdYearUnqualified = isThirdYearPresent && UNQUALIFIED_LEVELS.contains(thirdYear);

        // 获取每年的具体考核结果名称
        String firstYearResultName = isFirstYearPresent ? firstYear.getName() : "无";
        String secondYearResultName = isSecondYearPresent ? secondYear.getName() : "无";
        String thirdYearResultName = isThirdYearPresent ? thirdYear.getName() : "无";

        // 计算具体的年份
        int firstYearValue = beginYear;
        int secondYearValue = beginYear + 1;
        int thirdYearValue = beginYear + 2;

        int type = TYPE_NO_CHANGE;    // 调薪类型
        int level = 0;   // 调薪档次
        String reason = String.format("未满足调薪条件（%d年：%s，%d年：%s，%d年：%s）",
                firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName); // 调薪原因

        // 规则3: 考核结果为不合格-下降一档（最高优先级）
        if (isFirstYearUnqualified || isSecondYearUnqualified || isThirdYearUnqualified) {
            reason = String.format("考核结果【不合格】【降一档】（%d年：%s，%d年：%s，%d年：%s）",
                    firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
            type = TYPE_DEMOTE_FOR_FAIL;
            level = -1;
        } else {
            // 规则4: 连续两年考核结果为优秀且另一年考核结果为合格及以上-上调两档（次高优先级）
            // 检查所有可能的连续两年优秀的情况
            if ((isFirstYearExcellent && isSecondYearExcellent && isThirdYearQualifiedOrAbove) ||
                    (isFirstYearQualifiedOrAbove && isSecondYearExcellent && isThirdYearExcellent)) {
                reason = String.format("连续两年考核结果为【优秀】且另一年考核结果为【合格及以上】【升两档】（%d年：%s，%d年：%s，%d年：%s）",
                        firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
                type = TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS_FOR_TWO_YEARS;
                level = 2;
            }else{
                // 规则2: 考核结果连续两年优秀-上调一档（只要连续两年优秀就可以上调，不需要三年都存在）
                if ((isFirstYearExcellent && isSecondYearExcellent) ||
                        (isSecondYearExcellent && isThirdYearExcellent)) {
                    reason = String.format("连续两年考核结果为【优秀】【升一档】（%d年：%s，%d年：%s，%d年：%s）",
                            firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
                    type = TYPE_PROMOTE_FOR_TWO_EXCELLENT;
                    level = 1;
                }
                // 规则1: 考核结果三年合格及以上-上调一档（较低优先级）
                if (isFirstYearQualifiedOrAbove && isSecondYearQualifiedOrAbove && isThirdYearQualifiedOrAbove) {
                    reason = String.format("三年考核结果均为【合格】【升一档】（%d年：%s，%d年：%s，%d年：%s）",
                            firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
                    // 特殊处理：如果是因为连续两年优秀上调一档，并且同时满足三年合格及以上，则更新类型
                    if(type == TYPE_PROMOTE_FOR_TWO_EXCELLENT){
                        reason = String.format("连续两年考核结果【优秀】且三年【合格及以上】【升一档】（%d年：%s，%d年：%s，%d年：%s）",
                                firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
                        type = TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS;
                    }else{
                        type = TYPE_PROMOTE_FOR_THREE_PASS;
                    }
                    level = 1;
                }
            }

        }
        return new SalaryAdjustmentResult(type, level, reason);
    }

    /**
     * 检查第一年考核结果是否存在
     */
    private boolean isAppraisalResult(AppraisalResultEnum appraisalResult) {
        return appraisalResult != null;
    }


    /**
     * 构建考核周期查询条件
     */
    private static QFilter buildPerfManagerFilter() {
        QFilter perfManagerFilter = QFilter.of("1=1");
        // 只处理权限范围内的人员
        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
                RequestContext.get().getCurrUserId(), "nckd_pm",  PerfManagerFormConstant.PERFMANAGER_ENTITYID,
                PermItemConst.ITEM_VIEW, new HashMap<>());
        if (dataRule != null) {
            perfManagerFilter.and(dataRule);
        }
        perfManagerFilter.and(PerfManagerFormConstant.NCKD_THESTATUS, QCP.equals, EnableEnum.YES.getCode());
        return perfManagerFilter;
    }

    /**
     * 构建考核周期查询字段
     */
    private static QueryFieldBuilder buildPerfManagerQueryFieldBuilder() {
        return QueryFieldBuilder.create()
                .add(FormConstant.ID_KEY)
                .add(PerfManagerFormConstant.NCKD_ISCURRENTNEWEST)
                .add(PerfManagerFormConstant.NCKD_BEGINYEAR)
                .add(PerfManagerFormConstant.NCKD_ENDYEAR)
                .add(PerfManagerFormConstant.NCKD_ACTENDYEAR)
                .add(PerfManagerFormConstant.NCKD_THESTATUS)
                .addIdNumberName(FormConstant.NCKD_PERSON)
                .addGroup(new String[]{FormConstant.NCKD_EMPPOSORGREL},FormConstant.ID_KEY)
                .addIdNumberName(FormConstant.NCKD_DEP)
                .addIdNumberName(FormConstant.NCKD_EMPPOSORGREL,FormConstant.POSITION_KEY)
                .addIdNumberName(FormConstant.NCKD_DEP,FormConstant.NCKD_SECONDORG)
                .addIdNumberName(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT)
                .addIdNumberName(PerfManagerFormConstant.NCKD_SECONDYEARRESULT)
                .addIdNumberName(PerfManagerFormConstant.NCKD_THIRDYEARRESULT);
    }
    /**
     * 提取组织ID列表
     */
    private static List<Long> extractOrgIds(List<OrgSubInfo> orgSubInfos) {
        return orgSubInfos.stream()
                .map(OrgSubInfo::getOrgId)
                .collect(Collectors.toList());
    }


    // 调薪结果类
    class SalaryAdjustmentResult {
        /**id*/
        long id;
        /** 人员ID*/
        long personId;
        /** 人员姓名*/
        String personName;
        //所属公司ID
        long companyId;
        //所属部门
        long depId;
        //所属部门
        long positionId;
        //任职经历
        long empPosOrgRelId;
        LocalDateTime beginDate;
        LocalDateTime endDate;
        /** 调薪类型*/
        int type;
        /** 调薪档次*/
        int level;
        /** 调薪原因*/
        String reason;
        /**定调薪档案*/
        DynamicObject adjFileInfo;
        /**薪酬标准表*/
        DynamicObject salaryStDv;
        /** 原定调薪项目 */
        DynamicObject oldStandardItem;
        /** 原薪等（01岗、02岗）*/
        DynamicObject oldSalaryGrade;
        /** 原薪档（1档、2档）*/
        DynamicObject oldSalaryRank;
        //金额
        BigDecimal oldAmount;
        /** 薪档（1档、2档）*/
        DynamicObject salaryRank;
        //金额
        BigDecimal amount;

        SalaryAdjustmentResult(int type, int level, String reason) {
            this.type = type;
            this.level = level;
            this.reason = reason;
        }
    }
}