package nckd.jxccl.hr.psms.plugin.form.performance;

import com.google.common.collect.Lists;
import kd.bos.bill.BillShowParameter;
import kd.bos.bill.OperationStatus;
import kd.bos.common.enums.EnableEnum;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.RefObject;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.IMetadata;
import kd.bos.dataentity.metadata.dynamicobject.DynamicObjectType;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.QueryEntityType;
import kd.bos.entity.constant.StatusEnum;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.datamodel.RowDataEntity;
import kd.bos.entity.datamodel.events.AfterAddRowEventArgs;
import kd.bos.entity.datamodel.events.BeforeDeleteRowEventArgs;
import kd.bos.entity.datamodel.events.BeforeImportEntryEventArgs;
import kd.bos.entity.datamodel.events.ChangeData;
import kd.bos.entity.datamodel.events.GetEntityTypeEventArgs;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.entity.filter.CompareTypeEnum;
import kd.bos.entity.filter.FilterValue;
import kd.bos.entity.filter.SimpleFilterRow;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.form.ConfirmCallBackListener;
import kd.bos.form.ConfirmTypes;
import kd.bos.form.IClientViewProxy;
import kd.bos.form.IPageCache;
import kd.bos.form.MessageBoxOptions;
import kd.bos.form.MessageBoxResult;
import kd.bos.form.container.Wizard;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.control.Steps;
import kd.bos.form.control.events.StepEvent;
import kd.bos.form.control.events.WizardStepsListener;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.events.MessageBoxClosedEvent;
import kd.bos.form.operate.FormOperate;
import kd.bos.form.plugin.AbstractFormPlugin;
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.QueryServiceHelper;
import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.AppraisalResultEnum;
import nckd.jxccl.base.common.enums.psms.JobSeqEnum;
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.orm.helper.QFilterCommonHelper;
import nckd.jxccl.hr.psms.common.PerfRankMgmtConstant;
import nckd.jxccl.hr.psms.common.PositionStructureConstant;
import nckd.jxccl.hr.psms.helper.PositionFileHelper;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
* 年度绩效排名管理表单
* @author W.Y.C
* @date 2025/10/20 15:11
* @version 1.0
*/
public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements WizardStepsListener {

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

    private final static String CALLBACK_ID = "interrupt_confirm";

    @Override
    public void registerListener(EventObject e) {
        Wizard wizard = this.getControl(FormConstant.NCKD_WIZARDAP);
        wizard.addWizardStepsListener(this);
    }

    @Override
    public void afterBindData(EventObject e) {
        sortEntry();
        this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        // 该单据不需要审批，默认为暂存状态
        this.getModel().setValue(FormConstant.STATUS, StatusEnum.A.toString());
        String step = ConvertUtil.toStr(this.getModel().getValue(PerfRankMgmtConstant.NCKD_STEP));
        String cacheStep = this.getView().getPageCache().get(PerfRankMgmtConstant.NCKD_STEP);
        if("1".equals(step) || ("1".equals(cacheStep))){
            if("1".equals(cacheStep)){
                this.getModel().setValue(PerfRankMgmtConstant.NCKD_STEP, 1);
                this.getView().updateView(PerfRankMgmtConstant.NCKD_STEP);
                this.getView().getPageCache().put(PerfRankMgmtConstant.NCKD_STEP,null);
                this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                /*DynamicObjectCollection dynamicObjectCollection = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                for (int i = 0; i < dynamicObjectCollection.size(); i++) {
                    boolean isRanking = dynamicObjectCollection.get(i).getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING);
                    if(!isRanking){
                        this.getModel().setValue(PerfRankMgmtConstant.NCKD_ISRANKING,true,i);
                        this.getView().updateView(PerfRankMgmtConstant.NCKD_ISRANKING,i);
                        this.getModel().setValue(PerfRankMgmtConstant.NCKD_ISRANKING,false,i);
                        this.getView().updateView(PerfRankMgmtConstant.NCKD_ISRANKING,i);
                    }
                }*/
                DynamicObjectCollection entryEntityCols = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                entryEntityCols.removeIf(obj -> obj.getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING));
                this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
            }
            setStepStatus(0,Steps.FINISH);
            setStepStatus(1,Steps.PROCESS);

            //步骤为：导入考核结果时只显示参与排名的人员
//            applyRankingFilter(true);

            importResultStep();


        }else{
            generatePersonList();
        }
    }

    @Override
    public void afterAddRow(AfterAddRowEventArgs e) {
        try {
            // 获取新增行信息并设置焦点
            for (RowDataEntity rowDataEntity : e.getRowDataEntities()) {
                int rowIndex = rowDataEntity.getRowIndex();
                //获取分录焦点
                IClientViewProxy viewProxy = this.getView().getService(IClientViewProxy.class);
                viewProxy.focusCell(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, rowIndex, FormConstant.NCKD_PERSON);
            }
            this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        } catch (Exception ex) {
            logger.error("设置新增行焦点失败", ex);
        }
    }



    @Override
    public void beforePropertyChanged(PropertyChangedArgs e) {
        String name = e.getProperty().getName();
        if (PerfRankMgmtConstant.NCKD_ADMINORG.equalsIgnoreCase(name)) {
            ChangeData[] changeSet = e.getChangeSet();
            Long newValueId = ConvertUtil.toLong(changeSet[0].getNewValue(),null);
            Object oldValue = ConvertUtil.toDynamicObjectOrNull(changeSet[0].getOldValue());
            Long oldValueId = oldValue == null ? null : ConvertUtil.toLong(oldValue, null);
            if(!Objects.equals(newValueId, oldValueId)) {
                DynamicObjectCollection entryEntities = getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                boolean hasNonEmptyPerson = entryEntities.stream()
                        .anyMatch(entry -> entry.getDynamicObject(PerfRankMgmtConstant.NCKD_PERSON) != null);
                if(hasNonEmptyPerson) {
                    // 直接弹出确认框，无需回滚
                    // 表单字段修改前交互
                    this.getView().showConfirm(
                            "确认修改【所属组织】吗？",
                            "请注意：修改【所属组织】会导致排名单元范围变化会清空现有排名名单。您需要在之后重新生成。确认要修改吗？",
                            MessageBoxOptions.OKCancel,
                            ConfirmTypes.Delete,
                            new ConfirmCallBackListener(PerfRankMgmtConstant.NCKD_ADMINORG, this)
                    );
                }
            }
        }
    }




    @Override
    public void propertyChanged(PropertyChangedArgs e) {
        String name = e.getProperty().getName();
        if(Stream.of(PerfRankMgmtConstant.NCKD_ISRANKING, PerfRankMgmtConstant.NCKD_APPRAISALRESULT,
                        PerfRankMgmtConstant.NCKD_ALLOWANCERANK, PerfRankMgmtConstant.NCKD_POSTALLOWANCE,
                        PerfRankMgmtConstant.NCKD_TOPRANK)
                .anyMatch(prop -> prop.equalsIgnoreCase(name))){
            //排名信息变化计算排名数
//            calcRankCount();
        }else if(FormConstant.NCKD_PERSON.equalsIgnoreCase(name)){
            //变更或选择人员重新获取是否享受职位津贴
            ChangeData[] changeSet = e.getChangeSet();
            Object newValue = changeSet[0].getNewValue();
            Object oldValue = changeSet[0].getOldValue();
            if(newValue != null && !Objects.equals(newValue, oldValue)) {
                DynamicObject newPerson = ConvertUtil.toDynamicObject(newValue);
                long newValueId = newPerson.getLong(FormConstant.ID_KEY);
                Date now = new Date();
                Map<Long, Boolean> entitledToAllowance = isEntitledToAllowance(Collections.singletonList(newValueId), now);
                boolean hasAllowance = entitledToAllowance.get(newValueId);
                this.getModel().setValue(PerfRankMgmtConstant.NCKD_POSTALLOWANCE, hasAllowance,changeSet[0].getRowIndex());
                this.getView().updateView(PerfRankMgmtConstant.NCKD_POSTALLOWANCE,changeSet[0].getRowIndex());
            }
        }else if(PerfRankMgmtConstant.NCKD_TOPRANKS.equalsIgnoreCase(name)){
            //输入总排名
            ChangeData[] changeSet = e.getChangeSet();
            Object newValue = changeSet[0].getNewValue();
            Object oldValue = changeSet[0].getOldValue();
//            优秀人数、基本合格人数、不合格人数
            if(!Objects.equals(newValue, oldValue)) {
                calculateExpectedCount(ConvertUtil.toInt(newValue, 0));
            }
        }

    }

    private void calculateExpectedCount(int totalCount) {
        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, PerfRankMgmtConstant.NCKD_RATIO)
                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT}, FormConstant.NUMBER_KEY);
        DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.RANKRATIOCONF_ENTITYID, queryFieldBuilder.buildSelect(), null);
        if(query.isEmpty()){
            this.getView().showTipNotification("未配置排名比例信息");
            return;
        }
        Map<String, BigDecimal> appraisalResultRatioMap = new HashMap<>();
        query.forEach(dynamicObject -> {
            String key = dynamicObject.getString(String.join(".", FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
            BigDecimal value = dynamicObject.getBigDecimal(String.join(".", FormConstant.NCKD_ENTRYENTITY, PerfRankMgmtConstant.NCKD_RATIO));
            appraisalResultRatioMap.put(key, value);
        });

        // 获取配置比例
        BigDecimal excellentRatio = appraisalResultRatioMap.get(AppraisalResultEnum.EXCELLENT.getCode());
        BigDecimal qualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.QUALIFIED.getCode());
        BigDecimal basicallyQualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.BASICALLY_QUALIFIED.getCode());
        BigDecimal unQualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.UN_QUALIFIED.getCode());

        // 计算各等级的理论人数（四舍五入）
        int expectedExcellent = calculateExpectedCount(totalCount, excellentRatio);
        int expectedQualified = calculateExpectedCount(totalCount, qualifiedRatio);
        int expectedBasic = calculateExpectedCount(totalCount, basicallyQualifiedRatio);
        int expectedFail = calculateExpectedCount(totalCount, unQualifiedRatio);

        this.getModel().setValue(PerfRankMgmtConstant.NCKD_EXCELLENTS, expectedExcellent);
