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

import kd.bos.common.enums.EnableEnum;
import kd.bos.dataentity.entity.DataEntityState;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.dynamicobject.DynamicProperty;
import kd.bos.dataentity.serialization.SerializationUtils;
import kd.bos.dataentity.utils.ObjectUtils;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.property.BasedataProp;
import kd.bos.entity.property.MulBasedataProp;
import kd.bos.form.ConfirmCallBackListener;
import kd.bos.form.ConfirmTypes;
import kd.bos.form.IPageCache;
import kd.bos.form.MessageBoxOptions;
import kd.bos.form.MessageBoxResult;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.BeforeClosedEvent;
import kd.bos.form.events.MessageBoxClosedEvent;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.orm.ORM;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
import kd.hr.hbp.common.util.HRObjectUtils;
import kd.hr.hbp.common.util.HRStringUtils;
import nckd.jxccl.base.common.utils.PatternUtil;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PosBillEntryFastChgHelper;
import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;

import java.util.ArrayList;
import java.util.Date;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 岗位申请-岗位新设表单插件
 * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchDetailAddPlugin
 * @author: jtd
 * @date: 2025-11-05 15:32
 */
public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {

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

        getPageCache().put(PositionBillConstant.PC_PARAMSCHANGESETNUMBER, Boolean.FALSE.toString());
        DynamicObject positionDy = getModel().getDataEntity();
        long entityId = positionDy.getLong(PositionBillConstant.ID_KEY);
        if (entityId == 0L) {
            Long billId = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_BILLID);
            getModel().setValue(PositionBillConstant.NCKD_BILLID, billId);
            getPageCache().put(PositionBillConstant.PC_INITFLAG, Boolean.TRUE.toString());
        }

        if (!HRStringUtils.isEmpty(getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_PARENTID))) {
            getModel().setValue(PositionBillConstant.NCKD_PARENT, Long.valueOf(getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_PARENTID)));
        }

        // 设置生效时间
        Object positionBsedStr = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_POSITION_BSED);
        if (positionBsedStr != null) {
            long positionBsedTime = Long.parseLong(positionBsedStr.toString());
            getModel().setValue(PositionBillConstant.NCKD_BSED, new Date(positionBsedTime));
        } else {
            getModel().setValue(PositionBillConstant.NCKD_BSED, new Date());
        }

        getModel().setValue(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
        setLastTimeAddPositionInfo();
        // 设置岗位编码
        if (HRStringUtils.isEmpty(getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY))) {
            setPositionNumber(PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity()), true);
        } else {
            setPositionNumberEnable();
        }

        getPageCache().put(PositionBillConstant.PC_PARAMSCHANGESETNUMBER, Boolean.TRUE.toString());
        // 新增的时候生成岗位ID
        String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY);
        long positionId = getModel().getDataEntity().getLong(positionIdKey);
        if (positionId == 0L) {
            positionId = ORM.create().genLongId(PositionBillConstant.HBPM_POSITIONHR);
            getModel().setValue(positionIdKey, positionId);
        }

        getPageCache().put(PositionBillConstant.PC_MASTERORG, String.valueOf(positionDy.getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY))));
    }

    private void setPositionNumberEnable() {
        DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
        if (org == null) {
            getView().setEnable(Boolean.valueOf(false), PositionBillConstant.NUMBER_KEY);
            return;
        }
        long orgid = org.getLong(PositionBillConstant.ID_KEY);
        DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
        boolean cudeRule = CodeRuleServiceHelper.isExist(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgid));
        if (cudeRule && !CodeRuleServiceHelper.isModifiable(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(org.getLong(PositionBillConstant.ID_KEY)))) {
            getView().setEnable(false, PositionBillConstant.NUMBER_KEY);
            String orgNumber = getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY);
            if (HRStringUtils.isNotEmpty(orgNumber)) {
                getView().getPageCache().put(PositionBillConstant.PC_CODERULENUMBER, orgNumber);
                getView().getPageCache().put(PositionBillConstant.PC_NOTMODIFIABLE, Boolean.TRUE.toString());
            }
        }
    }

    private void setPositionNumber(DynamicObject positionHrDy, Boolean init) {
        DynamicObject dataEntity = getModel().getDataEntity();
        // 组织体系管理组织
        DynamicObject org = dataEntity.getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
        if (org == null) {
            getView().setEnable(Boolean.FALSE, PositionBillConstant.NUMBER_KEY);
            return;
        }

        String number = dataEntity.getString(PositionBillConstant.NUMBER_KEY);
        if (HRStringUtils.isNotEmpty(number) && !HRStringUtils.equals(number, getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER))) {
            return;
        }

        long orgid = org.getLong(PositionBillConstant.ID_KEY);
        boolean cudeRule = CodeRuleServiceHelper.isExist(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgid));
        if (cudeRule) {
            boolean fromDatabase = dataEntity.getDataEntityState().getFromDatabase();
            boolean modifiable = CodeRuleServiceHelper.isModifiable(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(org.getLong(PositionBillConstant.ID_KEY)));
            if (modifiable || fromDatabase && !init) {
                String positionNumber = CodeRuleServiceHelper.getNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(org.getLong(PositionBillConstant.ID_KEY)));
                HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
                QFilter qFilter = new QFilter(PositionBillConstant.NUMBER_KEY, QCP.equals, positionNumber);
                if (!hrBaseServiceHelper.isExists(qFilter)) {
                    getModel().setValue(PositionBillConstant.NUMBER_KEY, positionNumber);
                    getView().getPageCache().put(PositionBillConstant.PC_CODERULENUMBER, positionNumber);
                } else {
                    setPositionNumber(positionHrDy, init);
                }
            } else {
                getView().setEnable(Boolean.FALSE, PositionBillConstant.NUMBER_KEY);
            }
        } else {
            getModel().setValue(PositionBillConstant.NUMBER_KEY, null);
            getView().getPageCache().put(PositionBillConstant.PC_CODERULENUMBER, "");
            getView().setEnable(Boolean.TRUE, PositionBillConstant.NUMBER_KEY);
        }
    }

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

        String isCancelOverFlag = getView().getPageCache().get(PositionBillConstant.PC_ISCLOSE);
        if (HRStringUtils.isNotEmpty(isCancelOverFlag) && Boolean.TRUE.toString().equals(isCancelOverFlag)) {
            getModel().setDataChanged(false);
            getView().getPageCache().put(PositionBillConstant.PC_ISCLOSE, Boolean.FALSE.toString());
        } else {
            boolean dataChanged = getModel().getDataChanged();
            if (dataChanged) {
                event.setCancel(true);
                ConfirmCallBackListener confirmCallBacks = new ConfirmCallBackListener(String.join("_", PositionBillConstant.CLOSE_OP, PositionBillConstant.ADD_TAG), 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);
            } else {
                String codeRuleNumber = getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER);
                String notModifiable = getView().getPageCache().get(PositionBillConstant.PC_NOTMODIFIABLE);
                if (!StringUtils.isEmpty(codeRuleNumber) && !Boolean.TRUE.toString().equals(notModifiable)) {
                    DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
                    if (org == null) {
                        return;
                    }

                    String saveResult = getView().getPageCache().get(PositionBillConstant.PC_SAVERESULT);
                    if (!Boolean.TRUE.toString().equals(saveResult)) {
                        long orgId = org.getLong(PositionBillConstant.ID_KEY);
                        DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
                        CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgId), codeRuleNumber);
                    }
                }
            }
        }

    }

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

        // 设置岗位ID
        long positionId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
        if (positionId == 0L) {
            getModel().setValue(PositionBillConstant.ID_KEY, ORM.create().genLongId(PositionBillConstant.HBPM_POSITIONHR));
        }

        // 设置上级岗位变更前的数据到页面缓存中
        DynamicObject parentPosition = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_PARENT);
        if (parentPosition != null) {
            getView().getPageCache().put(PositionBillConstant.PC_BEFOREPARENTPOSITIONID, parentPosition.getString(PositionBillConstant.ID_KEY));
        }

        Object selectObject = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_SELECTOBJECT);
        if (selectObject != null) {
            String lineSuffix = "_"+PositionBillConstant.ADD_TAG;
            Map<String, Object> map = SerializationUtils.fromJsonString(selectObject.toString(), Map.class);
            Map<String, Object> noSuffixMap = map.entrySet().stream().collect(HashMap::new, (m, v) -> m.put(PositionBillServiceHelper.getNoLineSuffixProp(v.getKey(), lineSuffix), v.getValue()), HashMap::putAll);
            List<String> props = new ArrayList();

            for(String prop : noSuffixMap.keySet()) {
                if (PatternUtil.isExProperty(prop)) {
                    props.add(prop);
                }
            }

            // 获取分录要转换的键值，将单据分录字段转换转成分录页面字段
            Map<String, String> transKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
            transKeyMap.forEach((key, value) -> {
                noSuffixMap.put(value, noSuffixMap.get(key));
                noSuffixMap.remove(key);
                props.add(value);
                props.remove(key);
            });

            Stream<String> fields = Stream.of(props.toArray(new String[0]));
            fields.forEach((s) -> setValue(s, noSuffixMap.get(s)));
        }

        // 取消数据标哥标识
        getModel().setDataChanged(false);
    }

    private void setValue(String key, Object value) {
        if (getModel().getProperty(key) != null) {
            Class<?> propertyType = getModel().getDataEntityType().getProperty(key).getPropertyType();
            DynamicProperty dynamicProperty = getModel().getDataEntityType().getProperty(key);
            if (value != null) {
                if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof BasedataProp) {
                    // 岗位特殊处理
                    Object id = PositionBillConstant.NCKD_POSITION_KEY.equals(key) ? value : ((Map) value).get(PositionBillConstant.ID_KEY);
                    if (id != null && !HRStringUtils.equals(value.toString(), "0")) {
                        getModel().setValue(key, id);
                    }
                } else if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof MulBasedataProp && value instanceof List) {
                    MulBasedataProp property = (MulBasedataProp) getModel().getDataEntityType().getProperty(key);
                    DynamicObjectCollection dynamicObjectCollection = new DynamicObjectCollection();
                    HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(property.getBaseEntityId());
                    ((List) value).forEach((map) -> {
                        DynamicObject dy = new DynamicObject(property.getDynamicCollectionItemPropertyType());
                        dy.set(PositionBillConstant.FBASEDATAID_ID_KEY, ((Map) map).get(PositionBillConstant.FBASEDATAID_ID_KEY));
                        DynamicObject emptyDynamicObject = serviceHelper.generateEmptyDynamicObject();
                        emptyDynamicObject.set(PositionBillConstant.ID_KEY, ((Map) map).get(PositionBillConstant.FBASEDATAID_ID_KEY));
                        dy.set(PositionBillConstant.FBASEDATAID_KEY, emptyDynamicObject);
                        dynamicObjectCollection.add(dy);
                    });
                    getModel().setValue(key, !dynamicObjectCollection.isEmpty() ? dynamicObjectCollection : null);
                } else {
                    getModel().setValue(key, value);
                }

            }
        }
    }

    @Override
    public void propertyChanged(PropertyChangedArgs changedArgs) {
        String fieldKey = changedArgs.getProperty().getName();
        boolean isGetNumber = true;
        switch (fieldKey) {
            case PositionBillConstant.NCKD_ESTDATE:
                setEstablishmentDateToBsed((Date)changedArgs.getChangeSet()[0].getNewValue());
                break;
            case PositionBillConstant.NCKD_POSITION_KEY:
                break;
            case PositionBillConstant.NCKD_ORG_KEY:
                PosBillEntryFastChgHelper.orgPropertyChanged(changedArgs, getView(), this);
        }

        if (HRStringUtils.equals(Boolean.TRUE.toString(), getPageCache().get(PositionBillConstant.PC_PARAMSCHANGESETNUMBER)) && isGetNumber) {
            propertyChangedGetNumber(fieldKey, changedArgs.getChangeSet()[0].getOldValue());
        }

    }

    /**
     * 设置设立日期到生效日期
     * @param date
     */
    private void setEstablishmentDateToBsed(Date date) {
        if (date != null) {
            getModel().setValue(PositionBillConstant.NCKD_BSED, date);
            DynamicProperty property = getModel().getDataEntityType().getProperty(PositionBillConstant.NCKD_BSED);
            DataEntityState dataEntityState = getModel().getDataEntity().getDataEntityState();
            dataEntityState.setBizChanged(property.getOrdinal(), false);
        }
    }

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

        if (String.join("_", PositionBillConstant.CLOSE_OP, PositionBillConstant.ADD_TAG).equals(event.getCallBackId()) && event.getResult() != MessageBoxResult.Cancel) {
            String codeRuleNumber = getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER);
            if (!StringUtils.isEmpty(codeRuleNumber)) {
                DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
                if (HRObjectUtils.isEmpty(org)) {
                    return;
                }
                String saveResult = getView().getPageCache().get(PositionBillConstant.PC_SAVERESULT);
                if (!Boolean.TRUE.toString().equals(saveResult)) {
                    long orgId = org.getLong(PositionBillConstant.ID_KEY);
                    DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
                    CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgId), codeRuleNumber);
                }
            }

            getView().getPageCache().put(PositionBillConstant.PC_ISCLOSE, Boolean.TRUE.toString());
            getView().invokeOperation(PositionBillConstant.CLOSE_OP);
        } else if (PositionBillConstant.CB_CHG_ORG.equals(event.getCallBackId())) {
            if (event.getResult().getValue() == MessageBoxResult.Yes.getValue()) {
                getView().getPageCache().put(PositionBillConstant.PC_MASTERORG, String.valueOf(getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY))));
                getModel().beginInit();
                PosBillEntryFastChgHelper.cleanOrgBaseInfo(getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY)), getView());
                getModel().endInit();
            } else {
                Long masterOrgId = Long.valueOf(getPageCache().get(PositionBillConstant.PC_MASTERORG));
                getModel().beginInit();
                getModel().setValue(PositionBillConstant.NCKD_ORG_KEY, masterOrgId.equals(0L) ? null : masterOrgId);
                getView().updateView(PositionBillConstant.NCKD_ORG_KEY);
                getModel().endInit();
            }
        }
    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs eventArgs) {
        super.afterDoOperation(eventArgs);
        OperationResult result = eventArgs.getOperationResult();
        if (!ObjectUtils.isEmpty(result) && !result.isSuccess()) {
            return;
        }
        IPageCache parentPageCache = getView().getParentView().getPageCache();
        String operateKey = eventArgs.getOperateKey();
        if (HRStringUtils.equalsAny(operateKey, PositionBillConstant.SAVE_AND_NEW_OP, PositionBillConstant.SAVE_OP)) {
            String beforeParentPositionId = getView().getPageCache().get(PositionBillConstant.PC_BEFOREPARENTPOSITIONID);
            String addPositionParentChange = Boolean.FALSE.toString();
            DynamicObject parentPosition = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_PARENT);
            if (parentPosition != null) {
                String afterParentPositionId = parentPosition.getString(PositionBillConstant.ID_KEY);
                if (!HRStringUtils.equals(beforeParentPositionId, afterParentPositionId)) {
                    addPositionParentChange = Boolean.TRUE.toString();
                }
                parentPageCache.put(PositionBillConstant.PC_ADDPOSITIONPARENTCHANGE, addPositionParentChange);
                parentPageCache.put(PositionBillConstant.PC_PARENTID, afterParentPositionId);
            }
            Map<String, String> map = new HashMap<>();
            DynamicObject dataEntity = getModel().getDataEntity();
            map.put(PositionBillConstant.CP_POSITIONID, dataEntity.getString(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY)));
            map.put(PositionBillConstant.NAME_KEY, dataEntity.getString(PositionBillConstant.NAME_KEY));
            map.put(PositionBillConstant.ID_KEY, dataEntity.getString(PositionBillConstant.ID_KEY));
            getView().getPageCache().put(PositionBillConstant.PC_SAVERESULT, Boolean.TRUE.toString());
            getView().returnDataToParent(map);
        }

        if (HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_AND_NEW_OP)) {
            parentPageCache.put(PositionBillConstant.PC_LASTTIMEADDENTRYID, String.valueOf(getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY)));
        }
    }

    private void setLastTimeAddPositionInfo() {
        String positionIdStr = getView().getParentView().getPageCache().get(PositionBillConstant.PC_LASTTIMEADDENTRYID);
        if (!HRStringUtils.isEmpty(positionIdStr)) {
            Long lastTimeAddEntryId = Long.valueOf(positionIdStr);
            /*HRBaseServiceHelper billHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
            DynamicObject addPositionDy = billHelper.queryOne("", lastTimeAddEntryId);
            if (addPositionDy != null) {
                getModel().setValue();
            }*/

            getView().getParentView().getPageCache().remove(PositionBillConstant.PC_LASTTIMEADDENTRYID);
        }
    }

    private void propertyChangedGetNumber(String fieldKey, Object oldValue) {
        switch (fieldKey) {
            case PositionBillConstant.NCKD_POSITION_KEY:
                String codeRuleNumber = getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER);
                if (!StringUtils.isEmpty(codeRuleNumber)) {
                    DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
                    if (org == null) {
                        return;
                    }

                    long orgId = org.getLong(PositionBillConstant.ID_KEY);
                    recycleNumber(orgId, codeRuleNumber, Boolean.TRUE, fieldKey, oldValue);
                }

                setPositionNumber(PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity()), false);
            default:
        }
    }


    private void recycleNumber(Long orgId, String codeRuleNumber, Boolean paramsChg, String numberParams, Object numberParamsOb) {
        DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
        if (paramsChg) {
            if (positionHrDy.get(numberParams) instanceof DynamicObject && numberParamsOb instanceof Long) {
                String baseName = positionHrDy.getDynamicObject(numberParams).getDataEntityType().getName();
                HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(baseName);
                DynamicObject paramDy = hrBaseServiceHelper.loadSingle(numberParamsOb);
                positionHrDy.set(numberParams, paramDy);
            } else {
                positionHrDy.set(numberParams, numberParamsOb);
            }
        }

        String number = getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY);
        if (HRStringUtils.equals(number, codeRuleNumber)) {
            CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgId), codeRuleNumber);
        }

    }

}
