package nckd.jxccl.hr.psms.plugin.operate.annualadjust;

import kd.bos.common.enums.EnableEnum;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.ObjectUtils;
import kd.bos.entity.ExtendedDataEntity;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.AddValidatorsEventArgs;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
import kd.bos.entity.validate.AbstractValidator;
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.servicehelper.operation.SaveServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.psms.AdjustTypeEnum;
import nckd.jxccl.base.common.exception.ValidationException;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.StrFormatter;
import nckd.jxccl.base.pm.helper.PerformanceManagerHelper;
import nckd.jxccl.hr.psms.business.AnnualAdjustmentService;
import nckd.jxccl.hr.psms.business.ManagerAllowanceService;
import nckd.jxccl.hr.psms.common.PositionStructureConstant;
import nckd.jxccl.hr.psms.common.bo.PositionAppointmentBO;
import nckd.jxccl.hr.psms.helper.PositionFileHelper;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* 新建年度调整记录操作插件
* @author W.Y.C
* @date 2025/10/13 20:40
* @version 1.0
*/
public class AnnualAdjustmentOperationPlugin extends AbstractOperationServicePlugIn implements Plugin {

    protected final static Log logger = LogFactory.getLog(AnnualAdjustmentOperationPlugin.class);

    /** 初定职位档案（key：人员ID，value：最新职位档案） */
    Map<Long,DynamicObject> firstPersonPosFileMap;

    /** 记录上年度考核结果（key：人员ID）*/
    Map<Long,DynamicObject> lastYearPerformanceResultMap;

    /** 记录上年度考核结果（key：人员ID）*/
    Map<Long,PositionAppointmentBO> positionAppointmentMap;

