package nckd.jxccl.hr.ijp.plugin.operate;

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.dataentity.utils.ObjectUtils;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.MainEntityType;
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.PreparePropertysEventArgs;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
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.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.ijp.TalentTypeEnum;
import nckd.jxccl.base.common.exception.ValidationException;
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.hr.ijp.common.IntJobPostConstant;
import nckd.jxccl.hr.psms.common.PositionStructureConstant;

import java.util.ArrayList;
import java.util.Arrays;
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;

/**
* 内部人力资源市场-三类人员记录生成-反审批
* 实体标识：nckd_intjobpost
* @author W.Y.C
* @date 2026/1/8 21:34
* @version 1.0
*/
public class IntJobPostUnAuditedOpPlugin extends AbstractOperationServicePlugIn implements Plugin {

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

    @Override
    public void onPreparePropertys(PreparePropertysEventArgs e) {
        e.getFieldKeys().addAll(billEntityType.getAllFields().keySet());
    }


    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {

        List<Long> personIds = new ArrayList<>();
        List<Long> entityIds = new ArrayList<>();
        for (DynamicObject dataEntity : e.getDataEntities()) {
            DynamicObjectCollection entryEntity = dataEntity.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
            for (DynamicObject entry : entryEntity) {
                DynamicObject person = entry.getDynamicObject(PositionStructureConstant.NCKD_PERSON);
                boolean isEnter = entry.getBoolean(IntJobPostConstant.NCKD_ISENTER);
                if(isEnter){
                    personIds.add(person.getLong(IntJobPostConstant.ID_KEY));
                }
                entityIds.add(entry.getLong(IntJobPostConstant.ID_KEY));
            }
        }
        Map<Long, DynamicObject> empPosOrgRelMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
        Map<Long, DynamicObject> latestRecordMap = getLatestRecordIdsByPersons(personIds, entityIds);
        Map<Long, DynamicObject> latestLocusByPerson = findLatestLocusByPerson(personIds);
        List<DynamicObject> savedRecords = new ArrayList<>();
        List<DynamicObject> savedLocus = new ArrayList<>();
        for (DynamicObject dataEntity : e.getDataEntities()) {
            Date auditDate = dataEntity.getDate(IntJobPostConstant.AUDIT_DATE_KEY);
            String talentType = dataEntity.getString(IntJobPostConstant.NCKD_TALENTTYPE);
            TalentTypeEnum talentTypeEnum = TalentTypeEnum.getByCode(talentType);
            DynamicObjectCollection entryEntity = dataEntity.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
            for (DynamicObject entry : entryEntity) {
                long id = entry.getLong(IntJobPostConstant.ID_KEY);
                boolean isEnter = entry.getBoolean(IntJobPostConstant.NCKD_ISENTER);
                long personId = entry.getLong(String.join(".", IntJobPostConstant.NCKD_PERSON, IntJobPostConstant.ID_KEY));
                String name = entry.getString(String.join(".", IntJobPostConstant.NCKD_PERSON, IntJobPostConstant.NAME_KEY));
                // --- A. 恢复旧记录 ---
                // 逻辑：找到该单据对应的“上一条”记录。
                // 实际上就是找那些被“此单据”截断的记录。
                DynamicObject prevRecord = latestRecordMap.get(personId);
                if(prevRecord != null) {
                    // 还原备份的值
                    prevRecord.set(IntJobPostConstant.NCKD_TOFOURDATE,prevRecord.get(IntJobPostConstant.NCKD_OLDTOFOURDATE));
                    // 只有当备份状态不为空时才还原，否则保持原样 (NVL逻辑)
                    if (prevRecord.get(IntJobPostConstant.NCKD_OLDSTATE) != null) {
                        prevRecord.set(IntJobPostConstant.NCKD_STATE, prevRecord.get(IntJobPostConstant.NCKD_OLDSTATE));
                    }
                    prevRecord.set(IntJobPostConstant.NCKD_ISCURRENTNEWEST, Boolean.TRUE);
                    savedRecords.add(prevRecord);
                }

                // --- B. 恢复旧轨迹 ---
                DynamicObject prevLocus  = latestLocusByPerson.get(personId);
                if (prevLocus != null) {
                    prevLocus.set(IntJobPostConstant.NCKD_ENDDATE,prevLocus.get(IntJobPostConstant.NCKD_OLDENDDAY));
                    prevLocus.set(IntJobPostConstant.NCKD_ISCURRENTNEWEST,Boolean.TRUE);
                    savedLocus.add(prevLocus);
                }

            }
        }

        // --- A. 恢复旧记录 ---
        // 逻辑：找到该单据对应的“上一条”记录。
        // 实际上就是找那些被“此单据”截断的记录。







        // --- A. 处理旧记录 ---
        // 1. 查询该员工最近的一条记录（排除当前单据产生的记录，按创建时间倒序取第一条）


        //1、阶段1：备份原有记录
        // 条件：单据中要进入市场(CFIsenter=1)的员工 + 他们最新的记录 + 记录来源不是当前单据
        //目的：为反审批时恢复数据做准备

        //阶段2：关闭原记录
        //逻辑：一个员工只能有一条活跃记录(FIsSingle=1)
        //状态变化：1(在市场中) → 4(退出市场)

        //阶段3：创建新记录
        //新记录状态：FIsSingle=1, CFInsidehrRecordState='1'

        //阶段3：特殊处理
        //A类员工：有预计退出时间（1年后）
        //非A类员工：预计退出时间为null

    }

