package nckd.jxccl.opmc.pm.plugin.form.cycle;

import kd.bos.bd.pojo.CtrlStrategyEnum;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.operate.OperateOptionConst;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.form.ConfirmCallBackListener;
import kd.bos.form.ConfirmTypes;
import kd.bos.form.FormShowParameter;
import kd.bos.form.MessageBoxOptions;
import kd.bos.form.MessageBoxResult;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.MessageBoxClosedEvent;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.org.utils.DynamicObjectUtils;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.exception.ValidationException;
import nckd.jxccl.base.common.utils.ConvertUtil;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.StrFormatter;
import nckd.jxccl.base.entity.helper.EntityHelper;
import nckd.jxccl.base.org.helper.OrgHelper;
import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
import nckd.jxccl.opmc.pm.common.SalAdjTrackerConstant;
import nckd.jxccl.opmc.pm.helper.PerfManagerHelper;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
* 批量新增考核周期插件
* 实体标识：nckd_batchevalcycle
* @author W.Y.C
* @date 2025/11/5 11:22
* @version 1.0
*/
public class BatchEvalCycleFormPlugin extends AbstractFormPlugin implements Plugin {

    @Override
    public void afterCreateNewData(EventObject e) {
        // 获取当前页面的FormShowParameter对象
        FormShowParameter showParameter = this.getView().getFormShowParameter();
        //获取列表选择的人员
        String isAddOrUpdate = ConvertUtil.toStr(showParameter.getCustomParam("nckd_isaddorupdate"));
        if("2".equalsIgnoreCase(isAddOrUpdate)) {
            //批量修改
            this.getModel().setValue("nckd_isaddorupdate", isAddOrUpdate);
            this.getView().updateView("nckd_isaddorupdate");

            List<Long> selectedRows = ConvertUtil.toList(showParameter.getCustomParam("selectedRows"));
            int max = Math.max(selectedRows.size() - 1, 0);
            if(max > 0) {
                this.getModel().batchCreateNewEntryRow(FormConstant.NCKD_ENTRYENTITY, max);
            }
            DynamicObject[] perfManagerList = PerfManagerHelper.getById(selectedRows);
            AtomicInteger index = new AtomicInteger(0);
            for (DynamicObject perfManager : perfManagerList) {
                int i = index.getAndIncrement();
                Date beginYear = perfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR);
                Date endYear = perfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
                this.getModel().setValue(PerfManagerFormConstant.PERFMANAGER_ENTITYID,perfManager, i);
                this.getModel().setValue(PerfManagerFormConstant.NCKD_EMPPOSORGREL,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_EMPPOSORGREL), i);
                this.getModel().setValue(PerfManagerFormConstant.NCKD_PERSON,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_PERSON), i);
                this.getModel().setValue(PerfManagerFormConstant.NCKD_BEGINYEAR,beginYear, i);
                this.getModel().setValue(PerfManagerFormConstant.NCKD_ENDYEAR,endYear, i);
                this.getModel().setValue(PerfManagerFormConstant.DESCRIPTION_KEY,perfManager.getString(FormConstant.DESCRIPTION_KEY), i);

                DynamicObjectCollection entrys = perfManager.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
                for (DynamicObject entry : entrys) {
                    boolean isAllRankSource = entry.getBoolean(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE);
                    Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);

