package nckd.jxccl.opmc.pm.task;

import kd.bos.bd.pojo.CtrlStrategyEnum;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.operate.OperateOptionConst;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.exception.KDException;
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.schedule.executor.AbstractTask;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
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.QueryFieldBuilder;
import nckd.jxccl.base.common.utils.StrFormatter;
import nckd.jxccl.base.entity.helper.EntityHelper;
import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
import nckd.jxccl.base.org.helper.OrgHelper;
import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
import nckd.jxccl.opmc.pm.common.SalAdjTrackerConstant;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * 每月一号根据获取前两月的晋升数据，生成新的三年考评周期
 * @author W.Y.C
 * @date 2025/11/26 21:51
 * @version 1.0
 */
public class PromotionCycleGeneratorTask extends AbstractTask implements Plugin {

    private static final Log logger = LogFactory.getLog(PromotionCycleGeneratorTask.class);

    @Override
    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
        logger.info("开始执行晋升考核周期生成任务");
        
        try {
            //先查询由调动单生成的考核周期
            QueryFieldBuilder perfManagerQueryFieldBuilder = QueryFieldBuilder.create()
                    .add(FormConstant.SOURCEDATA);
            QFilter perfManagerFilter = new QFilter(FormConstant.SOURCEDATA, QCP.is_notnull, null)
                    //只查询数据来源：调动（晋升）
                    .and(FormConstant.INITDATASOURCE,QCP.equals,"3");
            logger.debug("查询已存在的晋升考核周期数据");
            DynamicObjectCollection perfManagerQuery = QueryServiceHelper.query(PerfManagerFormConstant.PERFMANAGER_ENTITYID, perfManagerQueryFieldBuilder.buildSelect(), new QFilter[]{perfManagerFilter});
            List<Long> sourcedataList = perfManagerQuery.stream()
                    .map(obj -> obj.getLong(FormConstant.SOURCEDATA))
                    .collect(Collectors.toList());
            logger.info("已存在{}条晋升考核周期数据", sourcedataList.size());

            //查询N月前的所有调动单
            QueryFieldBuilder transferApplyQueryFieldBuilder = QueryFieldBuilder.create()
                    .add(FormConstant.ID_KEY)
                    //调出岗位
                    .addIdNumberName("bb_po_position")
                    .addIdNumberName("bb_po_position","nckd_mgtlvldtl")
                    //调入岗位
                    .addIdNumberName("aposition")
                    .addIdNumberName("aposition","nckd_mgtlvldtl")
                    //调动人员
                    .addIdNumberName("bb_em_tid")
                    //实际调动日期
                    .add("b_effectivedate");

            Integer month = ConvertUtil.toInt(map.get("month"));
            if (month == null || month < 1) {
                month = 2; // 默认值
                logger.warn("未设置month参数，默认使用2个月前的数据");
            }
            
            LocalDateTime now = DateUtil.now();


            // 计算前两个月的开始和结束日期（不包括本月）
            LocalDateTime startDate = DateUtil.minusMonths(now, month);
            startDate = DateUtil.beginOfMonth(startDate); // 设置为月份第一天

            LocalDateTime endDate = DateUtil.minusMonths(now, 1);
            endDate = DateUtil.endOfMonth(endDate); // 设置为月份最后一天

            logger.info("查询调动单的时间范围: {} 至 {}", startDate, endDate);

            QFilter transferApplyFilter = QFilterCommonHelper.getBillStatusFilter()
                    .and("b_effectivedate", QCP.large_equals, DateUtil.toDate(startDate))
                    .and("b_effectivedate", QCP.less_equals, DateUtil.toDate(endDate))
                    .and(FormConstant.ID_KEY, QCP.not_in, sourcedataList);
            DynamicObjectCollection transferApplyFilterQuery = QueryServiceHelper.query(FormConstant.HDM_TRANSFERAPPLY, transferApplyQueryFieldBuilder.buildSelect(), new QFilter[]{transferApplyFilter});
            logger.info("查询到{}条调动单数据", transferApplyFilterQuery.size());

            //查询管理层级细项（由于管理层级细项的排序号在第三级，只能再查一次）
            List<Long> mgtLvldtlIdList = new ArrayList<>();
            for (DynamicObject transferApply : transferApplyFilterQuery) {
                mgtLvldtlIdList.add(transferApply.getLong(String.join(".", "bb_po_position", "nckd_mgtlvldtl", FormConstant.ID_KEY)));
                mgtLvldtlIdList.add(transferApply.getLong(String.join(".", "aposition", "nckd_mgtlvldtl", FormConstant.ID_KEY)));
            }
            DynamicObjectCollection mgtlvldtlQuery = QueryServiceHelper.query("nckd_hbss_mgtlvldtl",
                    QueryFieldBuilder.create().add(FormConstant.ID_KEY).add(FormConstant.NAME_KEY).add(FormConstant.NUMBER_KEY).add(FormConstant.NCKD_SORTNUM).buildSelect() ,
                    new QFilter[]{QFilterCommonHelper.getIdInFilter(mgtLvldtlIdList)});
            Map<Long, DynamicObject> mgtLvldtlMap = mgtlvldtlQuery.stream()
                    .collect(Collectors.toMap(
                            obj -> obj.getLong(FormConstant.ID_KEY),
                            obj -> obj
                    ));
            logger.debug("查询到{}条管理层级细项数据", mgtLvldtlMap.size());

            Long createOrg = OrgHelper.getCreateOrgList(SalAdjTrackerConstant.SALADJTRACKER_ENTITYID);
            MainEntityType bosOrgEntityType = EntityMetadataCache.getDataEntityType(FormConstant.BOS_ORG);
            DynamicObject org = new DynamicObject(bosOrgEntityType);
            org.set(FormConstant.ID_KEY, createOrg);

            List<DynamicObject> perfManagerList = new ArrayList<>(transferApplyFilterQuery.size());
            List<Long> personIdList = new ArrayList<>(transferApplyFilterQuery.size());
            for (DynamicObject transferApply : transferApplyFilterQuery) {
                Long personId = transferApply.getLong(String.join(".","bb_em_tid", FormConstant.ID_KEY));
                personIdList.add(personId);
            }
            if(!personIdList.isEmpty()) {
                //判断这些员工有没有考核周期，有考核周期又是晋升才需要生成新考核周期
                QueryFieldBuilder perfManagerByPersonQueryFieldBuilder = QueryFieldBuilder.create()
                        .addIdNumberName(FormConstant.NCKD_PERSON);
                QFilter perfManagerByPersonFilter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, personIdList);
                DynamicObjectCollection perfManagerByPersonQuery = QueryServiceHelper.query(PerfManagerFormConstant.PERFMANAGER_ENTITYID, perfManagerByPersonQueryFieldBuilder.buildSelect(), new QFilter[]{perfManagerByPersonFilter});
                List<Long> needPersonId = perfManagerByPersonQuery.stream()
                        .map(obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON,FormConstant.ID_KEY)))
                        .collect(Collectors.toList());

                int promotionCount = 0;
                personIdList.clear();
                for (DynamicObject transferApply : transferApplyFilterQuery) {
                    Long personId = transferApply.getLong(String.join(".", "bb_em_tid", FormConstant.ID_KEY));
                    if(needPersonId.contains(personId)) {
                        long id = transferApply.getLong(FormConstant.ID_KEY);
                        //调出岗位管理层级细项
                        String outPositionName = transferApply.getString(String.join(".", "bb_po_position", FormConstant.NAME_KEY));
                        long outMgtLvldtlId = transferApply.getLong(String.join(".", "bb_po_position", "nckd_mgtlvldtl", FormConstant.ID_KEY));
                        DynamicObject outMgtLvldtl = mgtLvldtlMap.get(outMgtLvldtlId);
                        int outIndex = -1;
                        if (outMgtLvldtl != null) {
                            outIndex = outMgtLvldtl.getInt(FormConstant.NCKD_SORTNUM);
                        } else {
                            logger.warn("调出岗位【{}】管理层级细项不存在，跳过此条处理：", outPositionName);
                            continue;
                        }
                        //调入岗位管理层级细项
                        String inPositionName = transferApply.getString(String.join(".", "aposition", FormConstant.NAME_KEY));
                        long inMgtLvldtlId = transferApply.getLong(String.join(".", "aposition", "nckd_mgtlvldtl", FormConstant.ID_KEY));
                        DynamicObject inMgtLvldtl = mgtLvldtlMap.get(inMgtLvldtlId);
                        int inIndex = -1;
                        if (inMgtLvldtl != null) {
                            inIndex = inMgtLvldtl.getInt(FormConstant.NCKD_SORTNUM);
                        } else {
                            logger.warn("调入岗位【{}】管理层级细项不存在，跳过此条处理：", inPositionName);
                            continue;
                        }
                        //调入部门的管理层级细项-调出部门的管理层级细项>0表示晋升
                        if (inIndex - outIndex > 0) {
                            promotionCount++;
                            LocalDateTime effectiveDate = DateUtil.toLocalDateTime(transferApply.getDate("b_effectivedate"));
                            logger.debug("检测到晋升记录：员工 {} 从 {} 晋升到 {}，生效日期: {}",
                                    transferApply.getString(String.join(".", "bb_em_tid", FormConstant.NAME_KEY)),
                                    outPositionName,
                                    inPositionName,
                                    effectiveDate);

                            DynamicObject newPerfManager = EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);

                            String personName = transferApply.getString(String.join(".", "bb_em_tid", FormConstant.NAME_KEY));
                            DynamicObject person = EntityHelper.newEntity(FormConstant.HRPI_EMPLOYEE, personId);
                            person.set(FormConstant.NAME_KEY, personName);
                            newPerfManager.set(FormConstant.CREATEORG_KEY, org);
                            newPerfManager.set(PerfManagerFormConstant.CTRLSTRATEGY_KEY, CtrlStrategyEnum.GLOBAL_SHARE.getCtrlStrategy());
                            newPerfManager.set(FormConstant.NCKD_PERSON, person);
                            LocalDateTime newBeginDate = DateUtil.addYears(effectiveDate, 1);
                            LocalDateTime newEndDate = DateUtil.addYears(newBeginDate, 2);
                            newPerfManager.set(PerfManagerFormConstant.NCKD_BEGINYEAR, DateUtil.toDate(newBeginDate));
                            newPerfManager.set(PerfManagerFormConstant.NCKD_ENDYEAR, DateUtil.toDate(newEndDate));
                            newPerfManager.set(PerfManagerFormConstant.DESCRIPTION_KEY, StrFormatter.format("晋升后（岗位：{}->{}，层级：{}->{}）生成新周期", outPositionName, inPositionName, outMgtLvldtl.getString(FormConstant.NAME_KEY), inMgtLvldtl.getString(FormConstant.NAME_KEY)));
                            newPerfManager.set(FormConstant.NAME_KEY, StrFormatter.format("【{}】{}~{}的考核周期", personName, newBeginDate.getYear(), newEndDate.getYear()));
                            newPerfManager.set(FormConstant.SOURCEDATA, id);
                            newPerfManager.set(FormConstant.INITDATASOURCE, "3");
                            perfManagerList.add(newPerfManager);
                            personIdList.add(personId);
                        }
                    }
                }
                logger.info("共检测到{}条晋升记录，生成{}条考核周期数据", promotionCount, perfManagerList.size());

                if (!perfManagerList.isEmpty()) {
                    //获取最新任职经历
                    logger.debug("开始查询员工任职经历信息");
                    DynamicObject[] dynamicObjects = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployees(personIdList);
                    Map<Long, DynamicObject> empPosOrgRelGroupMap = Arrays.stream(dynamicObjects)
                            .filter(obj -> obj != null && obj.getDynamicObject(FormConstant.EMPLOYEE_KEY) != null)
                            .collect(Collectors.toMap(
                                    obj -> obj.getDynamicObject(FormConstant.EMPLOYEE_KEY).getLong(FormConstant.ID_KEY),
                                    obj -> obj,
                                    (existing, replacement) -> existing
                            ));
                    logger.debug("查询到{}条员工任职经历信息", empPosOrgRelGroupMap.size());

                    for (DynamicObject perfManager : perfManagerList) {
                        DynamicObject person = perfManager.getDynamicObject(FormConstant.NCKD_PERSON);
                        DynamicObject empPosOrgRel = empPosOrgRelGroupMap.get(person.getLong(FormConstant.ID_KEY));
                        perfManager.set(FormConstant.NCKD_EMPPOSORGREL, empPosOrgRel);
                        perfManager.set(FormConstant.NCKD_DEP, empPosOrgRel.getDynamicObject(FormConstant.ADMINORG));
                    }

                    OperateOption addPerfManagerOption = OperateOption.create();
                    addPerfManagerOption.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE + "");
                    addPerfManagerOption.setVariableValue("cyclegenerate", Boolean.TRUE + "");
                    logger.info("开始保存{}条考核周期数据", perfManagerList.size());
                    OperationResult addPerfManagerResult = SaveServiceHelper.saveOperate(FormConstant.SAVE_OP, PerfManagerFormConstant.PERFMANAGER_ENTITYID, perfManagerList.toArray(new DynamicObject[0]), addPerfManagerOption);

                    if (!addPerfManagerResult.isSuccess()) {
                        StringJoiner errorMsg = new StringJoiner(StrFormatter.LINE_SEPARATOR);
                        for (IOperateInfo error : addPerfManagerResult.getAllErrorOrValidateInfo()) {
                            errorMsg.add(error.getMessage());
                        }
                        logger.error("生成考核周期失败，原因：{}", errorMsg);
                        throw new ValidationException("生成考核周期失败，原因：" + errorMsg);
                    }
                    logger.info("成功保存{}条考核周期数据", perfManagerList.size());

                } else {
                    logger.info("没有需要生成的考核周期数据");
                }
            } else {
                logger.info("没有需要生成的考核周期数据");
            }
            
        } catch (Exception e) {
            logger.error("执行晋升考核周期生成任务时发生异常", e);
            throw e;
        }
        
        logger.info("完成执行晋升考核周期生成任务");
    }
}