    @Override
    public void onAddValidators(AddValidatorsEventArgs e){
        e.addValidator(new AbstractValidator() {
            @Override
            public void validate() {
                firstPersonPosFileMap = new HashMap<>();
                lastYearPerformanceResultMap = new HashMap<>();
                positionAppointmentMap = new HashMap<>();
                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                    DynamicObject data = rowDataEntity.getDataEntity();
                    if(data.containsProperty(FormConstant.NCKD_ENTRYENTITY)){
                        //批量调整
                        DynamicObjectCollection dynamicObjectCollection = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
                        // 检查人员ID重复
                        Set<Long> personIds = new HashSet<>();
                        for (DynamicObject dynamicObject : dynamicObjectCollection) {
                            if (dynamicObject.containsProperty(FormConstant.NCKD_PERSON)) {
                                DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
                                Long personId = person.getLong(FormConstant.ID_KEY);
                                if (!personIds.add(personId)) {
                                    addFatalErrorMessage(rowDataEntity,
                                            StrFormatter.format("人员【{}】在列表中重复，请保留一条信息",
                                                    person.getString(FormConstant.NAME_KEY)));
                                }
                            }
                        }
                        if(!this.getValidateResult().isSuccess()){
                            return;
                        }

                        for (DynamicObject dynamicObject : dynamicObjectCollection) {
                            validator(rowDataEntity, dynamicObject);
                        }
                    }else{
                        //单人调整
                        validator(rowDataEntity, data);
                    }
                }
            }

            private void validator(ExtendedDataEntity rowDataEntity, DynamicObject data) {
                Date adjustDate = data.getDate(PositionStructureConstant.NCKD_ADJUSTDATE);
                if (adjustDate != null) {
                    // 如果adjustDate不为空且为年初日期(xxxx-01-01)，则转换为当年7月1日
                    LocalDateTime adjustDateTime = DateUtil.toLocalDateTime(adjustDate);
                    if (adjustDateTime.getMonthValue() == 1 && adjustDateTime.getDayOfMonth() == 1) {
                        //前端只选年份，这里默认为XXX-07-01
                        adjustDate = DateUtil.toDate(adjustDateTime.withMonth(7).withDayOfMonth(1));
                    }
                }else{
                    //获取当年07-01的日期
                    /*LocalDate julyFirst = LocalDate.of(DateUtil.getYear(new Date()), 7, 1);
                    adjustDate = Date.from(julyFirst.atStartOfDay(ZoneId.systemDefault()).toInstant());*/
                    adjustDate = new Date();
                }

                int year = DateUtil.getYear(adjustDate);
                DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
                long personId = person.getLong(FormConstant.ID_KEY);
                String personName = person.getString(FormConstant.NAME_KEY);
                LocalDateTime lastYear = DateUtil.minusYears(DateUtil.toLocalDateTime(adjustDate), 1);
                DynamicObject performanceResult = PerformanceManagerHelper.getPerformanceResult(personId, lastYear);
                if(performanceResult == null){
                    addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】缺少【{}】年考核结果", personName,lastYear.getYear()));
                }

                PositionAppointmentBO positionAppointment = PositionFileHelper.positionAppointmentQuery(personId, adjustDate);
                if(positionAppointment.getEmpPosOrgRel() == null){
                    addFatalErrorMessage(rowDataEntity,StrFormatter.format("当前无法为【{}】进行调整，因为根据时间【{}】未获取到人员任职和聘任信息！", personName, DateUtil.format(adjustDate,DateUtil.NORM_DATE_PATTERN)));
                }

                DynamicObject firstRank = PositionFileHelper.getFirstRank(personId);
                if(firstRank == null){
                    addFatalErrorMessage(rowDataEntity,StrFormatter.format("当前无法为【{}】进行调整，因为他/她尚未建立职位档案。请前往“职位及积分初定” -> 进行初定！", personName));
                }else{
                    if(firstRank.getInt(PositionStructureConstant.NCKD_EXECUTEYEAR) == year){
                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("当前无法为【{}】进行调整，因为初定当年不能执行年度调整。初定时间【{}】", personName,DateUtil.format(firstRank.getDate(PositionStructureConstant.NCKD_BEGINDATE),DateUtil.NORM_DATE_PATTERN)));
                    }
                }
                int executeYear = DateUtil.getYear(adjustDate);
                //判断当前年是否已执行过年度调整
                DynamicObject[] personPosFileByYear = PositionFileHelper.getPersonPosFileByPersonAndState(person.getLong(FormConstant.ID_KEY), new String[]{"3"}, null, new QFilter(PositionStructureConstant.NCKD_EXECUTEYEAR, QCP.equals, executeYear));
                if(personPosFileByYear != null && personPosFileByYear.length > 0){
                    addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】已存在【{}】年的年度调整", person.getString(FormConstant.NAME_KEY), executeYear));
                }
                if(positionAppointment.getEmpPosOrgRel() != null) {
                    long jobSeqId = positionAppointment.getEmpPosOrgRel().getLong(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ, FormConstant.ID_KEY));
                    if (jobSeqId == 0) {
                        String positionName = positionAppointment.getEmpPosOrgRel().getString(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NAME_KEY));
                        addFatalErrorMessage(rowDataEntity, StrFormatter.format("无职位序列，请检查当前人员【{}】任职的岗位【{}】是否有职位序列", personName, positionName));
                    }
                }

                if(this.getValidateResult().isSuccess()){
                    //局部缓存，给下面其他逻辑使用；避免重复查询
                    firstPersonPosFileMap.put(personId,firstRank);
                    lastYearPerformanceResultMap.put(personId,performanceResult);
                    positionAppointmentMap.put(personId,positionAppointment);
                }
            }
        });
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
        logger.info("【职位体系】-年度调整-开始");
        List<Long> personIds = new ArrayList<>(e.getDataEntities().length);
        List<DynamicObject> newPersonPosFiles = new ArrayList<>(e.getDataEntities().length);
        for (DynamicObject data : e.getDataEntities()) {
            if(data.containsProperty(FormConstant.NCKD_ENTRYENTITY)){
                //批量调整
                DynamicObjectCollection dynamicObjectCollection = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
                for (DynamicObject dynamicObject : dynamicObjectCollection) {
                    extracted(dynamicObject, newPersonPosFiles, personIds);
                }
            }else{
                //单次调整
                extracted(data, newPersonPosFiles, personIds);
            }
        }

