package nckd.jxccl.hrmp.hbpm.plugin.form.hr;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import kd.bos.bill.BillOperationStatus;
import kd.bos.bill.BillShowParameter;
import kd.bos.bill.OperationStatus;
import kd.bos.consts.OrgViewTypeConst;
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.entity.LocaleString;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.IDataEntityType;
import kd.bos.dataentity.serialization.SerializationUtils;
import kd.bos.entity.BillEntityType;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.datamodel.ListSelectedRow;
import kd.bos.entity.datamodel.ListSelectedRowCollection;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.entity.operate.OperateOptionConst;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.property.BasedataProp;
import kd.bos.ext.hr.entity.property.PositionFieldProp;
import kd.bos.form.CloseCallBack;
import kd.bos.form.ConfirmCallBackListener;
import kd.bos.form.ConfirmTypes;
import kd.bos.form.IFormView;
import kd.bos.form.MessageBoxOptions;
import kd.bos.form.MessageBoxResult;
import kd.bos.form.ShowType;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.control.events.EntryGridBindDataListener;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.BeforeClosedEvent;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.events.ClosedCallBackEvent;
import kd.bos.form.events.LoadCustomControlMetasArgs;
import kd.bos.form.events.MessageBoxClosedEvent;
import kd.bos.form.field.BasedataEdit;
import kd.bos.form.field.events.BeforeBasedataSetValueEvent;
import kd.bos.form.field.events.BeforeBasedataSetValueListener;
import kd.bos.form.field.events.BeforeF7SelectEvent;
import kd.bos.form.field.events.BeforeF7SelectListener;
import kd.bos.form.operate.AbstractOperate;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.lang.Lang;
import kd.bos.list.ListShowParameter;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.mvc.bill.BillView;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.orm.util.CollectionUtils;
import kd.bos.permission.api.HasPermOrgResult;
import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
import kd.bos.servicehelper.model.PermissionStatus;
import kd.bos.servicehelper.permission.PermissionServiceHelper;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
import kd.hr.hbp.common.model.AuthorizedOrgResult;
import kd.hr.hbp.common.util.HRDateTimeUtils;
import kd.hr.hbp.common.util.HRDynamicObjectUtils;
import kd.hr.hbp.common.util.HRObjectUtils;
import kd.hr.hbp.common.util.HRStringUtils;
import kd.hr.hbp.common.util.concurrent.NullableConcurrentHashMap;
import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillAfterBindDataService;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillBeforeBindDataService;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillClosedCallBackService;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillConfirmCallBackService;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillPropertyChangedService;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
import org.apache.commons.lang3.time.DateUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

/**
 * 岗位申请单表单插件
 * @entity: nckd_positionbill
 * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchBillPlugin
 * @author: jtd
 * @date: 2025-10-25 13:38
 */
public class PositionBillFormPlugin extends AbstractFormPlugin implements BeforeF7SelectListener, EntryGridBindDataListener, BeforeBasedataSetValueListener {
    private static final Log LOG = LogFactory.getLog(PositionBillFormPlugin.class);
    private final Map<String, Map<?, DynamicObject>> baseDataCacheMap = new NullableConcurrentHashMap(3);

    @Override
    public void afterCreateNewData(EventObject e) {
        DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.ORG_KEY);
        if (org == null) {
            // 获取是否有查询权限
            HasPermOrgResult hrPermOrg = PermissionServiceHelper.getAllPermOrgs(RequestContext.get().getCurrUserId(), OrgViewTypeConst.HR_OD, PositionBillConstant.HOMS_APP, PositionBillConstant.HAOS_ADMINORGDETAIL_ENTITY, PermissionStatus.View, true);
            List<Long> hasPermOrgs = hrPermOrg.getHasPermOrgs();
            if (!Objects.isNull(hasPermOrgs) && hasPermOrgs.size() != 0) {
                if (hasPermOrgs.contains(RequestContext.get().getOrgId())) {
                    getModel().setValue(PositionBillConstant.ORG_KEY, RequestContext.get().getOrgId());
                } else {
                    getModel().setValue(PositionBillConstant.ORG_KEY, hasPermOrgs.get(0));
                }
            } else {
                LOG.error("PositionBillFormPlugin can not get any org");
            }
        }