//                this.getModel().setValue(PerfRankMgmtConstant.NCKD_BASICS, expectedQualified);
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_BASICS, expectedBasic);
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_FAILS, expectedFail);
    }

    /**
     * 计算理论人数（四舍五入）
     */
    private int calculateExpectedCount(int totalCount, BigDecimal ratio) {
        // 将百分比转换为小数进行计算
        BigDecimal decimalRatio = ratio.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
        BigDecimal expected = decimalRatio.multiply(BigDecimal.valueOf(totalCount));
        return expected.setScale(0, RoundingMode.HALF_UP).intValue();
    }

    @Override
    public void beforeImportEntry(BeforeImportEntryEventArgs e) {
        super.beforeImportEntry(e);
    }

    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        FormOperate operate = (FormOperate) args.getSource();
        String itemKey = operate.getOperateKey();
        if(PerfRankMgmtConstant.GETRANKLIST_OP.equalsIgnoreCase(itemKey)) {
            DynamicObject adminOrg = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(FormConstant.NCKD_ADMINORG));
            if(adminOrg == null) {
                this.getView().showTipNotification("请先选择“所属组织”");
                args.setCancel(true);
                return;
            }
            int theYear = ConvertUtil.toInt(this.getModel().getValue(PerfRankMgmtConstant.NCKD_THEYEAR));
            if(theYear <= 0){
                this.getView().showTipNotification("请先填写“年份”");
                args.setCancel(true);
                return;
            }

            RefObject<String> afterConfirm = new RefObject<>();
            if (!operate.getOption().tryGetVariableValue("afterConfirm", afterConfirm)) {
                //判断是否已获取过名单，如获取过再获取提示用户数据会丢失
                DynamicObjectCollection entry = this.getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                boolean isGetRank = false;
                if (!entry.isEmpty()) {
                    for (DynamicObject dynamicObject : entry) {
                        String rankSource = dynamicObject.getString(PerfRankMgmtConstant.NCKD_RANKSOURCE);
                        if (EnableEnum.NO.getCode().equals(rankSource)) {
                            isGetRank = true;
                            break;
                        }
                    }
                }
                if (isGetRank) {
                    // 取消当前操作，等待用户确认
                    args.setCancel(true);
                    //询问对话，交互
                    this.getView().showConfirm(
                            "已获取过排名名单了，重新获取将会覆盖（系统生成部分）现有人员名单是否继续操作？",
                            MessageBoxOptions.OKCancel,
                            ConfirmTypes.Default,
                            new ConfirmCallBackListener(CALLBACK_ID, this)
                    );
                }
            }
        } else if(Arrays.asList(FormConstant.SAVE_OP, FormConstant.SUBMIT_OP).contains(itemKey)){
            //保存或提交先计算一遍
            Integer step = ConvertUtil.toInt(this.getModel().getValue(PerfRankMgmtConstant.NCKD_STEP),0);
            if(step == 0) {
                calcRankCount();
            }
            IPageCache pageCache = this.getView().getPageCache();
            if(pageCache.get("removedEntries") != null && ConvertUtil.toBoolean(pageCache.get("removedEntries"))){
                //告诉OP需要加载被删除的分录（不参与排名）
                FormOperate formOperate = (FormOperate) args.getSource();
                formOperate.getOption().setVariableValue("removedEntries", "true");
            }



        } else if(FormConstant.DELETEENTRY_OP.equalsIgnoreCase(itemKey)){
            //校验人员考评，若考评周期已结束，则禁止删除。
            EntryGrid entryGrid = getView().getControl(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
            if (entryGrid != null) {
                Integer theYear = ConvertUtil.toInt(this.getModel().getValue(PerfRankMgmtConstant.NCKD_THEYEAR));
                LocalDate startDate = LocalDate.of(theYear, 1, 1);
                // 获取选中行索引数组
                int[] selectedRows = entryGrid.getSelectRows();
                List<Long> personIds = new ArrayList<>();
                if (selectedRows.length > 0) {
                    for (int rowIndex : selectedRows) {
                        DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                        DynamicObject rowData = entryEntity.get(rowIndex);
                        DynamicObject person = rowData.getDynamicObject(FormConstant.NCKD_PERSON);
                        if(person != null) {
                            long personId = person.getLong(FormConstant.ID_KEY);
                            personIds.add(personId);
                        }
                    }

                    if(!personIds.isEmpty()){
                        DynamicObject[] byDate = getByDate(DateUtil.toDate(startDate), personIds);
                        for (DynamicObject dynamicObject : byDate) {
                            String theStatus = dynamicObject.getString(PerfRankMgmtConstant.NCKD_THESTATUS);
                            DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
                            if(!EnableEnum.YES.getCode().equals(theStatus)){
                                DynamicObjectCollection entryList = dynamicObject.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFMANAGERENTRY);
                                for (DynamicObject object : entryList) {
                                    LocalDateTime appraisalYear = DateUtil.toLocalDateTime(object.getDate(PerfRankMgmtConstant.NCKD_APPRAISALYEAR));
                                    int year = appraisalYear.getYear();
                                    if(year == theYear){
                                        this.getView().showTipNotification(StrFormatter.format("所选人员【{}】考评周期【{}】，不能删除",person.getString(FormConstant.NAME_KEY),"2".equals(theStatus) ? "已锁定":"已结束"));
                                        args.setCancel(true);
                                    }
                                }

                            }
                        }
                    }
                }
            }
        }
    }


    /**
     * 根据日期查询范围内的考核周期
     * 查询逻辑说明：
     * 1. 开始时间条件：考核周期的开始年份(NCKD_BEGINYEAR)必须小于等于指定日期
     * 2. 结束时间条件：优先使用实际结束年份(NCKD_ACTENDYEAR)，如果为空则使用计划结束年份(NCKD_ENDYEAR)
     * 3. 结束时间必须大于等于指定日期
     * 4. 即查找满足 "NCKD_BEGINYEAR <= date <= (NCKD_ACTENDYEAR为空时取NCKD_ENDYEAR)" 条件的考核周期
     *
     * @param date      指定查询日期
     * @param personIds 人员ID集合
     * @return 符合条件的考核周期数组
     * @author W.Y.C
     * @date 2025/11/4 17:06
     */
    public static DynamicObject[] getByDate(Date date, Collection<Long> personIds) {
        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                .add(FormConstant.ID_KEY)
                .addIdNumberName(FormConstant.NCKD_PERSON)
                .add(PerfRankMgmtConstant.NCKD_THESTATUS)
                .addGroup(new String[]{PerfRankMgmtConstant.NCKD_PERFMANAGERENTRY},
                        PerfRankMgmtConstant.NCKD_APPRAISALRESULT,
                        PerfRankMgmtConstant.NCKD_APPRAISALYEAR,
                        PerfRankMgmtConstant.NCKD_ISALLRANKSOURCE);

        // 构造查询条件：日期在[NCKD_BEGINYEAR, NCKD_ENDYEAR]范围内
        // 考虑到NCKD_ACTENDYEAR可能为空，优先使用NCKD_ACTENDYEAR作为结束时间
        QFilter filter = new QFilter(PerfRankMgmtConstant.NCKD_BEGINYEAR, QCP.less_equals, date)
                .and(new QFilter(PerfRankMgmtConstant.NCKD_PERSON, QCP.in, personIds));

        // 添加结束时间判断逻辑
        QFilter endDateFilter = new QFilter(PerfRankMgmtConstant.NCKD_ACTENDYEAR, QCP.large_equals, date)
                .or(new QFilter(PerfRankMgmtConstant.NCKD_ACTENDYEAR, QCP.is_null, null)
                        .and(new QFilter(PerfRankMgmtConstant.NCKD_ENDYEAR, QCP.large_equals, date)));

        filter.and(endDateFilter);

        return BusinessDataServiceHelper.load(PerfRankMgmtConstant.PERFMANAGER_ENTITYID,
                queryFieldBuilder.buildSelect(), new QFilter[]{filter});
    }

    @Override
    public void beforeDeleteRow(BeforeDeleteRowEventArgs e) {
        super.beforeDeleteRow(e);
    }

    @Override
    public void confirmCallBack(MessageBoxClosedEvent evt) {
        super.confirmCallBack(evt);
        if (CALLBACK_ID.equals(evt.getCallBackId())) {
            if (evt.getResult() == MessageBoxResult.Yes) {
                // 用户选择“是”，继续执行业务逻辑
                OperateOption option = OperateOption.create();
                option.setVariableValue("afterConfirm", "true");
                this.getView().invokeOperation(PerfRankMgmtConstant.GETRANKLIST_OP,option);
            } else {
                // 用户选择“否”，中断操作
                this.getView().showTipNotification("操作已取消");
            }
        }else if(PerfRankMgmtConstant.NCKD_ADMINORG.equalsIgnoreCase(evt.getCallBackId())){
            // 用户确认：允许修改继续，并清空分录
            if (evt.getResult() == MessageBoxResult.Yes) {
                DynamicObjectCollection entryEntities = getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                entryEntities.clear();
//                getModel().updateEntryCache(entryEntities);
                getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
            }
        }else if("update".equalsIgnoreCase(evt.getCallBackId())){
            if (evt.getResult() == MessageBoxResult.Yes) {
                OperationResult operationResult = this.getView().invokeOperation(FormConstant.SAVE_OP);
                if (operationResult != null && operationResult.isSuccess()) {

                    String stepValueStr = this.getPageCache().get("stepValue");
                    if (StringUtils.isNotBlank(stepValueStr)) {
                        int stepValue = ConvertUtil.toInt(stepValueStr);
                        update(stepValue);
                    }
                    DynamicObject dataEntity = this.getModel().getDataEntity(true);
                    dataEntity.getDataEntityState().setFromDatabase( true);
                    DynamicObjectCollection dynamicObjectCollection = dataEntity.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                    for (DynamicObject dynamicObject : dynamicObjectCollection) {
                        dynamicObject.getDataEntityState().setFromDatabase( true);
                    }
                }
            }
        }
    }



    @Override
    public void afterDoOperation(@NotNull AfterDoOperationEventArgs afterDoOperationEventArgs) {
        String itemKey = afterDoOperationEventArgs.getOperateKey();
        if(PerfRankMgmtConstant.GETRANKLIST_OP.equalsIgnoreCase(itemKey)){
            /*IBillView billView = (IBillView)this.getView();
            //判断单据是否已保存
            boolean isFormDb = billView.getModel().getDataEntity().getDataEntityState().getFromDatabase();
            // 获取修改但还没保存的字段
            DynamicObject dataEntity = this.getModel().getDataEntity(true);
            List<IDataEntityProperty> iDataEntityProperties = dataEntity.getDataEntityState().GetDirtyProperties();
            boolean hasAdminOrgId = iDataEntityProperties.stream()
                    .anyMatch(property -> property.getName().equalsIgnoreCase(FormConstant.NCKD_ADMINORG + "_" + FormConstant.ID_KEY));
            if (!isFormDb) {
                billView.showTipNotification("请保存后再获取排名名单");
            } else if(hasAdminOrgId){
                billView.showTipNotification("由于您修改了【所属组织】但还没有保存，请保存之后在获取排名名单");
            }else{*/
            IDataModel model = this.getModel();
            DynamicObject adminOrg = ConvertUtil.toDynamicObjectOrNull(model.getValue(FormConstant.NCKD_ADMINORG));
            int theYear = ConvertUtil.toInt(model.getValue(PerfRankMgmtConstant.NCKD_THEYEAR));
            if(adminOrg != null) {
                Date targetDate = DateUtil.toDate(LocalDateTime.of(theYear, 12, 31, 23, 59, 59));
                String structLongNumber = adminOrg.getString(FormConstant.STRUCTLONGNUMBER);
                //查询所选组织下的人员
                //覆盖人员范围为：根据在职人员花名册，排名单元的所属组织和年度的上年度12月31日还在该所属组织的人员（不含岗位性质大类为离岗），其中含上挂人员（任职经历的任职类型为“上挂”）和在本所属组织待满183天的人员。取以下条件的并集
                //顺序1、上年度12月31日，任职状态为在岗，且任职经历的任职类型为全职任职的人员（（不含工作性质大类为离岗））
                //顺序2、上年度12月31日，任职状态为在岗，且任职经历的任职类型为“上挂”
                //顺序3：上年度12月31日，任职状态为在岗，且任职经历的任职类型为全职任职但是在本组织待满183天的人员
                //（例如说，12月31日那一天在B组织任职，但是在A组织待满183天，应该同时出现在A组织和B组织的排名单元里面，且默认A组织为参与排名，B组织为不参与排名）
                QFilter qFilter = new QFilter(String.join(".",FormConstant.ADMINORG, FormConstant.STRUCTLONGNUMBER), QCP.like, structLongNumber + "%")
                        .and(FormConstant.STARTDATE, QCP.less_equals, targetDate)
                        .and(FormConstant.ENDDATE, QCP.large_equals, targetDate)
                        //任职类型：上挂全职任职
                        .and(String.join( ".", FormConstant.POSTYPE, FormConstant.NUMBER_KEY), QCP.in,new String[]{"JTCC_1002", "1010_S"});

                //在职人员
                qFilter.and(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS, FormConstant.IS_HIRED), QCP.equals, EnableEnum.YES.getCode());
                QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                        .add(FormConstant.ID_KEY)
                        .add(FormConstant.STARTDATE)
                        //用工关系状态.编码（1005_S	在职-试用中、1010_S	在职、1020_S	离职、1030_S	已退休），istrial：是否试用，ishired：是否在职
                        .addGroup(new String[]{FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS}, FormConstant.NUMBER_KEY, FormConstant.NAME_KEY, FormConstant.IS_TRIAL, FormConstant.IS_HIRED)
                        //任职状态分类（1010_S：在岗，1030_S：不在岗）
                        .addIdNumberName(FormConstant.POS_STATUS, FormConstant.POST_STATE_CLS)
                        //入职日期
                        .addGroup(new String[]{FormConstant.HRPI_EMPENTREL}, FormConstant.ENTRYDATE)
                        //职务级别
                        .addGroup(new String[]{FormConstant.NCKD_HRPI_PARTYPOSH, FormConstant.NCKD_POSGRADE}, FormConstant.NAME_KEY, FormConstant.NUMBER_KEY, FormConstant.NCKD_SORTNUM)
                        .addGroup(new String[]{FormConstant.EMPLOYEE_KEY}, FormConstant.ID_KEY, FormConstant.NAME_KEY, FormConstant.EMP_NUMBER_KEY)
                        //工作性质大类
                        .addIdNumberName(FormConstant.NCKD_HBSS_WORKNATURE,FormConstant.NCKD_JOBTJOBTYPMAIN)
                        .orderDesc(FormConstant.STARTDATE);

                // -------------------------------- 1、查询组织下的在职人员 --------------------------------
                QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("personfilequery");
                DynamicObjectCollection personList = HRQueryEntityHelper.getInstance().getQueryDyoColl(queryEntityType, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, queryFieldBuilder.buildOrder());
                //添加分录
                DynamicObjectCollection entryEntityCols = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                //根据条件删除分录

                // -------------------------------- 2、删除系统生成部分人员 --------------------------------
                //删除系统生成部分人员
                entryEntityCols.removeIf(obj -> EnableEnum.NO.getCode().equals(obj.getString(PerfRankMgmtConstant.NCKD_RANKSOURCE)));

                List<Long> personIds = personList.stream()
                        .map(person -> person.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)))
                        .collect(Collectors.toList());
                //按员工ID分组，并只取开始日期最新的任职记录
                Map<Long, DynamicObject> groupedByEmployee = personList.stream()
                        .collect(Collectors.groupingBy(
                                person -> person.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
                                Collectors.collectingAndThen(
                                        Collectors.maxBy((p1, p2) -> {
                                            Date date1 = p1.getDate(FormConstant.STARTDATE);
                                            Date date2 = p2.getDate(FormConstant.STARTDATE);
                                            if (date1 == null && date2 == null) return 0;
                                            if (date1 == null) return -1;
                                            if (date2 == null) return 1;
                                            return date2.compareTo(date1); // 降序，取最新的
                                        }),
                                        optional -> optional.orElse(null)
                                )
                        ));
                if (!personIds.isEmpty()) {
                    Date now = new Date();
                    // -------------------------------- 3、获取人员是否享受职位津贴 --------------------------------
                    Map<Long, Boolean> entitledToAllowance = isEntitledToAllowance(personIds, now);

                    // -------------------------------- 4、加载数据到分录 --------------------------------
                    //预加载任职经历
                    List<Long> ids = personList.stream()
                            .map(person -> person.getLong(FormConstant.ID_KEY))
                            .collect(Collectors.toList());
                    MainEntityType empOrgRelEntityType = EntityMetadataCache.getDataEntityType(FormConstant.HRPI_EMPPOSORGREL);
                    DynamicObject[] empOrgRelArray = BusinessDataServiceHelper.load(ids.toArray(), empOrgRelEntityType);
                    Map<Long, DynamicObject> empOrgRelMap = Arrays.stream(empOrgRelArray)
                            .collect(Collectors.toMap(
                                    obj -> obj.getLong(FormConstant.ID_KEY),
                                    obj -> obj,
                                    (existing, replacement) -> existing
                            ));
                    Set<Long> addedPersonIds = new HashSet<>();
                    for (Map.Entry<Long, DynamicObject> personEntry : groupedByEmployee.entrySet()) {
                        DynamicObject person = personEntry.getValue();
                        long id = person.getLong(FormConstant.ID_KEY);
                        long personId = person.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
                        // 检查人员是否已经添加过，如果已存在则跳过
                        if (addedPersonIds.contains(personId)) {
                            continue;
                        }
                        DynamicObject empPosOrgRel = empOrgRelMap.get(id);
                        if(empPosOrgRel == null){
                            continue;
                        }
                        DynamicObject entryCol = entryEntityCols.addNew();
                        addedPersonIds.add(personId); // 记录已添加的人员ID
                        String personName = person.getString(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.NAME_KEY));
                        String personNumber = person.getString(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.EMP_NUMBER_KEY));


                        entryCol.set(FormConstant.NCKD_DEP, empPosOrgRel.get(FormConstant.ADMINORG));
                        entryCol.set(PositionStructureConstant.NCKD_POSITIONHR, empPosOrgRel.get(FormConstant.POSITION_KEY));


                        DynamicObjectType type = EntityMetadataCache.getDataEntityType(FormConstant.HRPI_EMPLOYEE);
                        DynamicObject personObj = (DynamicObject) type.createInstance();
                        personObj.set(FormConstant.ID_KEY, personId);
                        personObj.set(FormConstant.NAME_KEY, personName);
                        personObj.set(FormConstant.EMP_NUMBER_KEY, personNumber);
                        entryCol.set(FormConstant.NCKD_PERSON, personObj);




                        StringBuilder reason = new StringBuilder();
                        boolean participateRank = isParticipateRank(person, reason);
                        entryCol.set(PerfRankMgmtConstant.NCKD_ISRANKING, participateRank);
                        entryCol.set(PerfRankMgmtConstant.NCKD_EXCLUDERANKREASON, reason.toString());
                        entryCol.set(PerfRankMgmtConstant.NCKD_RANKSOURCE, EnableEnum.NO.getCode());
                        //判断是否有职位津贴
                        boolean hasAllowance = entitledToAllowance.get(personId);
                        entryCol.set(PerfRankMgmtConstant.NCKD_POSTALLOWANCE, hasAllowance);
                    }

                        /*this.getModel().updateEntryCache(entryEntityCols);
                        this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);*/


                        /*for (int i = 0; i < entryEntityCols.size(); i++) {
                            Boolean isRanking = ConvertUtil.toBoolean(this.getModel().getValue(PerfRankMgmtConstant.NCKD_ISRANKING, i));
                            if(isRanking){
                                this.getModel().setValue(PerfRankMgmtConstant.NCKD_ISRANKING, Boolean.FALSE,i);
                            }else{
                                this.getModel().setValue(PerfRankMgmtConstant.NCKD_ISRANKING, Boolean.TRUE,i);
                            }
                            this.getModel().setValue(PerfRankMgmtConstant.NCKD_ISRANKING, isRanking,i);
                            this.getView().updateView(PerfRankMgmtConstant.NCKD_ISRANKING,i);

                        }*/
                    this.getView().showSuccessNotification("名单获取完成");
                } else {
                    this.getView().showTipNotification("未获取到人员");
                }
            }
            /* }*/
        }else if(PerfRankMgmtConstant.SAVE_OP.equalsIgnoreCase(itemKey)){
            if(afterDoOperationEventArgs.getOperationResult() != null && afterDoOperationEventArgs.getOperationResult().isSuccess()){
                String wizadap = this.getView().getPageCache().get(FormConstant.NCKD_WIZARDAP);
                if(StringUtils.isBlank(wizadap) || "0".equals(wizadap)){
                    setStepStatus(0,Steps.FINISH);
                    setStepStatus(1,Steps.PROCESS);
                    this.getView().updateView(PerfRankMgmtConstant.NCKD_STEP);
                }else {
                    this.getView().showSuccessNotification("同步考核周期成功。");
                }
                //控制显示隐藏
                importResultStep();
            }
        }else if(FormConstant.DELETEENTRY_OP.equalsIgnoreCase(itemKey)){

        }
        if(Arrays.asList(FormConstant.DELETEENTRY_OP, PerfRankMgmtConstant.GETRANKLIST_OP).contains(itemKey)){
            sortEntry();
//            calcRankCount();
        }
        // this.getView().setStatus(OperationStatus.EDIT);
    }