//        SaveServiceHelper.save(newPersonPosFiles.toArray(new DynamicObject[0]));
        OperationResult operationResult = SaveServiceHelper.saveOperate(PositionStructureConstant.PERSONPOSFILE_ENTITYID, newPersonPosFiles.toArray(new DynamicObject[0]), OperateOption.create());
        if (!operationResult.isSuccess()) {
            StringJoiner errorMsg = new StringJoiner("\n");
            for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
                errorMsg.add(error.getMessage());
            }
            if (!ObjectUtils.isEmpty(operationResult.getMessage())) {
                errorMsg.add(operationResult.getMessage());
            }
            throw new ValidationException("保存职位档案失败，原因：" + errorMsg.toString());
        }
        PositionFileHelper.markAsNotCurrentNewest(personIds.toArray(new Long[0]));
        PositionFileHelper.markAsCurrentNewest(null,personIds.toArray(new Long[0]));
        for (DynamicObject newPersonPosFile : newPersonPosFiles) {
            String adjustType = newPersonPosFile.getString(PositionStructureConstant.NCKD_ADJUSTTYPE);
            setJobLevelResult(newPersonPosFile.getDynamicObject(PositionStructureConstant.NCKD_PERSON),newPersonPosFile.getDynamicObject(PositionStructureConstant.NCKD_JOBLEVELHR),AdjustTypeEnum.getByCode(adjustType));
        }
        //职位津贴（只取已生效的年度调整）
        List<DynamicObject> collect = newPersonPosFiles.stream().filter(newPersonPosFile -> newPersonPosFile.getString(PositionStructureConstant.NCKD_ADJUSSTATUS).equalsIgnoreCase(EnableEnum.YES.getCode())).collect(Collectors.toList());
        if(!collect.isEmpty()) {
            ManagerAllowanceService.generateMgrPostAllow(collect);
        }
    }

    private void extracted(DynamicObject data, List<DynamicObject> newPersonPosFiles, List<Long> personIds) {
        DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
        long personId = person.getLong(FormConstant.ID_KEY);
        Date adjustDate = data.getDate(PositionStructureConstant.NCKD_ADJUSTDATE);
        if (adjustDate != null) {
            // 如果adjustDate不为空且为年初日期(xxxx-01-01)，则转换为当年7月1日
            LocalDateTime adjustDateTime = DateUtil.toLocalDateTime(adjustDate);
            if (adjustDateTime.getMonthValue() == 1 && adjustDateTime.getDayOfMonth() == 1) {
                //前端只选年份，这里默认为XXX-07-01
                adjustDate = DateUtil.toDate(adjustDateTime.withMonth(7).withDayOfMonth(1));
            }
        }
        String remark = data.getString(FormConstant.NCKD_REMARK);
        DynamicObject newPersonPosFile = AnnualAdjustmentService.addNewYearPersonPositionFileInfo(person, adjustDate, remark, positionAppointmentMap.get(personId), lastYearPerformanceResultMap.get(personId), firstPersonPosFileMap.get(personId));
        newPersonPosFiles.add(newPersonPosFile);
        personIds.add(personId);
    }

    /**
     * 设置操作结果中的职级信息
     */
    protected void setJobLevelResult(DynamicObject person, DynamicObject jobLeve, AdjustTypeEnum adjustTypeEnum) {
        String jobLeveStr = StrFormatter.format("{}：{}（{}级）；{}",
                person.getString(FormConstant.NAME_KEY),
                jobLeve.getString(FormConstant.NAME_KEY),
                jobLeve.getString(PositionStructureConstant.NCKD_ALIAS),
                adjustTypeEnum.getName());

        Map<String, String> customData = this.getOperationResult().getCustomData();
        if(customData == null) {
            this.getOperationResult().setCustomData(new HashMap<>());
            customData = this.getOperationResult().getCustomData();
        }

        String oldJobLeveStr = customData.get(PositionStructureConstant.NCKD_JOBLEVELHR);
        if (oldJobLeveStr == null || oldJobLeveStr.isEmpty()) {
            customData.put(PositionStructureConstant.NCKD_JOBLEVELHR, jobLeveStr);
        } else {
            customData.put(PositionStructureConstant.NCKD_JOBLEVELHR, oldJobLeveStr + StrFormatter.LINE_SEPARATOR + jobLeveStr);
        }
    }
}