package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
import kd.bos.entity.operate.result.OperateErrorInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.validate.ErrorLevel;
import kd.bos.form.IFormView;
import kd.bos.form.MessageBoxResult;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.events.MessageBoxClosedEvent;
import kd.bos.orm.ORM;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
import kd.hr.hbp.common.util.HRStringUtils;
import nckd.jxccl.base.common.utils.QueryFieldBuilder;
import nckd.jxccl.base.common.utils.PatternUtil;
import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 岗位申请单确认回调服务类
 * @from: kd.hr.homs.business.domain.batchbill.service.impl.AdminOrgBatchBillConfirmCallBackService
 * @author: jtd
 * @date: 2025/12/21 21:59
 */
public class PositionBillConfirmCallBackService extends PositionBillBaseService {

    public PositionBillConfirmCallBackService(IFormView view) {
        super(view);
    }

    public void confirmCallBack(MessageBoxClosedEvent event) {
        String callBackId = event.getCallBackId();
        if (!"effect_confirm".equals(callBackId) || event.getResult() != MessageBoxResult.Yes) {
            if (callBackId.startsWith(PositionBillConstant.DELETE_ROWS_PREFIX)) {
                if (event.getResult() == MessageBoxResult.Cancel) {
                    return;
                }

                EntryGrid strategyEntryGrid = getView().getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, callBackId.substring(callBackId.lastIndexOf("_")+1)));
                int[] selectRows = strategyEntryGrid.getSelectRows();
                HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
                List<Long> entryIdList = Lists.newArrayListWithExpectedSize(selectRows.length);
                if (PositionBillConstant.DELETE_ROWS_ADD_OP.equals(callBackId)) {
                    List<Long> positionIds = Lists.newArrayListWithExpectedSize(selectRows.length);
                    int[] deleteRows = validateHasChildPositionAndDelete();
                    if (deleteRows.length == 0) {
                        return;
                    }

                    for (int i = 0; i < deleteRows.length; ++i) {
                        int row = deleteRows[i];
                        entryIdList.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(PositionBillConstant.ID_KEY));
                        positionIds.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ADD_TAG)));
                    }

                    getModel().deleteEntryRows(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY, deleteRows);
                    PositionBillServiceHelper.delAddMaster(positionIds);
                } else if (PositionBillConstant.DELETE_ROWS_CHANGE_OP.equals(callBackId)) {
                    entryIdList = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY).stream().map((entry) -> entry.getLong(PositionBillConstant.ID_KEY)).collect(Collectors.toList());
                    getModel().deleteEntryRows(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY, selectRows);
                }

                getView().showSuccessNotification("删除成功");
                hrBaseServiceHelper.delete(entryIdList.toArray(new Long[0]));
            } else if (!PositionBillConstant.CB_CLOSE_BILL.equals(callBackId)) {
                // 避免正常的回调操作误入else，需要增加这个判断(比如select_position_的回调)
            } else {
                if (PositionBillConstant.CB_CLOSE_BILL.equals(callBackId) && event.getResult() == MessageBoxResult.Cancel) {
                    return;
                }

                for (PositionChangeTypeEnum changeTypeEnum : PositionChangeTypeEnum.values()) {
                    getModel().deleteEntryData(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY));
                }

                long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
                HRBaseServiceHelper positionBillEntryHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
                QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
                String selectProperties = QueryFieldBuilder.create().add(PositionBillConstant.ID_KEY)
                        .add(PositionBillConstant.NUMBER_KEY)
                        .add(PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY)
                        .add(PositionBillConstant.NCKD_POSITION_KEY)
                        .buildSelect();
                DynamicObject[] positionBillEntryDynArr = positionBillEntryHelper.query(selectProperties, new QFilter[]{billIdFilter});
                positionBillEntryHelper.deleteByFilter(new QFilter[]{billIdFilter});
                List<Long> addPositionIdList = Arrays.stream(positionBillEntryDynArr).filter((dynx) -> HRStringUtils.equals(dynx.getDynamicObject(PositionBillConstant.NCKD_CHANGETYPE).getString(PositionBillConstant.NUMBER_KEY), PositionBillConstant.ADD_TAG)).map((dynx) -> dynx.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY))).collect(Collectors.toList());
                PositionBillServiceHelper.delAddMaster(addPositionIdList);

                getView().getPageCache().put(PositionBillConstant.PC_ISCANCELOVER, Boolean.TRUE.toString());
                getView().invokeOperation(PositionBillConstant.CLOSE_OP);
            }
        }

        changeOrgOrPositionConfirm(event, callBackId);
    }

    private int[] validateHasChildPositionAndDelete() {
        EntryGrid strategyEntryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
        int[] rows = strategyEntryGrid.getSelectRows();
        // 要删除的岗位
        List<Long> toBeDeletePositionIdList = Lists.newArrayListWithExpectedSize(rows.length);
        List<DynamicObject> toBeDeletePositionDynList = Lists.newArrayListWithExpectedSize(rows.length);
        // 新增岗位单据体中未选中的岗位数据，视作上级岗位，避免新增岗位中的上级岗位选择了该单据体中的其他未被选中的岗位
        List<Long> otherPositionIdList = Lists.newArrayListWithExpectedSize(rows.length);
        int count = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).getRowCount();
        List<Integer> rowList = Arrays.stream(rows).boxed().collect(Collectors.toList());

        // 岗位标识-新增岗位
        String positionAddKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ADD_TAG);
        for(int i = 0; i < count; ++i) {
            DynamicObject dynamicObject = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(i);
            long positionId = dynamicObject.getLong(positionAddKey);
            if (rowList.contains(i)) {
                toBeDeletePositionIdList.add(positionId);
                toBeDeletePositionDynList.add(dynamicObject);
            } else {
                otherPositionIdList.add(positionId);
            }
        }

        HRBaseServiceHelper positionServiceHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
        // 获取变更信息单据体中岗位的上级岗位
        DynamicObjectCollection parentEntryEntity = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);
        List<Long> positionParentIdList = parentEntryEntity.stream().map((entryEntity) -> entryEntity.getLong(String.format("%s_%s.%s",  PositionBillConstant.NCKD_PARENT, PositionBillConstant.CHANGE_TAG, PositionBillConstant.ID_KEY))).collect(Collectors.toList());
        QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.in, positionParentIdList);
        DynamicObject[] positionParentDyns = positionServiceHelper.query(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.BOID_KEY), new QFilter[]{idFilter});
        Set<Long> parentPositionBoIdList = Arrays.stream(positionParentDyns).map((dyn) -> dyn.getLong(PositionBillConstant.BOID_KEY)).collect(Collectors.toSet());
        // 要校验的上级岗位数据包含变更信息中岗位的上级岗位和新增岗位单据体中未被选中的岗位的上级岗位
        parentPositionBoIdList.addAll(otherPositionIdList);
        // 不能被删除的岗位
        Set<Long> doNotdeletePositionIdSet = Sets.newHashSetWithExpectedSize(toBeDeletePositionIdList.size());

        // 判断要删除的岗位是否为其他岗位的上级岗位
        for(Long toBeDeletePositionId : toBeDeletePositionIdList) {
           if (parentPositionBoIdList.contains(toBeDeletePositionId)) {
                doNotdeletePositionIdSet.add(toBeDeletePositionId);
            }
        }

        OperationResult operationResult = new OperationResult();
        operationResult.setSuccess(true);
        operationResult.setBillCount(rows.length);

        for(DynamicObject toBeDeletePositionDyn : toBeDeletePositionDynList) {
            long toBeDeletePositionId = toBeDeletePositionDyn.getLong(positionAddKey);
            if (doNotdeletePositionIdSet.contains(toBeDeletePositionId)) {
                OperateErrorInfo operateInfo = new OperateErrorInfo("100000", ErrorLevel.Error, toBeDeletePositionId);
                operateInfo.setErrorLevel(ErrorLevel.FatalError.name());
                operateInfo.setMessage(String.format(Locale.ROOT, "%s在本单有下层岗位，不允许删除。", toBeDeletePositionDyn.getString(String.join("_", PositionBillConstant.NCKD_NAME_KEY, PositionBillConstant.ADD_TAG))));
                operationResult.setSuccess(false);
                operationResult.addErrorInfo(operateInfo);
            } else {
                operationResult.addSuccessPkId(toBeDeletePositionId);
            }
        }

        if (!operationResult.isSuccess()) {
            getView().showOperationResult(operationResult, "删除");
        }

        List<Integer> deleteRowIndexList = Lists.newArrayListWithExpectedSize(toBeDeletePositionDynList.size());
        DynamicObjectCollection addEntryEntity = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);

        for(int i = 0; i < addEntryEntity.size(); ++i) {
            long positionId = addEntryEntity.get(i).getLong(positionAddKey);
            if (toBeDeletePositionIdList.contains(positionId) && !doNotdeletePositionIdSet.contains(positionId)) {
                deleteRowIndexList.add(i);
            }
        }

        return deleteRowIndexList.stream().mapToInt(Integer::intValue).toArray();
    }

    private void changeOrgOrPositionConfirm(MessageBoxClosedEvent messageBoxClosedEvent, String callBackId) {
        if (callBackId.startsWith(PositionBillConstant.CB_SELECT_POSITION)) {
            String suffix = callBackId.substring(16);
            String lineSuffix = "_" + suffix;
            HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
            String positionRow = getView().getPageCache().get(PositionBillConstant.PC_POSITIONROW);
            int row = Integer.parseInt(positionRow);
            if (messageBoxClosedEvent.getResult() != MessageBoxResult.Yes) {
                DynamicObject entryEntityDyn = getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix).get(row);
                String positionOld = getView().getPageCache().get(PositionBillConstant.PC_POSITIONOLD);
                if (HRStringUtils.isNotEmpty(positionOld)) {
                    QFilter filter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, Long.parseLong(positionOld));
                    DynamicObject position = helper.queryOne(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.NAME_KEY, PositionBillConstant.NUMBER_KEY), filter.toArray());
                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION_KEY + lineSuffix, position);
                } else {
                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION_KEY + lineSuffix, null);
                }

                getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
                return;
            }

            DataEntityPropertyCollection entryEntityInfo = getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix)).getDynamicObjectType().getProperties();
            Map<String, String> transKeyMap = new HashMap<String, String>();
            // 获取分录要转换的键值，将单据分录字段转换转成分录页面字段
            transKeyMap.putAll(PositionBillServiceHelper.getPosBillEntryTransKeyMap());
            // 获取岗位要转换的键值
            transKeyMap.putAll(PositionBillServiceHelper.getPositionTransKeyMap());
            // 获取岗位所有属性
            Set<String> positionProperties = PositionBillServiceHelper.getPositionProperties();

            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create();
            for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
                String propName = iDataEntityProperty.getName();
                if (PatternUtil.isExProperty(propName) && propName.endsWith(lineSuffix)) {
                    String selectName = PositionBillServiceHelper.getNoLineSuffixProp(propName, lineSuffix);
                    selectName = transKeyMap.getOrDefault(selectName, selectName);
                    if (positionProperties.contains(selectName)) {
                        queryFieldBuilder.add(selectName);
                    }
                }
            }

            DynamicObject entryEntityDyn = PositionBillServiceHelper.getFocusEntry(suffix, getView(), row);
            long positionId = entryEntityDyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY+lineSuffix, PositionBillConstant.ID_KEY));
            QFilter filter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, positionId);
            DynamicObject position = helper.queryOne(queryFieldBuilder.buildSelect(), filter.toArray());
            long entryId = ORM.create().genLongId(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
            entryEntityDyn.set(PositionBillConstant.ID_KEY, entryId);
            // 设置单据分录字段值
            for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
                String propName = iDataEntityProperty.getName();
                if (PatternUtil.isExProperty(propName) && propName.endsWith(lineSuffix)) {
                    String selectName = PositionBillServiceHelper.getNoLineSuffixProp(propName, lineSuffix);
                    selectName = transKeyMap.getOrDefault(selectName, selectName);
                    if (positionProperties.contains(selectName)) {
                        // 原上级岗位特殊处理
                        if (HRStringUtils.equals(selectName, PositionBillConstant.NCKD_PARENT)) {
                            entryEntityDyn.set(PositionBillConstant.NCKD_ORIPARENT_KEY+lineSuffix, position.get(selectName));
                        }
                        entryEntityDyn.set(propName, position.get(selectName));
                    }
                }
            }

            getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
        } else if (callBackId.equals(String.join("_", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.CHANGE_TAG))) {
            String entryId = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, callBackId);
            EntryGrid entryGrid = getView().getControl(entryId);
            int row = entryGrid.getEntryState().getFocusRow();
            if (messageBoxClosedEvent.getResult() == MessageBoxResult.Yes) {
                PosBillEntryFastChgHelper.cleanOrgBaseInfoForBillEntry(getView(), row, callBackId, entryId);
            } else {
                String oldId = getView().getPageCache().get(PositionBillConstant.PC_ENTRY_ORG_VALUE);
                getModel().beginInit();
                getModel().setValue(callBackId, Long.parseLong(oldId), row);
                getModel().endInit();
                getView().updateView(callBackId, row);
            }
        }

    }
}
