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

import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.EntityType;
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.EntryProp;
import kd.bos.form.MessageTypes;
import kd.bos.form.control.Control;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
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 nckd.jxccl.base.common.utils.QueryFieldBuilder;
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.PositionHRConstant;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 岗位分配表单插件
 * @entity: nckd_positionassign
 * @author: jtd
 * @date: 2026/1/5 09:40
 */
public class PositionAssignFormPlugin extends AbstractFormPlugin {

    /**
     * 获取岗位分配转换键值
     * @return 源字段: 目标字段
     */
    public static Map<String, String> getPosAssignTransKeyMap() {
        String selectFields = QueryFieldBuilder.create().add(PositionHRConstant.NUMBER_KEY).add(PositionHRConstant.NAME_KEY).buildSelect();
        DynamicObject[] transKeyDyos = HRBaseServiceHelper.create(PositionHRConstant.NCKD_POSASSIGN_TRANSKEY_ENTITY).queryOriginalArray(selectFields, null);
        Map<String, String> transKeyMap = Arrays.stream(transKeyDyos).collect(Collectors.toMap(
                transKeyDyo -> transKeyDyo.getString(PositionHRConstant.NUMBER_KEY),
                transKeyDyo -> transKeyDyo.getString(PositionHRConstant.NAME_KEY),
                (oldValue, newValue) -> newValue)
        );
        return transKeyMap;
    }

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