    /**
     * 获取每个人员最新一条记录
     * @param personIds 人员ID
     * @param entityIds 分录ID
     * @return: java.util.Map<java.lang.Long, java.util.List < kd.bos.dataentity.entity.DynamicObject>>
     * @author W.Y.C
     * @date: 2026/01/13 15:56
     */
    public Map<Long, DynamicObject> getLatestRecordIdsByPersons(List<Long> personIds,List<Long> entityIds) {
        QueryFieldBuilder intJobPostRecord = QueryFieldBuilder.create().add(IntJobPostConstant.ID_KEY)
                .add(FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY,FormConstant.ID_KEY)
                .add(IntJobPostConstant.NCKD_ISCURRENTNEWEST)
                .orderDesc(IntJobPostConstant.CREATE_TIME_KEY);
        QFilter filter = new QFilter(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY), QCP.in, personIds)
                .and(IntJobPostConstant.NCKD_INTJOBPOSTENTRY,QCP.not_in,entityIds);
        DynamicObjectCollection records = QueryServiceHelper.query(IntJobPostConstant.INTJOBPOSTRECORD_ENTITYID, intJobPostRecord.buildSelect(), new QFilter[]{filter});
        Set<Long> uniquePersonIds = new HashSet<>();
        List<Long> result = new ArrayList<>();
        for (DynamicObject record : records) {
            Long personId = record.getLong(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
            if (uniquePersonIds.add(personId)) { // 如果是新的personId，添加到结果中
                result.add(record.getLong(IntJobPostConstant.ID_KEY));
            }
        }
        MainEntityType intJobPostRecordEntityType = EntityMetadataCache.getDataEntityType(IntJobPostConstant.INTJOBPOSTRECORD_ENTITYID);
        DynamicObject[] load = BusinessDataServiceHelper.load(result.toArray(new Long[0]), intJobPostRecordEntityType);
        return Arrays.stream(load)
                .collect(Collectors.toMap(
                        obj -> obj.getLong(String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
                        obj -> obj
                ));
    }

    /**
     * 查询最近的轨迹
     * @param personIds 人员ID
     * @return: java.util.Map<java.lang.Long, java.util.List < kd.bos.dataentity.entity.DynamicObject>>
     * @author W.Y.C
     * @date: 2026/01/13 15:56
     */
    public Map<Long, DynamicObject> findLatestLocusByPerson(List<Long> personIds) {
        QueryFieldBuilder intJobPostLocus = QueryFieldBuilder.create().add(IntJobPostConstant.ID_KEY)
                .add(FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY,FormConstant.ID_KEY)
                .add(IntJobPostConstant.NCKD_ISCURRENTNEWEST)
                .orderDesc(IntJobPostConstant.CREATE_TIME_KEY);
        QFilter filter = new QFilter(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY), QCP.in, personIds);
        DynamicObjectCollection records = QueryServiceHelper.query(IntJobPostConstant.INTJOBPOSTLOCUS_ENTITYID, intJobPostLocus.buildSelect(), new QFilter[]{filter});
        Set<Long> uniquePersonIds = new HashSet<>();
        List<Long> result = new ArrayList<>();
        for (DynamicObject record : records) {
            Long personId = record.getLong(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
            if (uniquePersonIds.add(personId)) { // 如果是新的personId，添加到结果中
                result.add(record.getLong(IntJobPostConstant.ID_KEY));
            }
        }
        MainEntityType intJobPostLocusEntityType = EntityMetadataCache.getDataEntityType(IntJobPostConstant.INTJOBPOSTLOCUS_ENTITYID);
        DynamicObject[] load = BusinessDataServiceHelper.load(result.toArray(new Long[0]), intJobPostLocusEntityType);
        return Arrays.stream(load)
                .collect(Collectors.toMap(
                        obj -> obj.getLong(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
                        obj -> obj
                ));
    }
}