/*    @Override
    public void getEntityType(GetEntityTypeEventArgs e) {
        super.getEntityType(e);

        MainEntityType originalEntityType = e.getOriginalEntityType();
        try {
            e.setNewEntityType((MainEntityType)originalEntityType.clone());
        } catch (CloneNotSupportedException ex) {
            throw new RuntimeException(ex);
        }
    }*/

    private void importResultStep() {
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_STEP,1);
        this.getView().updateView(PerfRankMgmtConstant.NCKD_STEP);
        this.getView().setVisible(false, FormConstant.NUMBER_KEY, PerfRankMgmtConstant.NCKD_GETRANKLIST,"nckd_advconbaritemap2","nckd_advconbaritemap3");
        this.getView().setVisible(true, PerfRankMgmtConstant.NCKD_TOPRANKS, PerfRankMgmtConstant.NCKD_ALLOWANCERANKS, PerfRankMgmtConstant.NCKD_FAILS,PerfRankMgmtConstant.NCKD_APPRAISALRESULT,
                PerfRankMgmtConstant.NCKD_POSTALLOWANCE,PerfRankMgmtConstant.NCKD_ALLOWANCERANK,PerfRankMgmtConstant.NCKD_BASICS, PerfRankMgmtConstant.NCKD_EXCELLENTS,PerfRankMgmtConstant.NCKD_TOPRANK, "nckd_advconbaritemap6","nckd_advconbaritemap");

        DynamicObjectCollection dbEntryEntity = null;
        Long id = ConvertUtil.toLong(this.getModel().getValue(FormConstant.ID_KEY));
        if (id != null && id > 0) {
            MainEntityType perfRankMgmtEntityType = EntityMetadataCache.getDataEntityType(PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID);
            DynamicObject dbPerfRankMgmt = BusinessDataServiceHelper.loadSingle(id, perfRankMgmtEntityType);
            dbEntryEntity = dbPerfRankMgmt.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        }

        DynamicObjectCollection entryEntityCols = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        // 暂存被过滤掉的条目而不是直接删除
        List<DynamicObject> removedEntries = entryEntityCols.stream()
                .filter(obj -> !obj.getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING))
                .collect(Collectors.toList());
        entryEntityCols.removeIf(obj -> !obj.getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING));
        if((dbEntryEntity != null && dbEntryEntity.size() != entryEntityCols.size()) || !removedEntries.isEmpty()){
            this.getView().getPageCache().put("removedEntries","true");
        }else{
            this.getView().getPageCache().put("removedEntries","false");
        }
        this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        this.getModel().updateEntryCache(entryEntityCols);

        DynamicObjectCollection entryEntity = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        for (int i = 0; i < entryEntity.size(); i++) {
            this.getView().setEnable(Boolean.FALSE, i, FormConstant.NCKD_PERSON);
            this.getView().setEnable(Boolean.FALSE, i, PerfRankMgmtConstant.NCKD_ISRANKING);
            this.getView().updateView(PerfRankMgmtConstant.NCKD_ISRANKING,i);
        }

    }

    private void generatePersonList() {

        IPageCache pageCache = this.getView().getPageCache();
        if(pageCache.get("removedEntries") != null && ConvertUtil.toBoolean(pageCache.get("removedEntries"))) {
            Long id = ConvertUtil.toLong(this.getModel().getValue(FormConstant.ID_KEY));
            if (id != null && id > 0) {

                MainEntityType perfRankMgmtEntityType = EntityMetadataCache.getDataEntityType(PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID);
                DynamicObject dbPerfRankMgmt = BusinessDataServiceHelper.loadSingle(id, perfRankMgmtEntityType);
                DynamicObjectCollection dynamicObjectCollection = dbPerfRankMgmt.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                List<DynamicObject> removedEntries = dynamicObjectCollection.stream()
                        .filter(obj -> !obj.getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING))
                        .collect(Collectors.toList());
                DynamicObjectCollection entryEntityCols = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);

                // 创建一个Set来存储entryEntityCols中已有的ID
                Set<Object> existingIds = entryEntityCols.stream()
                        .map(obj -> obj.get(FormConstant.ID_KEY))
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet());

                // 只添加不存在的项
                List<DynamicObject> entriesToAdd = removedEntries.stream()
                        .filter(obj -> {
                            Object idObj = obj.get(FormConstant.ID_KEY);
                            return idObj == null || !existingIds.contains(idObj);
                        })
                        .collect(Collectors.toList());

                entryEntityCols.addAll(entriesToAdd);

                this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                this.getModel().updateEntryCache(entryEntityCols);
                this.getView().getPageCache().put("removedEntries", "false");
            }
        }
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_STEP,0);
        this.getView().updateView(PerfRankMgmtConstant.NCKD_STEP);
        this.getView().setVisible(true, FormConstant.NUMBER_KEY, PerfRankMgmtConstant.NCKD_GETRANKLIST,"nckd_advconbaritemap2","nckd_advconbaritemap3");
        this.getView().setVisible(false, PerfRankMgmtConstant.NCKD_TOPRANKS, PerfRankMgmtConstant.NCKD_ALLOWANCERANKS, PerfRankMgmtConstant.NCKD_FAILS,PerfRankMgmtConstant.NCKD_APPRAISALRESULT,
                PerfRankMgmtConstant.NCKD_POSTALLOWANCE,PerfRankMgmtConstant.NCKD_ALLOWANCERANK,PerfRankMgmtConstant.NCKD_BASICS, PerfRankMgmtConstant.NCKD_EXCELLENTS,PerfRankMgmtConstant.NCKD_TOPRANK, "nckd_advconbaritemap6","nckd_advconbaritemap");
        DynamicObjectCollection entryEntity = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        for (int i = 0; i < entryEntity.size(); i++) {
            this.getView().setEnable(Boolean.TRUE, i, FormConstant.NCKD_PERSON);
            this.getView().setEnable(Boolean.TRUE, i, PerfRankMgmtConstant.NCKD_ISRANKING);
            Boolean aBoolean = ConvertUtil.toBoolean(this.getModel().getValue(PerfRankMgmtConstant.NCKD_ISRANKING, i), false);
            if(!aBoolean){
               /* this.getModel().setValue(PerfRankMgmtConstant.NCKD_ISRANKING, true, i);
                this.getModel().setValue(PerfRankMgmtConstant.NCKD_ISRANKING, false, i);*/
               /* DynamicObject dynamicObject = entryEntity.get(i);
                if(!entryEntity.get(i).getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING)){
                    dynamicObject.getDataEntityState().setFromDatabase( true);
                }*/
            }
            this.getView().updateView(PerfRankMgmtConstant.NCKD_ISRANKING,i);

        }
        this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        this.getModel().updateEntryCache(entryEntity);

    }

    /**
     * 判断人员是否享受职位津贴
     * @param personIds 人员ID列表
     * @param date 查询时间
     * @return Map<Long, Boolean> 人员ID到是否享受津贴的映射
     * @author W.Y.C
     * @date: 2025/10/21
     */
    private Map<Long, Boolean> isEntitledToAllowance(List<Long> personIds, Date date) {
        Map<Long, Boolean> result = new HashMap<>();

        if (personIds == null || personIds.isEmpty()) {
            return result;
        }

        //获取职位积分档案，用于判断是否有职级；职级大于0默认勾选“职位津贴”
        //属于技能序列、技术序列或职能序列，并且职级不为0。
        DynamicObject[] personPosFiles = PositionFileHelper.getNewestPersonPosFileByPerson(personIds.toArray(new Long[0]));
        Map<Long, Long> personJobLevelMap = Arrays.stream(personPosFiles)
                .filter(obj -> Stream.of(JobSeqEnum.TECHNICALS.getCode(), JobSeqEnum.FUNCTIONAL.getCode(), JobSeqEnum.SKILL.getCode())
                        .anyMatch(s -> s.equalsIgnoreCase(obj.getDynamicObject(PositionStructureConstant.NCKD_JOBSEQHR).getString(FormConstant.NUMBER_KEY))))
                .collect(Collectors.toMap(
                        obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)),
                        obj -> obj.getLong(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.JOBLEVELSEQ))
                ));

        // 查询管理人员职位津贴配置
        // 获取《管理人员职位津贴》，存在则默认勾选“职位津贴”

        QFilter managerAllowanceFilter = QFilterCommonHelper.getValidDateFilter(FormConstant.NCKD_STARTDATE,FormConstant.NCKD_ENDDATE)
                .and(FormConstant.NCKD_PERSON, QCP.in, personIds)
                .and(FormConstant.STATUS,QCP.in,Arrays.asList(StatusEnum.C.toString(),StatusEnum.B.toString()));

        DynamicObjectCollection managerAllowanceQuery = QueryServiceHelper.query(
                PositionStructureConstant.MANAGERALLOWANCE_ENTITYID,
                String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY),
                new QFilter[]{managerAllowanceFilter});

        Map<Long, Boolean> managerAllowanceMap = managerAllowanceQuery.stream()
                .collect(Collectors.toMap(
                        obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)),
                        obj -> Boolean.TRUE
                ));

        // 合并判断结果
        for (Long personId : personIds) {
            boolean hasAllowance = (personJobLevelMap.containsKey(personId) && personJobLevelMap.get(personId) > 0)
                    || managerAllowanceMap.containsKey(personId);
            result.put(personId, hasAllowance);
        }

        return result;
    }




    /**
     * 判断是否参与排名
     * @param isTrial 是否试用
     * @param entryDate 入职日期
     * @param posGradeSort 职务级别排序
     * @return: boolean
     * @author W.Y.C
     * @date: 2025/10/20 20:17
     */
    private boolean isParticipateRank(DynamicObject person,StringBuilder reason) {
        //是否试用
        boolean isTrial = person.getBoolean(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS, FormConstant.IS_TRIAL));
        //入职日期
        Date entryDate = person.getDate(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.ENTRYDATE));
        //职务级别编码
        Integer posGradeSort = null;
        if (person.containsProperty(FormConstant.NCKD_HRPI_PARTYPOSH)
                && person.containsProperty(String.join(".", FormConstant.NCKD_HRPI_PARTYPOSH, FormConstant.NCKD_POSGRADE))
                && person.containsProperty(String.join(".", FormConstant.NCKD_HRPI_PARTYPOSH, FormConstant.NCKD_POSGRADE, FormConstant.NCKD_SORTNUM))) {
            posGradeSort = person.getInt(String.join(".", FormConstant.NCKD_HRPI_PARTYPOSH, FormConstant.NCKD_POSGRADE, FormConstant.NCKD_SORTNUM));
        }
        //工作性质大类
        String jobtJobTypMain = null;
        if(person.containsProperty(String.join(".", FormConstant.NCKD_HBSS_WORKNATURE, FormConstant.NCKD_JOBTJOBTYPMAIN,FormConstant.NUMBER_KEY))){
            jobtJobTypMain = person.getString(String.join(".", FormConstant.NCKD_HBSS_WORKNATURE, FormConstant.NCKD_JOBTJOBTYPMAIN, FormConstant.NUMBER_KEY));
        }

        //获取入职天数
        long between = DateUtil.between(DateUtil.toLocalDateTime(entryDate), DateUtil.now(), ChronoUnit.DAYS);
        if(between < 183){
            //本所属组织未待满183天
            reason.append("本所属组织未待满183天");
            return false;
        }
        if(isTrial){
            reason.append("试用");
            return false;
        }
        if(posGradeSort != null && posGradeSort >= 115){
            reason.append("副科级及以上不参与");
            return false;
        }
        if(FormConstant.NCKD_JOBTJOBTYPMAIN_LEAVE_NUMBER.equalsIgnoreCase(jobtJobTypMain)){
            reason.append("工作性质大类为离岗");
            return false;
        }
        return true;
    }

    /**
     * 分录排序
     * @param
     * @return: void
     * @author W.Y.C
     * @date: 2025/10/21 16:00
     */
    private void sortEntry(){
        DynamicObjectCollection entryEntityCols = this.getModel().getDataEntity(true).getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
            if(!entryEntityCols.isEmpty()) {
            entryEntityCols.sort((o1, o2) -> {
                // 先按 NCKD_TOPRANK 排序，空值或 0 视为最大值（排在最后）
                Integer topRank1 = o1.getInt(PerfRankMgmtConstant.NCKD_TOPRANK);
                Integer topRank2 = o2.getInt(PerfRankMgmtConstant.NCKD_TOPRANK);
                if (topRank1 == 0) {
                    topRank1 = Integer.MAX_VALUE;
                }
                if (topRank2 == 0) {
                    topRank2 = Integer.MAX_VALUE;
                }

                int topRankCompare = topRank1.compareTo(topRank2);
                if (topRankCompare != 0) {
                    return topRankCompare;
                }

                // 再按 NCKD_ALLOWANCERANK 排序，空值或 0 视为最大值（排在最后）
                Integer allowanceRank1 = o1.getInt(PerfRankMgmtConstant.NCKD_ALLOWANCERANK);
                Integer allowanceRank2 = o2.getInt(PerfRankMgmtConstant.NCKD_ALLOWANCERANK);
                if (allowanceRank1 == 0) {
                    allowanceRank1 = Integer.MAX_VALUE;
                }
                if (allowanceRank2 == 0) {
                    allowanceRank2 = Integer.MAX_VALUE;
                }

                int allowanceRankCompare = allowanceRank1.compareTo(allowanceRank2);
                if (allowanceRankCompare != 0) {
                    return allowanceRankCompare;
                }

                // 最后按 NCKD_ISRANKING 排序，true 在前，false 在后
                Boolean isRanking1 = o1.getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING);
                Boolean isRanking2 = o2.getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING);
                return Boolean.compare(isRanking2, isRanking1);
            });
            this.getModel().updateEntryCache(entryEntityCols);
            this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        }
    }

    /**
     * 计算排名数
     * @return: void
     * @author W.Y.C
     * @date: 2025/10/21 16:30
     */
    private void calcRankCount(){
        DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        Object value = this.getModel().getValue(PerfRankMgmtConstant.NCKD_TOPRANKS);
        int totalRankCount = 0;
        int allowanceRankCount = 0;
        int failCount = 0;
        int basicCount = 0;
        int excellentCount = 0;

        for (DynamicObject entry : entryEntity) {
            DynamicObject person = entry.getDynamicObject(FormConstant.NCKD_PERSON);
            if(person != null) {
                //是否排名
                boolean isRanking = entry.getBoolean(PerfRankMgmtConstant.NCKD_ISRANKING);
                //是否R排名
                boolean postAllowance = entry.getBoolean(PerfRankMgmtConstant.NCKD_POSTALLOWANCE);
                //考核结果
                DynamicObject appraisalResult = entry.getDynamicObject(PerfRankMgmtConstant.NCKD_APPRAISALRESULT);

                if (isRanking) {
                    totalRankCount++;  // 统计参加排名人数

                    if (postAllowance) {
                        allowanceRankCount++;  // 统计参加R排名人数
                    }
                }

                if (appraisalResult != null) {
                    String appraisalResultNumber = appraisalResult.getString(FormConstant.NUMBER_KEY);
                    AppraisalResultEnum appraisalResultEnum = AppraisalResultEnum.getByCode(appraisalResultNumber);

                    if (appraisalResultEnum != null) {
                        switch (appraisalResultEnum) {
                            case EXCELLENT:
                                excellentCount++;
                                break;
                            case BASICALLY_QUALIFIED:
                                basicCount++;
                                break;
                            case UN_QUALIFIED:
                                failCount++;
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
        //参加排名总人数
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_TOPRANKS, totalRankCount);
        calculateExpectedCount(totalRankCount);
        /*//参加R排名人数
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_ALLOWANCERANKS, allowanceRankCount);
        //不合格人数
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_FAILS, failCount);
        //基本合格人数
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_BASICS, basicCount);
        //优秀人数
        this.getModel().setValue(PerfRankMgmtConstant.NCKD_EXCELLENTS, excellentCount);*/
    }


    /**
     * 设置步骤状态
     * @param step 步骤索引（从0开始）
     * @param stepStatus 步骤状态 {@link Steps}
     * @return: void
     * @author W.Y.C
     * @date: 2025/06/14 20:12
     */
    private void setStepStatus(int step,String stepStatus) {
        Wizard wizard = this.getControl(FormConstant.NCKD_WIZARDAP);
        Map<String, Object> currentStepMap = new HashMap<>();
        currentStepMap.put("currentStep", step);
        currentStepMap.put("currentStatus", stepStatus);
        wizard.setWizardCurrentStep(currentStepMap);
        this.getView().getPageCache().put(FormConstant.NCKD_WIZARDAP, step+"");
    }

    @Override
    public void update(StepEvent stepEvent) {
        BillShowParameter bsp = (BillShowParameter) this.getView().getFormShowParameter();
        boolean isUpdate = true;
        if (bsp.getStatus() == OperationStatus.EDIT) {
            DynamicObject dataEntity = this.getModel().getDataEntity(true);
            boolean hasChanged = false;
            List<IDataEntityProperty> iDataEntityProperties = dataEntity.getDataEntityState().GetDirtyProperties();
            ArrayList<String> fields = Lists.newArrayList(PerfRankMgmtConstant.NCKD_STEP,FormConstant.STATUS,FormConstant.USEORG_KEY,"useorg_id");
            for (IDataEntityProperty iDataEntityProperty : iDataEntityProperties) {
                if (fields.stream().noneMatch(ignoreField -> ignoreField.equalsIgnoreCase(iDataEntityProperty.getName()))) {
                    hasChanged = true;
                }
            }
            if(!hasChanged) {
                DynamicObjectCollection entityColl = dataEntity.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                for (DynamicObject dynamicObject : entityColl) {
                    List<IDataEntityProperty> iDataEntityProperties1 = dynamicObject.getDataEntityState().GetDirtyProperties();
                    List<String> name = iDataEntityProperties1.stream().map(IMetadata::getName).collect(Collectors.toList());

                    // 判断name中是否只有"seq"或FormConstant.NCKD_DEP或同时只存在这两个值
                    boolean onlyContainsSeqAndDep = !name.isEmpty() &&
                            name.stream().allMatch(ignoreField ->
                                    ignoreField.equalsIgnoreCase("seq") ||
                                            ignoreField.equalsIgnoreCase(FormConstant.NCKD_DEP)
                            );

                    if (!iDataEntityProperties1.isEmpty() && !onlyContainsSeqAndDep) {
                        hasChanged = true;
                    }
                }
            }
            if(hasChanged){
                isUpdate = false;
                this.getPageCache().put("stepValue", stepEvent.getValue()+"");
                this.getView().showConfirm(
                        "您当前有未保存的变更，切换步骤前需要保存。",
                        "✅ 点击“确认”将先保存当前信息，再切换步骤\n❌ 点击“取消”则放弃保存，停留在本步骤。\n\n是否需要继续？",
                        MessageBoxOptions.OKCancel,
                        ConfirmTypes.Delete,
                        new ConfirmCallBackListener("update", this));

            }
        }

        if (isUpdate) {
            update(stepEvent.getValue());
        }
    }

    private void update(int stepValue){
        Wizard wizard = this.getControl(FormConstant.NCKD_WIZARDAP);
        if (stepValue == 0) {
            generatePersonList();
            setStepStatus(0, Steps.PROCESS);

            //步骤为：导入考核结果时只显示参与排名的人员
//            applyRankingFilter(false);

        } else {
            //校验有没有保存
            DynamicObject dataEntity = this.getModel().getDataEntity(true);
            Object pkValue = dataEntity.getPkValue();
            if (pkValue == null || pkValue.toString().equals("0")) {
                this.getView().showTipNotification("请先生成名单并保存后再进行下一步！");
            } else {
                importResultStep();
                setStepStatus(1, Steps.PROCESS);


                //步骤为：导入考核结果时只显示参与排名的人员
//                applyRankingFilter(true);
            }
        }
        this.getView().updateView(PerfRankMgmtConstant.NCKD_STEP);
    }

    /**
     * 应用排名过滤器
     * @param onlyRankingParticipants 是否只显示参与排名的人员
     */
    private void applyRankingFilter(boolean onlyRankingParticipants) {
        EntryGrid entryGrid = this.getView().getControl(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
        List<SimpleFilterRow> filterRowList = new ArrayList<>(1);
        List<FilterValue> value = new ArrayList<>();
        
        if (onlyRankingParticipants) {
            // 只显示参与排名的人员 (nckd_isranking = 1)
            FilterValue rankingValue = new FilterValue();
            rankingValue.setValue("1");
            value.add(rankingValue);
        } else {
            // 显示参与和不参与排名的人员 (nckd_isranking in (0,1))
            FilterValue notRankingValue = new FilterValue();
            notRankingValue.setValue("0");
            value.add(notRankingValue);
            
            FilterValue rankingValue = new FilterValue();
            rankingValue.setValue("1");
            value.add(rankingValue);
        }
        
        filterRowList.add(new SimpleFilterRow("(", CompareTypeEnum.IN.getId(), "nckd_isranking", ")", "", value));
        //分录过滤
        entryGrid.getGridDataByDefaultFilterRow(filterRowList);
        this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
    }

}