        Object selectedIds = getView().getFormShowParameter().getCustomParam(PositionHRConstant.SELECTED_IDS_CUSTOM_PARAM);
        if (selectedIds != null) {
            DynamicObject[] positionHrDyns = HRBaseServiceHelper.create(PositionHRConstant.HBPM_POSITIONHR).loadDynamicObjectArray(Arrays.stream(String.valueOf(selectedIds).split(",")).map(Long::valueOf).toArray());
            DynamicObjectCollection entryEntityDynColl = getModel().getDataEntity().getDynamicObjectCollection(PositionHRConstant.NCKD_ENTRYENTITY);
            // 获取岗位要转换的键值
            Map<String, String> posAssignTransKeyMap = getPosAssignTransKeyMap();
            Map<Long, Long> oriAdminOrgData = new HashMap<Long, Long>();
            for (DynamicObject positionHrDy : positionHrDyns) {
                DynamicObject entryEntityDy = entryEntityDynColl.addNew();
                HRDynamicObjectUtils.copy(positionHrDy, entryEntityDy, posAssignTransKeyMap);
                // 设置ID
                entryEntityDy.set(PositionHRConstant.ID_KEY, positionHrDy.getLong(PositionHRConstant.ID_KEY));
                // 设立日期
                entryEntityDy.set(PositionHRConstant.NCKD_ESTABLISHMENTDATE_KEY, HRDateTimeUtils.getNowDate());
                oriAdminOrgData.put(positionHrDy.getLong(PositionHRConstant.ID_KEY), positionHrDy.getLong(String.join(".", PositionHRConstant.ADMINORG, PositionHRConstant.ID_KEY)));
            }
            getView().updateView(PositionHRConstant.NCKD_ENTRYENTITY);

            getModel().setDataChanged(false);
        }
    }

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

        addClickListeners(PositionHRConstant.BTN_OK_OP);
    }

    @Override
    public void click(EventObject evt) {
        super.click(evt);

        String key = ((Control) evt.getSource()).getKey();
        if (HRStringUtils.equals(key, PositionHRConstant.BTN_OK_OP)) {
            Object[] positionIds = getModel().getDataEntity(true).getDynamicObjectCollection(PositionHRConstant.NCKD_ENTRYENTITY).stream().map(entryEntityDy -> entryEntityDy.getLong(PositionHRConstant.ID_KEY)).toArray();
            if (positionIds.length == 0) {
                getView().showMessage("没有数据可执行。");
            } else {
                DynamicObject[] positionDyns = HRBaseServiceHelper.create(PositionHRConstant.HBPM_POSITIONHR).loadDynamicObjectArray(positionIds);
                Map<Long, DynamicObject> positionDyMap = Arrays.stream(positionDyns).collect(Collectors.toMap(positionDy -> positionDy.getLong(PositionHRConstant.ID_KEY), Function.identity()));
                Boolean needSave = hasDataNeedSave(positionDyMap);
                if (needSave) {
                    confirm(positionDyMap);
                }
            }
        }
    }

    private Boolean hasDataNeedSave(Map<Long, DynamicObject> positionDyMap) {
        DynamicObjectCollection entryEntityDynColl = getModel().getDataEntity(true).getDynamicObjectCollection(PositionHRConstant.NCKD_ENTRYENTITY);
        // 获取分录名称
        EntryProp entryEntityProp = (EntryProp) getModel().getDataEntityType().getProperty(PositionHRConstant.NCKD_ENTRYENTITY);
        String entryEntityName = entryEntityProp.getDisplayName().getLocaleValue();
        String adminOrgName = entryEntityProp.getItemType().getProperties().get(PositionHRConstant.NCKD_ADMINORG).getDisplayName().getLocaleValue();

        List<String> errorMsgList = new ArrayList<String>();
        for (int i = 0; i < entryEntityDynColl.size(); i++) {
            DynamicObject entryEntityDy = entryEntityDynColl.get(i);
            Long oriAdminOrg = positionDyMap.get(entryEntityDy.getLong(PositionHRConstant.ID_KEY)).getLong(String.join(".", PositionHRConstant.ADMINORG, PositionHRConstant.ID_KEY));
            Long newAdminOrg = entryEntityDy.getLong(String.join(".", PositionHRConstant.NCKD_ADMINORG, PositionHRConstant.ID_KEY));
            // 判断行政组织是否发生变更
            if (oriAdminOrg.equals(newAdminOrg)) {
                errorMsgList.add(HRStringUtils.format("请变更“{}”第{}行：“{}”。", new Object[]{entryEntityName, i+1, adminOrgName}));
            }
        }

        if (!errorMsgList.isEmpty()) {
            getView().showMessage(null, String.join(System.lineSeparator(), errorMsgList), MessageTypes.Default);
            return false;
        }

        return true;
    }

    private void confirm(Map<Long, DynamicObject> positionDyMap) {
        DynamicObjectCollection entryEntityDyoColl = getModel().getDataEntity(true).getDynamicObjectCollection(PositionHRConstant.NCKD_ENTRYENTITY);
        // 获取所有单据体 属性
        Set<String> entryFields = ((EntityType) entryEntityDyoColl.getDynamicObjectType()).getFields().keySet();
        // 获取所有岗位属性
        Set<String> positionFields = PositionBillServiceHelper.getPositionAllFields();
        // 获取岗位要转换的键值，页面字段: 岗位字段
        Map<String, String> posAssignReverseTransKeyMap = getPosAssignTransKeyMap().entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (oldValue, newValue) -> newValue));
        List<DynamicObject> dataEntities = new ArrayList<DynamicObject>();
        HRBaseServiceHelper positionServiceHelper = HRBaseServiceHelper.create(PositionHRConstant.HBPM_POSITIONHR);
        String orgId = "";
        for (DynamicObject entryEntityDy : entryEntityDyoColl) {
            DynamicObject newDyo = positionServiceHelper.generateEmptyDynamicObject();
            DynamicObject dbPositionDy = positionDyMap.get(entryEntityDy.getLong(PositionHRConstant.ID_KEY));
            HRDynamicObjectUtils.copy(dbPositionDy, newDyo);

            // 设置 变更值到要新增的岗位数据中
            for (String entryField : entryFields) {
                String positionField = posAssignReverseTransKeyMap.getOrDefault(entryField, entryField);
                // 如果岗位中不存在该属性则忽略
                if (!positionFields.contains(positionField)) {
                    continue;
                }

                Object oldValue = dbPositionDy.get(positionField);
                Object newValue = entryEntityDy.get(entryField);
                boolean isChange;
                if (HRObjectUtils.isEmpty(oldValue) && HRObjectUtils.isEmpty(newValue)) {
                    isChange = false;
                } else if ((!HRObjectUtils.isEmpty(oldValue) && HRObjectUtils.isEmpty(newValue)) || (HRObjectUtils.isEmpty(oldValue) && !HRObjectUtils.isEmpty(newValue))) {
                    isChange = true;
                } else {
                    isChange = !HRDynamicObjectUtils.compareValues(newValue, oldValue);
                }

                if (isChange) {
                    newDyo.set(positionField, newValue);
                }
            }

            // 重置ID
            newDyo.set(PositionHRConstant.ID_KEY, null);
            newDyo.set(PositionHRConstant.BOID_KEY, null);
            // 设置 生效日期为设立日期
            newDyo.set(PositionHRConstant.BSED_KEY, newDyo.get(PositionHRConstant.NCKD_ESTABLISHMENTDATE_KEY));
            // 设置编码
            orgId = newDyo.getString(String.join(".", PositionHRConstant.ORG_KEY, PositionHRConstant.ID_KEY));
            String positionNumber = CodeRuleServiceHelper.getNumber(PositionHRConstant.HBPM_POSITIONHR, newDyo, orgId);
            newDyo.set(PositionHRConstant.NUMBER_KEY, positionNumber);
            // 放入
            dataEntities.add(newDyo);
        }

        OperateOption operateOption = OperateOption.create();
        operateOption.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
        operateOption.setVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.TRUE.toString());
        OperationResult operationResult = OperationServiceHelper.executeOperate(PositionHRConstant.SAVE_OP, PositionBillConstant.HBPM_POSITIONHR, dataEntities.toArray(new DynamicObject[0]), operateOption);
        List<String> errorMsgList = new ArrayList<String>();
        if (!operationResult.isSuccess()) {
            for(IOperateInfo operateInfo : operationResult.getAllErrorOrValidateInfo()) {
                errorMsgList.add(operateInfo.getMessage());
            }

            if (HRStringUtils.isNotBlank(operationResult.getMessage())) {
                errorMsgList.add(operationResult.getMessage());
            }

            // 回收编码
            String[] numbers = dataEntities.stream().map(data -> data.getString(PositionHRConstant.NUMBER_KEY)).toArray(String[]::new);
            CodeRuleServiceHelper.recycleBatchNumber(PositionHRConstant.HBPM_POSITIONHR, dataEntities.toArray(new DynamicObject[0]), orgId, numbers);
        }

        if (!errorMsgList.isEmpty()) {
            getView().showMessage(null ,String.join(System.lineSeparator(), errorMsgList), MessageTypes.Default);
            return;
        }

        operationResult = OperationServiceHelper.executeOperate(PositionHRConstant.SAVE_OP, PositionBillConstant.HBPM_POSITIONHR, dataEntities.toArray(new DynamicObject[0]));
        if (!operationResult.isSuccess()) {
            for(IOperateInfo operateInfo : operationResult.getAllErrorOrValidateInfo()) {
                errorMsgList.add(operateInfo.getMessage());
            }

            if (HRStringUtils.isNotBlank(operationResult.getMessage())) {
                errorMsgList.add(operationResult.getMessage());
            }

            // 回收编码
            String[] numbers = dataEntities.stream().map(data -> data.getString(PositionHRConstant.NUMBER_KEY)).toArray(String[]::new);
            CodeRuleServiceHelper.recycleBatchNumber(PositionHRConstant.HBPM_POSITIONHR, dataEntities.toArray(new DynamicObject[0]), orgId, numbers);
        }

        if (!errorMsgList.isEmpty()) {
            getView().showMessage(null ,String.join(System.lineSeparator(), errorMsgList), MessageTypes.Default);
            return;
        }

        getView().returnDataToParent("true");
        getView().close();
    }
}
