package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;

import com.google.common.collect.Maps;
import kd.bos.common.enums.EnableEnum;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.ExtendedDataEntity;
import kd.bos.entity.validate.AbstractValidator;
import kd.bos.entity.validate.ValidateResultCollection;
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.orm.util.CollectionUtils;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
import kd.hr.hbp.common.util.HRStringUtils;
import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;

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

/**
 * 岗位社区内单保存并提交校验器
 * @from: kd.hr.homs.opplugin.web.orgbatch.OrgBatchBillSaveAndSubmitValidator
 * @author: jtd
 * @date: 2026/1/2 16:01
 */
public class PositionBillSaveAndSubmitValidator extends AbstractValidator {
    private static final Log logger = LogFactory.getLog(PositionBillSaveAndSubmitValidator.class);
    private String operateKey;

    /**
     * 获取所有岗位的历史版本数据
     * @param billId
     * @return
     */
    private Map<Long, Long> getBoIdPositionIdMap(Long billId) {
        // from: kd.hr.homs.business.domain.batchbill.service.impl.OrgBatchBillConverter.processDynamicObject
        // unSafeAndDeleteDataMap获取到是空的，因为mergesplitstatus默认是2，而岗位并不需要考虑拆分合并的数据所以视作无数据即可
        // 拿到所有岗位ID，实际上并不需要新增的岗位
        HRBaseServiceHelper baseHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
        QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
        DynamicObject[] objects = baseHelper.loadDynamicObjectArray(billIdFilter.toArray());
        // from: kd.hr.homs.business.domain.orgbatch.service.impl.OrgBatchChgFeasibleCheckServiceImpl.check
        // 获取所有岗位的BOID
        Set<Long> ownBoIdSet = Arrays.stream(objects).map(object -> object.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.BOID_KEY))).collect(Collectors.toSet());
        // from: kd.hr.homs.business.domain.orgbatch.repository.OrgBatchBillCheckHelper.queryNewBoIdOrgIdMap
        // 查询出对应的历史版本
        QFilter adminFilter = new QFilter(PositionBillConstant.BOID_KEY, QCP.in, ownBoIdSet);
        adminFilter.and(new QFilter(PositionBillConstant.DATA_STATUS, QCP.in, HisModelDataStatusEnum.EFFECTING));
        adminFilter.and(new QFilter(PositionBillConstant.ENABLE, QCP.equals, EnableEnum.YES.getCode()));
        adminFilter.and(new QFilter(PositionBillConstant.IS_CURRENT_VERSION, QCP.equals, EnableEnum.NO.getCode()));
        HRBaseServiceHelper positionHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
        DynamicObjectCollection positionColl = positionHelper.queryOriginalCollection(String.join(",", PositionBillConstant.BOID_KEY, PositionBillConstant.ID_KEY), new QFilter[]{adminFilter}, String.format("%s desc", PositionBillConstant.BSED_KEY));
        Map<Long, List<DynamicObject>> positionGroupMap = positionColl.stream().collect(Collectors.groupingBy((dy) -> dy.getLong(PositionBillConstant.BOID_KEY)));
        Map<Long, Long> boIdPositionIdMap = Maps.newHashMapWithExpectedSize(positionColl.size());

        for(Map.Entry<Long, List<DynamicObject>> entry : positionGroupMap.entrySet()) {
            Long positionId = entry.getValue().get(0).getLong(PositionBillConstant.ID_KEY);
            boIdPositionIdMap.put(entry.getKey(), positionId);
        }

        return boIdPositionIdMap;
    }

    /**
     * 校验变更信息中的岗位是否最新一笔历史版本
     * @from: kd.hr.homs.business.domain.orgbatch.service.impl.OrgBatchChgFeasibleCheckServiceImpl#checkInfoChg(java.lang.String, kd.bos.dataentity.entity.DynamicObject, java.util.List)
     * @param dynamicObject
     * @return
     */
    private String checkChangeHandler(DynamicObject dynamicObject, Map<Long, Long> boIdOrgIdMap) {
        DynamicObject position = dynamicObject.getDynamicObject(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG));
        Long boId = position.getLong(PositionBillConstant.BOID_KEY);
        Long positionId = position.getLong(PositionBillConstant.ID_KEY);
        String positionName = position.getString(PositionBillConstant.NAME_KEY);
        Long newPositionId = boIdOrgIdMap.get(boId);
        if (!Objects.isNull(newPositionId) && !newPositionId.equals(positionId)) {
            return String.format("“变更信息”中“%s”：当前岗位已发生变化，请基于最新的信息进行调整。", new Object[]{positionName});
        }

        return "";
    }

    @Override
    public void validate() {
        this.operateKey = getOption().getVariableValue(PositionBillConstant.OP_OPERATE_KEY, "");
        long startTime = System.currentTimeMillis();
        ValidateResultCollection validateResultCollection = getValidateContext().getValidateResults();
        if (validateResultCollection == null || CollectionUtils.isEmpty(validateResultCollection.getValidateErrors()) || CollectionUtils.isEmpty((validateResultCollection.getValidateErrors().get(0)).getAllErrorInfo())) {
            ExtendedDataEntity[] dataEntities = getDataEntities();
            List<String> entryKeyList = new ArrayList(8);

            for(ExtendedDataEntity dataEntity : dataEntities) {
                Map<Long, Long> boIdPositionIdMap = getBoIdPositionIdMap(dataEntity.getDataEntity().getLong(PositionBillConstant.ID_KEY));
                if (entryKeyList.isEmpty()) {
                    entryKeyList = Arrays.stream(PositionChangeTypeEnum.values()).map(changeTypeEnum -> changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY)).collect(Collectors.toList());
                }

                DynamicObject checkObject = dataEntity.getDataEntity();
                String message = showMessageBeforeCheck(checkObject, entryKeyList);
                if (HRStringUtils.isEmpty(message)) {
                    // 这里不校验新增岗位的数据
                    for (DynamicObject dynamicObject : dataEntity.getDataEntity().getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY)) {
                        String errorMessage = checkChangeHandler(dynamicObject, boIdPositionIdMap);
                        if (HRStringUtils.isNotBlank(errorMessage)) {
                            addErrorMessage(dataEntity, errorMessage);
                        }
                    }
                } else {
                    addErrorMessage(dataEntity, message);
                }
            }

            logger.info(String.format(Locale.ROOT, "PositionBillSaveAndSubmitValidator() time cost is: %s", System.currentTimeMillis() - startTime));
        }
    }

    private String showMessageBeforeCheck(DynamicObject checkObject, List<String> entryKeyList) {
        String message = null;
        boolean isChange = isChange(checkObject, entryKeyList);
        this.operateKey = HRStringUtils.isEmpty(this.operateKey) ? getOperateKey() : this.operateKey;
        switch (this.operateKey) {
            case PositionBillConstant.SAVE_OP:
                if (!isChange) {
                    message = "没有“岗位调整”的数据，请调整后再操作“保存”";
                }
                break;
            case PositionBillConstant.SUBMIT_OP:
                if (!getIsHasWorkFlow()) {
                    message = "提交失败，当前单据没有可用的工作流，请保存单据后前往“流程服务云>工作流服务>设计中心>流程设计”中新增或发布流程。";
                }
            case "wftask_save":
                if (!isChange) {
                    message = "没有“岗位调整”的数据，请调整后再操作“提交”。";
                }
                break;
            case PositionBillConstant.SUBMITEFFECT_OP:
                if (!isChange) {
                    message = "没有“岗位调整”的数据，请调整后再操作“提交并生效”。";
                }
        }

        return message;
    }

    private boolean getIsHasWorkFlow() {
        String entityNumber = getDataEntities()[0].getDataEntity().getDataEntityType().getName();
        HRBaseServiceHelper wfHelper = new HRBaseServiceHelper("wf_model");
        QFilter qFilter = new QFilter("entrabill", "=", entityNumber);
        qFilter.and("publish", "=", '1').and("discard", "=", '0');
        return wfHelper.isExists(qFilter);
    }

    private boolean isChange(DynamicObject checkObject, List<String> entryKeyList) {
        logger.info("isChange entryKeys:{}", entryKeyList);

        for(String entryKey : entryKeyList) {
            DynamicObjectCollection entryColl = checkObject.getDynamicObjectCollection(entryKey);
            if (!CollectionUtils.isEmpty(entryColl)) {
                return true;
            }
        }

        return false;
    }
}