                    if (isAllRankSource && appraisalYear != null) {
                        LocalDateTime appraisalLocalDate = DateUtil.toLocalDateTime(appraisalYear);
                        LocalDateTime beginLocalDate = DateUtil.toLocalDateTime(beginYear);

                        // 计算是第几年（分录中的年份-(周期开始时间 + 1)）
                        long yearsDiff = appraisalLocalDate.getYear() - beginLocalDate.getYear() + 1;
                        // 根据年份差异禁用对应的考核结果字段
                        switch ((int) yearsDiff) {
                            case 1:
                                this.getView().setEnable(Boolean.FALSE, i, PerfManagerFormConstant.NCKD_FIRSTYEARRESULT);
                                break;
                            case 2:
                                this.getView().setEnable(Boolean.FALSE, i, PerfManagerFormConstant.NCKD_SECONDYEARRESULT);
                                break;
                            case 3:
                                this.getView().setEnable(Boolean.FALSE, i, PerfManagerFormConstant.NCKD_THIRDYEARRESULT);
                                break;
                        }
                    }
                }

                this.getModel().setValue(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT), i);
                this.getModel().setValue(PerfManagerFormConstant.NCKD_SECONDYEARRESULT,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_SECONDYEARRESULT), i);
                this.getModel().setValue(PerfManagerFormConstant.NCKD_THIRDYEARRESULT,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_THIRDYEARRESULT), i);
            }

            this.getView().updateView(FormConstant.NCKD_ENTRYENTITY);
        }
    }


    @Override
    public void afterDoOperation(AfterDoOperationEventArgs e) {
        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()){
            String operateKey = e.getOperateKey();
            if(FormConstant.CONFIRM_OP.equalsIgnoreCase(operateKey)){
                String isAddOrUpdate = ConvertUtil.toStr(this.getModel().getValue("nckd_isaddorupdate"));
                boolean isUpdate = "2".equalsIgnoreCase(isAddOrUpdate);

                DynamicObjectCollection perfManagerList = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
                Map<Long, Date> personBeginYearMap = new HashMap<>(perfManagerList.size());
                //转换为考核周期实体
                for (DynamicObject dynamicObject : perfManagerList) {
                    DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
                    Long personId = person.getLong(FormConstant.ID_KEY);
                    Date beginYear = dynamicObject.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR);

                    if (beginYear != null) {
                        personBeginYearMap.put(personId, beginYear);
                    }
                }
                if(isUpdate){
                    //修改
                    executeOperateSave();
                }else{
                    //获取开始时间之前状态为正常的考核周期
                    Map<Long, DynamicObject[]> lastPerfManagerMap = new HashMap<>(personBeginYearMap.size());
                    for (Map.Entry<Long, Date> longDateEntry : personBeginYearMap.entrySet()) {

                        DynamicObject[] beforeBeginYear = PerfManagerHelper.getBeforeBeginYear(longDateEntry.getValue(), Collections.singletonList(longDateEntry.getKey()), null);
                        lastPerfManagerMap.put(longDateEntry.getKey(), beforeBeginYear);
                    }

                    StringJoiner confirmMsg = new StringJoiner("，");
                    for (DynamicObject[] lastPerfManagerArray : lastPerfManagerMap.values()) {
                        for (DynamicObject lastPerfManager : lastPerfManagerArray) {
                            String personName = lastPerfManager.getDynamicObject(FormConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
                            LocalDateTime beginYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
                            LocalDateTime endYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
                            confirmMsg.add(StrFormatter.format("{}（周期：{}~{}）", personName, beginYear.getYear(), endYear.getYear()));

                        }
                    }
                    if(confirmMsg.length() > 0){
                        // 创建回调监听器，指定回调ID和处理此回调的插件（this）
                        ConfirmCallBackListener confirmCallBacks = new ConfirmCallBackListener(PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID, this);
                        // 弹出确认框
                        this.getView().showConfirm(StrFormatter.format("检测到本次新增的人员中存在【未结束】的考核周期，新周期新增成功后会自动结束上一周期，并将上一周期结束时间更新为当前新周期开始年前一年。请确认是否继续。{}", confirmMsg),
                                MessageBoxOptions.OKCancel,
                                ConfirmTypes.Default,
                                confirmCallBacks);
                    }else{
                        executeOperateSave();
                    }
                }

            }
        }
    }

    @Override
    public void confirmCallBack(MessageBoxClosedEvent messageBoxClosedEvent) {
        // 判断回调ID和用户点击的按钮
        if (PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID.equals(messageBoxClosedEvent.getCallBackId())
                && messageBoxClosedEvent.getResult() == MessageBoxResult.Yes) {
            executeOperateSave();
        }
    }

    private void executeOperateSave() {


        String isAddOrUpdate = ConvertUtil.toStr(this.getModel().getValue("nckd_isaddorupdate"));
        boolean isUpdate = "2".equalsIgnoreCase(isAddOrUpdate);
        DynamicObjectCollection perfManagerList = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
        List<Long> perfManagerIds = Collections.emptyList();
        Map<Long, DynamicObject> perfManagerMap = null;
        if(isUpdate){
            perfManagerIds = perfManagerList.stream()
                    .map(dynamicObject -> dynamicObject.getDynamicObject(PerfManagerFormConstant.PERFMANAGER_ENTITYID))
                    .filter(Objects::nonNull)
                    .map(perfManager -> perfManager.getLong(FormConstant.ID_KEY))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            DynamicObject[] byId = PerfManagerHelper.getById(perfManagerIds);
            perfManagerMap = Arrays.stream(byId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            perfManager -> perfManager.getLong(FormConstant.ID_KEY),
                            perfManager -> perfManager,
                            (existing, replacement) -> existing
                    ));
        }
        List<DynamicObject> savePerfManagerList = new ArrayList<>();

        //转换为考核周期实体
        for (DynamicObject dynamicObject : perfManagerList) {
            DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
            String personName = person.getString(FormConstant.NAME_KEY);
            LocalDateTime beginYear = DateUtil.toLocalDateTime(dynamicObject.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
            LocalDateTime endYear = DateUtil.toLocalDateTime(dynamicObject.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
            String description = dynamicObject.getString(PerfManagerFormConstant.DESCRIPTION_KEY);
            DynamicObject savePerfManager = null;
            if(isUpdate){
                //修改
                DynamicObject perfManager = dynamicObject.getDynamicObject(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
                long id = perfManager.getLong(FormConstant.ID_KEY);
                DynamicObject dbPerfManager = perfManagerMap.get(id);


                dbPerfManager.set(PerfManagerFormConstant.DESCRIPTION_KEY, description);
                LocalDateTime dbBeginYear = DateUtil.toLocalDateTime(dbPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
                LocalDateTime dbEndYear = DateUtil.toLocalDateTime(dbPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));

                boolean isCycleRangeChange = Boolean.FALSE;
                DynamicObjectCollection dbPerfManagerEntry = dbPerfManager.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
                if(!Objects.equals(dbBeginYear, beginYear)){
                    isCycleRangeChange = true;
                    dbPerfManager.set(PerfManagerFormConstant.NCKD_BEGINYEAR, DateUtil.toDate(beginYear));
                }
                if(!Objects.equals(dbEndYear, endYear)){
                    isCycleRangeChange = true;
                    dbPerfManager.set(PerfManagerFormConstant.NCKD_ENDYEAR, DateUtil.toDate(endYear));
                }
                Iterator<DynamicObject> iterator = dbPerfManagerEntry.iterator();
                while (iterator.hasNext()) {
                    DynamicObject entry = iterator.next();
                    Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
                    if (appraisalYear != null) {
                        LocalDateTime appraisalLocalDate = DateUtil.toLocalDateTime(appraisalYear);
                        long yearsDiff = appraisalLocalDate.getYear() - dbBeginYear.getYear();
                        // 判断年份是否在范围外
                        if (appraisalLocalDate.getYear() < beginYear.getYear() || appraisalLocalDate.getYear() > endYear.getYear()) {
                            // 删除不在范围内的考核结果记录
                            iterator.remove();
                        }
                    }
                }

                // 考核结果写回到分录，save操作的时候会将分录的结果写回到表头
                DynamicObject firstYearResult = dynamicObject.getDynamicObject(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT);
                DynamicObject secondYearResult = dynamicObject.getDynamicObject(PerfManagerFormConstant.NCKD_SECONDYEARRESULT);
                DynamicObject thirdYearResult = dynamicObject.getDynamicObject(PerfManagerFormConstant.NCKD_THIRDYEARRESULT);

                DynamicObject dbFirstYearResult = dbPerfManager.getDynamicObject(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT);
                DynamicObject dbSecondYearResult = dbPerfManager.getDynamicObject(PerfManagerFormConstant.NCKD_SECONDYEARRESULT);
                DynamicObject dbThirdYearResult = dbPerfManager.getDynamicObject(PerfManagerFormConstant.NCKD_THIRDYEARRESULT);

                // 判断跟数据库的有没有变化，有变化才写回到分录
               /* Long firstYearResultId = firstYearResult != null ? firstYearResult.getLong(FormConstant.ID_KEY) : null;
                Long dbFirstYearResultId = dbFirstYearResult != null ? dbFirstYearResult.getLong(FormConstant.ID_KEY) : null;
                if (!Objects.equals(firstYearResultId, dbFirstYearResultId) || isCycleRangeChange) {
                    updateAppraisalResult(dbPerfManagerEntry, beginYear, firstYearResult, 0);
                }

                Long secondYearResultId = secondYearResult != null ? secondYearResult.getLong(FormConstant.ID_KEY) : null;
                Long dbSecondYearResultId = dbSecondYearResult != null ? dbSecondYearResult.getLong(FormConstant.ID_KEY) : null;
                if (!Objects.equals(secondYearResultId, dbSecondYearResultId) || isCycleRangeChange) {
                    updateAppraisalResult(dbPerfManagerEntry, beginYear, secondYearResult, 1);
                }

                Long thirdYearResultId = thirdYearResult != null ? thirdYearResult.getLong(FormConstant.ID_KEY) : null;
                Long dbThirdYearResultId = dbThirdYearResult != null ? dbThirdYearResult.getLong(FormConstant.ID_KEY) : null;
                if (!Objects.equals(thirdYearResultId, dbThirdYearResultId) || isCycleRangeChange) {
                    updateAppraisalResult(dbPerfManagerEntry, beginYear, thirdYearResult, 2);
                }*/
                savePerfManager = dbPerfManager;
            }else{
                //新增
                savePerfManager = EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
                DynamicObjectUtils.copy(dynamicObject, savePerfManager);
                savePerfManager.set(FormConstant.NAME_KEY, StrFormatter.format("【{}】{}~{}的考核周期",personName,beginYear.getYear(),endYear.getYear()));
                DynamicObject empPosOrgRel = savePerfManager.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL);
                savePerfManager.set(PerfManagerFormConstant.NCKD_DEP, empPosOrgRel.getDynamicObject(FormConstant.ADMINORG));
            }
            savePerfManagerList.add(savePerfManager);
        }

        OperateOption option = OperateOption.create();
        option.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE+"");
        //告诉OP此次操作类型
        option.setVariableValue("isUpdate", isUpdate+"");

        OperationResult operationResult =   SaveServiceHelper.saveOperate(FormConstant.SAVE_OP, PerfManagerFormConstant.PERFMANAGER_ENTITYID, savePerfManagerList.toArray(new DynamicObject[0]), option);

        if (!operationResult.isSuccess()) {
            StringJoiner errorMsgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
            for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
                errorMsgJoiner.add(error.getMessage());
            }
            String errorMsg = errorMsgJoiner.toString();
            if(StringUtils.isBlank(errorMsg)){
                errorMsg = operationResult.getMessage();
            }
            throw new ValidationException(errorMsg);
        }else{
            this.getView().getParentView().showSuccessNotification("保存成功");
            this.getView().getParentView().invokeOperation(FormConstant.REFRESH_OP);
            this.getView().close();
        }
    }


    private void updateAppraisalResult(DynamicObjectCollection perfManagerEntry,
                                       LocalDateTime beginYear,
                                       DynamicObject result,
                                       int yearOffset) {
        boolean isExist = false;
        for (DynamicObject entry : perfManagerEntry) {
            Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
            if (appraisalYear != null) {
                LocalDateTime appraisalLocalDate = DateUtil.toLocalDateTime(appraisalYear);
                long yearsDiff = appraisalLocalDate.getYear() - beginYear.getYear();
                if (yearsDiff == yearOffset) {
                    entry.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, result);
                    isExist = true;
                    break;
                }
            }
        }

        if (!isExist) {
            DynamicObject entry = perfManagerEntry.addNew();
            entry.set(PerfManagerFormConstant.NCKD_APPRAISALYEAR,
                    DateUtil.toDate(DateUtil.addYears(beginYear, yearOffset)));
            entry.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, result);
        }
    }
}