package nckd.jxccl.opmc.pm.plugin.operate.result;

import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.ExtendedDataEntity;
import kd.bos.entity.operate.OperateOptionConst;
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.servicehelper.operation.OperationServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.AppraisalResultEnum;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.StrFormatter;
import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
import nckd.jxccl.opmc.pm.helper.PerfManagerHelper;

import java.time.LocalDateTime;
import java.util.*;

/**
* 视同合格/优秀/无结果
* 实体标识：nckd_updateresult
* @author W.Y.C
* @date 2025/11/14 16:50
* @version 1.0
*/
public class UpdateResultOpPlugin extends AbstractOperationServicePlugIn implements Plugin {

    //缓存需要修改的数据，key：考核周期ID
    Map<Long, List<PendingUpdate>> pendingUpdateMap = new java.util.HashMap<>();

    private class PendingUpdate {

        Long entryId;
        Date appraisalYear;
        DynamicObject appraisalResult;

        public PendingUpdate(Long entryId,Date appraisalYear,DynamicObject appraisalResult) {
            this.entryId = entryId;
            this.appraisalResult = appraisalResult;
            this.appraisalYear = appraisalYear;
        }
    }

    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {

        e.addValidator(new AbstractValidator() {
            @Override
            public void validate() {
                if(getOperationResult() != null && getOperationResult().isSuccess()) {
                    for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                        DynamicObject data = rowDataEntity.getDataEntity();
                        DynamicObjectCollection entryColl = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
                        for (DynamicObject entry : entryColl) {
                            DynamicObject empPosOrgRel = entry.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL);
                            DynamicObject employee = empPosOrgRel.getDynamicObject(FormConstant.EMPLOYEE_KEY);
                            long personId = employee.getLong(FormConstant.ID_KEY);
                            Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
                            LocalDateTime appraisalYearLocalDateTime = DateUtil.toLocalDateTime(appraisalYear);
                            DynamicObject appraisalResult = entry.getDynamicObject(PerfManagerFormConstant.NCKD_APPRAISALRESULT);

                            DynamicObject[] dbPerfManagerArray = PerfManagerHelper.getByDate(appraisalYear, Collections.singletonList(personId));
                            if (dbPerfManagerArray == null || dbPerfManagerArray.length == 0) {
                                this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("员工【{}】没有【{}】年的考核周期", employee.getString(FormConstant.NAME_KEY), DateUtil.getYear(appraisalYear)));
                            }else{
                                for (DynamicObject dbPerfManager : dbPerfManagerArray) {
                                    long dbId = dbPerfManager.getLong(FormConstant.ID_KEY);
                                    Date dbBeginYear = dbPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR);
                                    Date dbEndYear = dbPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
                                    if(dbPerfManager.getDate(PerfManagerFormConstant.NCKD_ACTENDYEAR) != null){
                                        //如果有实际结束周期则结束时间为实际结束周期
                                        dbEndYear = dbPerfManager.getDate(PerfManagerFormConstant.NCKD_ACTENDYEAR);
                                    }
                                    DynamicObjectCollection dbEntryColl = dbPerfManager.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
                                    boolean isExist = false;
                                    for (DynamicObject dbEntry : dbEntryColl) {
                                        long entryId = dbEntry.getLong(FormConstant.ID_KEY);
                                        LocalDateTime dbAppraisalYear = DateUtil.toLocalDateTime(dbEntry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR));
                                        //只取年份在考核周期内的数据

                                        if(dbAppraisalYear.getYear() >= DateUtil.getYear(dbBeginYear) &&  dbAppraisalYear.getYear()  <= DateUtil.getYear(dbEndYear)){
                                            if(dbAppraisalYear.getYear() == appraisalYearLocalDateTime.getYear()) {
                                                isExist = true;
                                                DynamicObject dbAppraisalResult = dbEntry.getDynamicObject(PerfManagerFormConstant.NCKD_APPRAISALRESULT);
                                                boolean dbIsAllRankSource = dbEntry.getBoolean(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE);
                                                if (dbAppraisalResult != null) {
                                                    if (dbIsAllRankSource) {
                                                        this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("员工【{}】已存在【{}】年的考核结果【{}】，并且结果来源于全排名。", employee.getString(FormConstant.NAME_KEY), DateUtil.getYear(appraisalYear), dbAppraisalResult.getString(FormConstant.NAME_KEY)));
                                                    } else {
                                                        String dbAppraisalResultNumber = dbAppraisalResult.getString(FormConstant.NUMBER_KEY);
                                                        if (!AppraisalResultEnum.NONE.getCode().equalsIgnoreCase(dbAppraisalResultNumber)) {
                                                            if (!Objects.equals(dbAppraisalResult.getLong(FormConstant.ID_KEY), appraisalResult.getLong(FormConstant.ID_KEY))) {
                                                                this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("员工【{}】已存在【{}】年的考核结果【{}】，不能修改。", employee.getString(FormConstant.NAME_KEY), DateUtil.getYear(appraisalYear), dbAppraisalResult.getString(FormConstant.NAME_KEY)));
                                                            } else {
                                                                //原绩效跟要更新的绩效一样，忽略
                                                            }
                                                        } else {
                                                            //原绩效结果等于"无"，又不是来源于全排名。可以修改
                                                            List<PendingUpdate> pendingUpdateList = pendingUpdateMap.computeIfAbsent(dbId, k -> new ArrayList<>());
                                                            PendingUpdate pendingUpdate = new PendingUpdate(entryId, appraisalYear, appraisalResult);
                                                            pendingUpdateList.add(pendingUpdate);
                                                            pendingUpdateMap.put(dbId, pendingUpdateList);
                                                        }
                                                    }
                                                } else {
                                                    //原绩效结果为空。可以修改
                                                    List<PendingUpdate> pendingUpdateList = pendingUpdateMap.computeIfAbsent(dbId, k -> new ArrayList<>());
                                                    PendingUpdate pendingUpdate = new PendingUpdate(entryId, appraisalYear, appraisalResult);
                                                    pendingUpdateList.add(pendingUpdate);
                                                    pendingUpdateMap.put(dbId, pendingUpdateList);
                                                }
                                            }
                                        }
                                    }
                                    if(!isExist){
                                        //考核周期分录没有该年份的数据
                                        //检查全排名是否存在
                                        Map<Long, AppraisalResultEnum> perfRankResult = PerfManagerHelper.getPerfRankResult(appraisalYear, Collections.singletonList(personId));
                                        boolean isPass = true;
                                        if(!perfRankResult.isEmpty()){
                                            AppraisalResultEnum appraisalResultEnum = perfRankResult.get(personId);
                                            if(appraisalResultEnum != null){
                                                this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("【{}】【{}】年的考核结果已在全排名中产生【{}】，不能修改。", employee.getString(FormConstant.NAME_KEY), DateUtil.getYear(appraisalYear), appraisalResultEnum.getName()));
                                                isPass = false;
                                            }
                                        }
                                        if(isPass) {
                                            List<PendingUpdate> pendingUpdateList = pendingUpdateMap.computeIfAbsent(dbId, k -> new ArrayList<>());
                                            PendingUpdate pendingUpdate = new PendingUpdate(null, appraisalYear, appraisalResult);
                                            pendingUpdateList.add(pendingUpdate);
                                            pendingUpdateMap.put(dbId, pendingUpdateList);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }


    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {

        if(!pendingUpdateMap.isEmpty()){
            DynamicObject[] updatePerfManagerArray = PerfManagerHelper.getById(pendingUpdateMap.keySet());
            for (DynamicObject updatePerfManager : updatePerfManagerArray) {
                long id = updatePerfManager.getLong(FormConstant.ID_KEY);
                List<PendingUpdate> pendingUpdateList = pendingUpdateMap.get(id);
                DynamicObjectCollection updatePerfManagerEntryColl = updatePerfManager.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
                for (PendingUpdate pendingUpdate : pendingUpdateList) {
                    if(pendingUpdate.entryId != null) {
                        for (DynamicObject updatePerfManagerEntry : updatePerfManagerEntryColl) {
                            long entryId = updatePerfManagerEntry.getLong(FormConstant.ID_KEY);
                            if (Objects.equals(entryId, pendingUpdate.entryId)) {
                                updatePerfManagerEntry.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, pendingUpdate.appraisalResult);
                                updatePerfManagerEntry.set(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE, false);
                            }
                        }
                    }else{
                        DynamicObject newEntry = updatePerfManagerEntryColl.addNew();
                        newEntry.set(PerfManagerFormConstant.NCKD_APPRAISALYEAR,pendingUpdate.appraisalYear);
                        newEntry.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, pendingUpdate.appraisalResult);
                        newEntry.set(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE, false);
                    }
                }

            }

            OperateOption option = OperateOption.create();
            option.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE + "");
            //告诉OP此次操作类型
            option.setVariableValue("isUpdate", Boolean.TRUE+"");
            OperationResult operationResult = OperationServiceHelper.executeOperate(FormConstant.SAVE_OP, PerfManagerFormConstant.PERFMANAGER_ENTITYID, updatePerfManagerArray, option);
        }

    }
}