        org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.ORG_KEY);
        if (org == null) {
            setBillNo(e);
        } else {
            long orgid = org.getLong(PositionBillConstant.ID_KEY);
            boolean cudeRule = CodeRuleServiceHelper.isExist(PositionBillConstant.NCKD_POSITIONBILL_ENTITY, getModel().getDataEntity(), String.valueOf(orgid));
            if (!cudeRule) {
                setBillNo(e);
            }
        }

    }

    private void setBillNo(EventObject e) {
        Map map = new HashMap();
        Map item = new HashMap();
        Map emptyTip = new HashMap();
        map.put("item", item);
        item.put("emptytip", emptyTip);
        Lang lang = Lang.get();
        emptyTip.put(lang.getLocale(), "");
        getView().updateControlMetadata(PositionBillConstant.BILL_NO_KEY, map);
        getModel().setValue(PositionBillConstant.BILL_NO_KEY, "");
        getView().setEnable(Boolean.TRUE, PositionBillConstant.BILL_NO_KEY);
        super.afterCreateNewData(e);
    }

    @Override
    public void loadCustomControlMetas(LoadCustomControlMetasArgs e) {
        super.loadCustomControlMetas(e);
        BillShowParameter billShowParameter = (BillShowParameter) e.getSource();
        LocaleString caption = billShowParameter.getFormConfig().getCaption();
        if (billShowParameter.getPkId() == null) {
            caption.setLocaleValue("岗位调整申请");
        } else {
            HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
            DynamicObject billObject = hrBaseServiceHelper.queryOne(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.BILL_NO_KEY), billShowParameter.getPkId());
            if (billObject != null) {
                caption.setLocaleValue(String.format(Locale.ROOT, "岗位调整申请-%s", billObject.getString(PositionBillConstant.BILL_NO_KEY)));
            }
        }

    }

    @Override
    public void beforeBindData(EventObject e) {
        super.beforeBindData(e);

        long startTime = System.currentTimeMillis();
        PositionBillBeforeBindDataService beforeBindDataService = new PositionBillBeforeBindDataService(getView());
        beforeBindDataService.beforeBindData(e);
        LOG.info(String.format(Locale.ROOT, "PositionBillFormPlugin beforeBindData() time cost is: %s", System.currentTimeMillis() - startTime));
    }

    @Override
    public void afterBindData(EventObject e) {
        super.afterBindData(e);

        long startTime = System.currentTimeMillis();
        PositionBillAfterBindDataService afterBindDataService = new PositionBillAfterBindDataService(getView());
        afterBindDataService.afterBindData();
        LOG.info(String.format(Locale.ROOT, "PositionBillFormPlugin afterBindData() time cost is: %s", System.currentTimeMillis() - startTime));
    }

    public void beforeBasedataSetValue(BeforeBasedataSetValueEvent beforeBasedataSetValueEvent) {
        Object value = beforeBasedataSetValueEvent.getValue();
        Object source = beforeBasedataSetValueEvent.getSource();
        if (value instanceof ListSelectedRowCollection && source instanceof BasedataEdit) {
            ListSelectedRowCollection rows = (ListSelectedRowCollection) value;
            BasedataEdit basedataEdit = (BasedataEdit) source;
            IDataEntityProperty property = basedataEdit.getProperty();
            if (property instanceof PositionFieldProp && basedataEdit.isF7MultipleSelect()) {
                String baseEntityId = ((BasedataProp) property).getBaseEntityId();
                HRBaseServiceHelper helper = new HRBaseServiceHelper(baseEntityId);
                DynamicObject[] baseDataDys = helper.loadDynamicObjectArray(rows.stream().map(ListSelectedRow::getPrimaryKeyValue).distinct().toArray());
                Map<Object, DynamicObject> baseDataDyMap = Maps.newHashMapWithExpectedSize(baseDataDys.length);

                for(DynamicObject positionDy : baseDataDys) {
                    baseDataDyMap.put(positionDy.getPkValue(), positionDy);
                }

                baseDataCacheMap.put(baseEntityId, baseDataDyMap);
            }
        }

    }

    @Override
    public void propertyChanged(PropertyChangedArgs e) {
        super.propertyChanged(e);

        PositionBillPropertyChangedService propertyChangedService = new PositionBillPropertyChangedService(getView(), baseDataCacheMap);
        propertyChangedService.setCloseCallBackPlugin(this);
        propertyChangedService.propertyChanged(e);
    }

    public void confirmCallBack(MessageBoxClosedEvent event) {
        super.confirmCallBack(event);

        PositionBillConfirmCallBackService confirmCallBackService = new PositionBillConfirmCallBackService(getView());
        confirmCallBackService.confirmCallBack(event);
    }

    @Override
    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
        super.closedCallBack(closedCallBackEvent);

        PositionBillClosedCallBackService closedCallBackService = new PositionBillClosedCallBackService(getView());
        closedCallBackService.closedCallBack(closedCallBackEvent);
    }

    @Override
    public void beforeClosed(BeforeClosedEvent e) {
        super.beforeClosed(e);

        String isCancelOverFlag = getView().getPageCache().get(PositionBillConstant.PC_ISCANCELOVER);
        if (HRStringUtils.isNotEmpty(isCancelOverFlag) && Boolean.TRUE.toString().equals(isCancelOverFlag)) {
            getModel().setDataChanged(false);
            getView().getPageCache().put(PositionBillConstant.PC_ISCANCELOVER, Boolean.FALSE.toString());
        } else {
            boolean hasEntryData = false;
            DynamicObject dataEntity = getModel().getDataEntity(Boolean.TRUE);

            for (PositionChangeTypeEnum changeTypeEnum : PositionChangeTypeEnum.values()) {
                DynamicObjectCollection entryDynColl = dataEntity.getDynamicObjectCollection(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY));
                hasEntryData = entryDynColl != null && entryDynColl.size() > 0;
                if (hasEntryData) {
                    break;
                }
            }

            HRBaseServiceHelper orgBatchChgBillHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
            long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
            QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, billId);
            boolean isExistFromDb = orgBatchChgBillHelper.isExists(idFilter);
            if (hasEntryData && !isExistFromDb) {
                e.setCancel(true);
                ConfirmCallBackListener confirmCallBacks = new ConfirmCallBackListener(PositionBillConstant.CB_CLOSE_BILL, this);
                Map<Integer, String> btnNameMaps = new HashMap();
                btnNameMaps.put(MessageBoxResult.Cancel.getValue(), "返回编辑");
                btnNameMaps.put(MessageBoxResult.Yes.getValue(), "直接退出");
                MessageBoxOptions options = MessageBoxOptions.OKCancel;
                String msg = "检测到您有更改内容，是否不保存直接退出？若直接退出，将丢失这些更改。";
                getView().showConfirm(msg, getModel().getChangeDesc(), options, ConfirmTypes.Save, confirmCallBacks, btnNameMaps);
            }

        }
    }

    private boolean executeSaveOperation(String operateKey, OperateOption operateOption) {
        OperateOption option = OperateOption.create();
        if (operateOption != null) {
            option.mergeValue(operateOption);
        }

        option.setVariableValue(OperateOptionConst.MUTEX_IGNORE_VALIDATION, Boolean.TRUE.toString());
        option.setVariableValue(PositionBillConstant.OP_OPERATE_KEY, operateKey);
        option.setVariableValue(OperateOptionConst.ISSHOWMESSAGE, Boolean.FALSE.toString());
        OperationResult saveOperationResult = getView().invokeOperation(PositionBillConstant.SAVE_NO_LOG_OP, option);
        if (!saveOperationResult.isSuccess()) {
            getView().showOperationResult(saveOperationResult);
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        super.beforeDoOperation(args);
        AbstractOperate operate = (AbstractOperate) args.getSource();
        String operateKey = operate.getOperateKey();
        OperateOption option = operate.getOption();
        if (getAllEntrySize() == 0) {
            option.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
            option.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
        }

        if (HRStringUtils.equals("import_multientry_hr", operate.getOperateKey())) {
            if (getModel().getValue(PositionBillConstant.ORG_KEY) == null) {
                getView().showTipNotification("请先填写组织体系管理组织。");
                args.setCancel(Boolean.TRUE);
                return;
            }

            DynamicObject dataEntity = getModel().getDataEntity(Boolean.TRUE);
            long billId = dataEntity.getLong(PositionBillConstant.ID_KEY);
            HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
            DynamicObject[] dynamicObjects = serviceHelper.query(PositionBillConstant.BILL_STATUS_KEY, new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.equals, billId)});
            if (dynamicObjects.length > 0 && !Sets.newHashSet(new String[]{RegBillStatusEnum.TEMPSTORAGE.getCode(), RegBillStatusEnum.WAITRESUBMIT.getCode()}).contains(dynamicObjects[0].getString(PositionBillConstant.BILL_STATUS_KEY))) {
                String auditStatus = dynamicObjects[0].getString(PositionBillConstant.BILL_STATUS_KEY);
                getView().showTipNotification(String.format(Locale.ROOT, "%s的单据不能导入。", RegBillStatusEnum.getName(auditStatus)));
                args.setCancel(Boolean.TRUE);
            }
        }

        if (HRStringUtils.equalsAny(operateKey, PositionBillConstant.SAVE_OP, PositionBillConstant.SUBMIT_OP, PositionBillConstant.SUBMITEFFECT_OP)) {
            PositionBillServiceHelper.setChangeDes(getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY), true);
            getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);

            if (HRStringUtils.equals(operateKey, PositionBillConstant.SUBMIT_OP) || HRStringUtils.equals(operateKey, PositionBillConstant.SUBMITEFFECT_OP)) {
                if (!executeSaveOperation(operateKey, operate.getOption())) {
                    args.setCancel(true);
                } else {
                    option.setVariableValue(OperateOptionConst.MUTEX_IGNORE_VALIDATION, Boolean.TRUE.toString());
                }
            }
        }

        if (PositionBillConstant.DELETE_ROWS_ADD_OP.equals(operateKey)) {
            EntryGrid entryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
            int[] selectRows = entryGrid.getSelectRows();
            operate.getOption().setVariableValue(PositionBillConstant.OP_ROW_INDEX, JSONObject.toJSONString(selectRows));
        }

        if (HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
            option.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
            option.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
        }

    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs eventArgs) {
        super.afterDoOperation(eventArgs);

        OperationStatus status = getView().getFormShowParameter().getStatus();
        if (HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
            ((BillView) getView()).setBillStatus(BillOperationStatus.EDIT);
            getView().getFormShowParameter().setStatus(OperationStatus.EDIT);
            ((BillShowParameter) getView().getFormShowParameter()).setBillStatus(BillOperationStatus.EDIT);
            String billStatus = ((BillEntityType) getModel().getDataEntityType()).getBillStatus();
            getModel().setValue(billStatus, RegBillStatusEnum.TEMPSTORAGE.getCode());
            getModel().setDataChanged(Boolean.FALSE);
        }

        String opKey = eventArgs.getOperateKey();
        if (!PositionBillConstant.VIEWFLOWCHART_OP.equals(opKey)) {
            OperationResult afterOperationResult = eventArgs.getOperationResult();
            if (afterOperationResult != null && !afterOperationResult.isSuccess()) {
                if (PositionBillConstant.SUBMIT_OP.equals(opKey)) {
                    afterSubmitError(afterOperationResult);
                }

            } else {
                switch (opKey) {
                    case PositionBillConstant.NEWENTRY_ADD_OP:
                        PositionBillServiceHelper.openViewForm(getView(), PositionBillConstant.ADD_TAG, getPluginName(), null);
                        break;
                    case PositionBillConstant.EDIT_ADD_OP:
                        openEditAddPage(status, getModel(), getView());
                        break;
                    case PositionBillConstant.EDIT_CHANGE_OP:
                        PositionBillServiceHelper.entryEntityMore(getModel(), getView(), PositionBillConstant.CHANGE_TAG, status, getPluginName());
                        break;
                    case PositionBillConstant.DELETE_ROWS_ADD_OP:
                    case PositionBillConstant.DELETE_ROWS_CHANGE_OP:
                        deleteRowsConfirm(opKey);
                        break;
                    case PositionBillConstant.SUBMIT_OP:
                        afterSubmit();
                }
            }

        }
    }

    private void afterSubmitError(OperationResult operationResult) {
        boolean needWfAssignPersons = operationResult.isNeedWfAssignPersons();
        List<IOperateInfo> allErrorOrValidateInfo = operationResult.getAllErrorOrValidateInfo();
        String errorMsg;
        if (allErrorOrValidateInfo.isEmpty()) {
            errorMsg = operationResult.getMessage();
        } else {
            errorMsg = operationResult.getAllErrorOrValidateInfo().get(0).getMessage();
        }

        if (errorMsg != null && !errorMsg.isEmpty() || !needWfAssignPersons) {
            String exist = "已存在";
            if (errorMsg != null && !errorMsg.contains(exist)) {
                getView().showErrorNotification(errorMsg);
            }

        }
    }

    private void afterSubmit() {
        LOG.info("afterDoSubmit:" + getModel().getDataEntity().get(PositionBillConstant.BILL_NO_KEY));
        LOG.info("afterDoSubmit getEntityId refresh:" + getView().getFormShowParameter().getAppId());
        if (HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
            LOG.info("afterDoSubmit refresh:" + getModel().getDataEntity().get(PositionBillConstant.BILL_NO_KEY));
            getView().getParentView().invokeOperation(PositionBillConstant.REFRESH_OP);
            getView().invokeOperation(PositionBillConstant.CLOSE_OP);
        } else {
            getView().updateView();
        }

    }

    private void deleteRowsConfirm(String callBackId) {
        long id = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
        HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
        QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, id);
        DynamicObject dyn = helper.queryOne(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.BILL_STATUS_KEY), new QFilter[]{idFilter});
        String billstatus;
        if (Objects.isNull(dyn)) {
            billstatus = RegBillStatusEnum.TEMPSTORAGE.getCode();
        } else {
            billstatus = dyn.getString(PositionBillConstant.BILL_STATUS_KEY);
        }

        boolean enableDeleteForUserPage = billstatus.equals(RegBillStatusEnum.TEMPSTORAGE.getCode()) || billstatus.equals(RegBillStatusEnum.WAITRESUBMIT.getCode());
        boolean enableDeleteForAuditPage = HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP) && billstatus.equals(RegBillStatusEnum.ALREADYSUBMIT.getCode());
        if (!enableDeleteForUserPage && !enableDeleteForAuditPage) {
            String auditStatusName = RegBillStatusEnum.getName(billstatus);
            getView().showErrorNotification(String.format("%s的单据不能删除调整明细。", auditStatusName));
        } else {
            EntryGrid strategyEntryGrid = getView().getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, callBackId.substring(callBackId.lastIndexOf("_")+1)));
            if (null == strategyEntryGrid) {
                getView().showTipNotification("请选中需要删除的行。");
            } else {
                int[] selectRows = strategyEntryGrid.getSelectRows();
                int length = selectRows.length;
                if (selectRows.length > 0) {
                    ConfirmCallBackListener deleteEntryCallBackListener = new ConfirmCallBackListener(callBackId, this);
                    getView().showConfirm(String.format("删除选中的数据后将无法恢复（选中条数：%s），确定要删除吗？", length), MessageBoxOptions.OKCancel, ConfirmTypes.Delete, deleteEntryCallBackListener);
                } else {
                    getView().showTipNotification("请选中需要操作的行。");
                }

            }
        }
    }

    private void openEditAddPage(OperationStatus status, IDataModel iDataModel, IFormView iFormView) {
        EntryGrid strategyEntryGrid = iFormView.getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
        int row = strategyEntryGrid.getEntryState().getFocusRow();
        DynamicObject addDy = iDataModel.getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row);
        Long adddyId = addDy.getLong(PositionBillConstant.ID_KEY);
        DynamicObject dataEntity = iDataModel.getDataEntity(true);
        DynamicObject dynamicObject = dataEntity.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row);
        Map map = HRDynamicObjectUtils.convertDynamicObjectToMap(dynamicObject);
        BillShowParameter formShowParameter = new BillShowParameter();
        formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
        formShowParameter.setCustomParam(PositionBillConstant.CP_POSITION_BSED, iDataModel.getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date) iDataModel.getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
        formShowParameter.setPkId(adddyId);
        formShowParameter.setStatus(status);
        formShowParameter.setCustomParam(PositionBillConstant.CP_BILLID, iDataModel.getDataEntity().getLong(PositionBillConstant.ID_KEY));
        if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
            formShowParameter.setHasRight(true);
        }

        if (!status.equals(OperationStatus.VIEW)) {
            formShowParameter.setCloseCallBack(new CloseCallBack(getPluginName(), PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY));
        }

        formShowParameter.setCustomParam(PositionBillConstant.CP_SELECTOBJECT, SerializationUtils.toJsonString(map));
        formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
        formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY, PositionBillServiceHelper.getThisBillAllValidateDataStr(dataEntity));
        formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_NEW_POSITION_NUMBERS_KEY, PositionBillServiceHelper.getThisBillPositionNumbersStr(dataEntity));
        iFormView.showForm(formShowParameter);
    }

    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);

        EntryGrid entryGrid = getControl(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);
        entryGrid.addDataBindListener(this);

        for(String registerBeforeF7Listener : getRegisterBeforeF7ListenerControlList()) {
            BasedataEdit basedataEdit = getControl(registerBeforeF7Listener);
            if (basedataEdit != null) {
                basedataEdit.setF7BatchFill(false);
                basedataEdit.addBeforeF7SelectListener(this);
                basedataEdit.addBeforeBasedataSetValueListener(this);
            }
        }
    }

    private List<String> getRegisterBeforeF7ListenerControlList() {
        return Arrays.asList(PositionBillConstant.NCKD_DISORG_KEY, String.join("_", PositionBillConstant.ORG_KEY, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_PARENT, PositionBillConstant.CHANGE_TAG));
    }

    @Override
    public void beforeF7Select(BeforeF7SelectEvent beforeF7SelectEvent) {
        String fieldKey = beforeF7SelectEvent.getProperty().getName();
        setFuzzySearchAuthFilter(beforeF7SelectEvent);
        replaceFormIdByFieldKey(beforeF7SelectEvent);
        if (PositionBillConstant.NCKD_DISORG_KEY.equals(fieldKey)) {
            beforeF7SelectEvent.getFormShowParameter().setCaption("签发组织");
            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ORG_KEY, QCP.equals, ((DynamicObject) getView().getModel().getValue(PositionBillConstant.ORG_KEY)).getLong(PositionBillConstant.ID_KEY)));
        } else {
            int rowIndex = beforeF7SelectEvent.getRow();
            String suffix = getSuffixByFieldKey(fieldKey);
            String entryName = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix);
            DynamicObjectCollection entryDynColl = getModel().getDataEntity(true).getDynamicObjectCollection(entryName);
            DynamicObject focusEntryDyn = entryDynColl.get(rowIndex);
            Date date = DateUtils.truncate(new Date(), 5);
            MainEntityType entityType = EntityMetadataCache.getDataEntityType(getView().getEntityId());
            IDataEntityProperty property = entityType.getAllFields().get(fieldKey);
            IDataEntityType parent = property.getParent();
            if (!checkOrgValue(beforeF7SelectEvent, property, parent)) {
                ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
                if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG))) {
                    showParameter.getCustomParams().put(PositionBillConstant.CP_SEARCHDATE, date);
                    PositionBillServiceHelper.filterF7Org(getView(), beforeF7SelectEvent, null);
                    setFilterByOrg(beforeF7SelectEvent);
                } else if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_PARENT, PositionBillConstant.CHANGE_TAG))) {
                    DynamicObject position = focusEntryDyn.getDynamicObject(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG));
                    PositionBillServiceHelper.setParentFilter(getView(), position, beforeF7SelectEvent);
                    beforeF7SelectEvent.getFormShowParameter().setCaption("上级岗位");
                    if (!HRObjectUtils.isEmpty(position)) {
                        // 过滤下级岗位
                        Date effDate = HRObjectUtils.isEmpty(getModel().getValue(PositionBillConstant.NCKD_EFFDT)) ? DateUtils.truncate(new Date(), 5) : (Date) getModel().getValue(PositionBillConstant.NCKD_EFFDT);
                        List<Long> positionIds = PositionBillServiceHelper.getPositionAndChildren(position.getLong(PositionBillConstant.BOID_KEY), effDate);
                        if (!positionIds.isEmpty()) {
                            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ID_KEY, QCP.not_in, positionIds));
                        }
                    }
                } else if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.CHANGE_TAG))) {
                    HasPermOrgResult permOrgResult = PermissionServiceHelper.getUserHasPermOrgs(RequestContext.get().getCurrUserId(), false);
                    if (!permOrgResult.hasAllOrgPerm()) {
                        List<Long> hasPermOrgs = permOrgResult.getHasPermOrgs();
                        beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ID_KEY, QCP.equals, hasPermOrgs));
                    }
                }
            }
        }
    }

    private boolean checkOrgValue(BeforeF7SelectEvent beforeF7SelectEvent, IDataEntityProperty property, IDataEntityType parent) {
        if (parent == null) {
            return false;
        } else if (parent.getName().equals(getView().getEntityId())) {
            return false;
        } else if (!getModel().getDataEntity().containsProperty(property.getParent().getName())) {
            return false;
        } else {
            DynamicObjectCollection dynamicObjectCollection = getModel().getDataEntity(true).getDynamicObjectCollection(parent.getName());
            DynamicObject dynamicObject = dynamicObjectCollection.get(beforeF7SelectEvent.getRow());
            String name = property.getName();
            String lineSuffix = name.substring(name.lastIndexOf("_"));
            String fieldKey = PositionBillServiceHelper.getNoLineSuffixProp(name, lineSuffix);
            if (PositionBillConstant.ORG_KEY.equals(fieldKey)) {
                return false;
            } else if (!dynamicObject.getDataEntityType().getProperties().containsKey(String.join(PositionBillConstant.ORG_KEY +lineSuffix))) {
                return false;
            } else {
                Boolean baseDataCtrl = BaseDataServiceHelper.checkBaseDataCtrl(((BasedataProp) property).getBaseEntityId());
                DynamicObject orgDy = dynamicObject.getDynamicObject(String.join(PositionBillConstant.ORG_KEY +lineSuffix));
                if (orgDy == null && baseDataCtrl) {
                    getView().showTipNotification("请先选择组织体系管理组织。");
                    beforeF7SelectEvent.setCancel(true);
                    return true;
                } else {
                    return false;
                }
            }
        }
    }

    private void setFilterByOrg(BeforeF7SelectEvent beforeF7SelectEvent) {
        List<Long> orgIdList = Collections.singletonList(((DynamicObject) getModel().getValue(PositionBillConstant.ORG_KEY)).getLong(PositionBillConstant.ID_KEY));
        if (CollectionUtils.isEmpty(orgIdList)) {
            beforeF7SelectEvent.getCustomQFilters().add(new QFilter("1", QCP.not_equals, 1));
        } else {
            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ORG_KEY, QCP.in, orgIdList));
        }
    }

    private void setFuzzySearchAuthFilter(BeforeF7SelectEvent beforeF7SelectEvent) {
        if ("getLookUpList".equals(beforeF7SelectEvent.getSourceMethod()) || "setItemByNumber".equals(beforeF7SelectEvent.getSourceMethod())) {
            AuthorizedOrgResult authorizedOrgResult = PositionBillServiceHelper.getOrgAuth(getView());
            if (authorizedOrgResult.isHasAllOrgPerm()) {
                return;
            }

            String fieldName = beforeF7SelectEvent.getProperty().getName();
            if (PositionBillConstant.NCKD_DISORG_KEY.equals(fieldName) || HRStringUtils.equals(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG), fieldName)) {
                List<Long> hasPermOrgList = authorizedOrgResult.getHasPermOrgs();
                beforeF7SelectEvent.getCustomQFilters().add(new QFilter(String.join(".", PositionBillConstant.ADMINORG, PositionBillConstant.BOID_KEY), QCP.in, hasPermOrgList));
            }
        }

    }

    private void replaceFormIdByFieldKey(BeforeF7SelectEvent beforeF7SelectEvent) {
        String fieldKey = beforeF7SelectEvent.getProperty().getName();
        if (HRStringUtils.equals(fieldKey, String.join(PositionBillConstant.NCKD_DISORG_KEY))) {
            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
            showParameter.setFormId(PositionBillConstant.HAOS_ORGBATCHTREELISTF7_ENTITY);
        }

        if (HRStringUtils.equalsAny(fieldKey, String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_PARENT, PositionBillConstant.CHANGE_TAG))) {
            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
            showParameter.setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
        }

    }

    private static String getSuffixByFieldKey(String fieldKey) {
        return fieldKey.substring(fieldKey.lastIndexOf("_") + 1);
    }

    private int getAllEntrySize() {
        return Arrays.stream(PositionChangeTypeEnum.values()).mapToInt(changeTypeEnum -> getModel().getEntryEntity(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY)).size()).sum();
    }
}
