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

import com.google.common.collect.Lists;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.entity.ExtendedDataEntity;
import kd.bos.entity.plugin.AddValidatorsEventArgs;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
import kd.bos.entity.plugin.args.RollbackOperationArgs;
import kd.bos.entity.validate.AbstractValidator;
import nckd.jxccl.base.common.constant.FormConstant;
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.JobLevelCalculatorService;
import nckd.jxccl.hr.psms.business.ManagerAllowanceService;
import nckd.jxccl.hr.psms.common.PositionStructureConstant;
import nckd.jxccl.hr.psms.helper.PositionFileHelper;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 在职人员初定-确认定级操作OP
 * @author W.Y.C
 * @date 2025/9/10 16:54
 * @version 1.0
 */
public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {

    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {
        e.addValidator(new AbstractValidator() {
            @Override
            public void validate() {
                if(!this.getValidateContext().getValidateResults().isSuccess()){
                    //前面的校验器失败跳过本校验器
                    return;
                }
                Date currentDate = new Date();

                Set<Long> personIds = new HashSet<>();
                Map<Long,Integer> personDataEntityMap = new HashMap<>();
                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                    DynamicObject data = rowDataEntity.getDataEntity();
                    //提取信息
                    List<BaseInitialData> servingInitialDataList = extractBasicInfo(data);
                    int dataEntityIndex = rowDataEntity.getDataEntityIndex();
                    // 检查人员ID重复
                    for (BaseInitialData servingInitialData : servingInitialDataList) {
                        if (servingInitialData.person != null) {
                            Long personId = servingInitialData.person.getLong(FormConstant.ID_KEY);
                            if (!personIds.add(personId)) {
                                Integer i = personDataEntityMap.get(personId);
                                if(i != null){
                                    //将上一个重复人员也标记为错误
                                    addFatalErrorMessage(getDataEntities()[i],
                                            StrFormatter.format("人员【{}】在列表中重复，请保留一条信息",
                                                    servingInitialData.person.getString(FormConstant.NAME_KEY)));
                                }
                                addFatalErrorMessage(rowDataEntity,
                                        StrFormatter.format("人员【{}】在列表中重复，请保留一条信息",
                                                servingInitialData.person.getString(FormConstant.NAME_KEY)));
                            }
                            personDataEntityMap.put(personId,dataEntityIndex);
                        }

                    }

                    for (BaseInitialData servingInitialData : servingInitialDataList) {
                        Date beginDate = servingInitialData.beginDate;
                        DynamicObject person = servingInitialData.person;
                        //------ 1.非空校验 ------
                        if(person == null){
                            addFatalErrorMessage(rowDataEntity,"请选择人员");
                            return;
                        }
                        if(PositionFileHelper.isInitial(person.getLong(FormConstant.ID_KEY))){
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】已初定，不能重复初定",person.getString(FormConstant.NAME_KEY)));
                        }
                        if(servingInitialData.empPosOrgRel == null){
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】无任职信息",person.getString(FormConstant.NAME_KEY)));
                        }
                        if (beginDate == null) {
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能为空",person.getString(FormConstant.NAME_KEY)));
                        }
                        BigDecimal allSumScore = servingInitialData.allSumScore;
                        if(allSumScore == null || allSumScore.compareTo(BigDecimal.ZERO) == 0){
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】请填写总积分",person.getString(FormConstant.NAME_KEY)));
                        }
                        DynamicObject positionHr = servingInitialData.positionHr;
                        DynamicObject jobSeq = servingInitialData.jobSeq;
                        if(positionHr == null){
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("无岗位，请检查当前人员【{}】任职的岗位信息",person.getString(FormConstant.NAME_KEY)));
                        }
                        if (positionHr != null && jobSeq == null) {
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("无职位序列，请检查当前人员【{}】任职的岗位【{}】是否有职位序列",person.getString(FormConstant.NAME_KEY),positionHr.getString(FormConstant.NAME_KEY)));
                        }

                        //------ 3、验证初定时间不能超过当前日期 ------
                        if (beginDate != null && beginDate.after(currentDate)) {
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能晚于当前日期，请检查输入的日期是否正确",person.getString(FormConstant.NAME_KEY)));
                        }

                        //------ 4.获取上年度绩效结果 ------
                        if(beginDate != null) {
                            LocalDateTime lastYearDateTime = DateUtil.minusYears(DateUtil.toLocalDateTime(beginDate), 1);
                            DynamicObject lastYearPerformanceResult = PerformanceManagerHelper.getPerformanceResult(person.getLong(FormConstant.ID_KEY), lastYearDateTime);
                            if (lastYearPerformanceResult == null) {
                                addFatalErrorMessage(rowDataEntity, StrFormatter.format("人员【{}】没有上年度考核结果，无法初定", person.getString(FormConstant.NAME_KEY)));
                            }
                        }
                    }

                }
            }
        });
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
        if(this.getOperationResult().isSuccess()) {
            //对应SHR：com.kingdee.shr.customer.web.handler.ContributeScore.PersonpositionfileListHandler#addNewPersonpositionfileInfo_older
            logger.info("【职位体系】-在职人员初定-开始");
            processServingInitial();

        }
    }

    @Override
    public void endOperationTransaction(EndOperationTransactionArgs e) {
        logger.info("【职位体系】-在职人员初定-完成");
    }

    @Override
    public void rollbackOperation(RollbackOperationArgs e) {
        logger.error("【职位体系】-在职人员初定-异常回滚");
    }

    /**
     * 处理单个在职人员初定
     */
    private void processServingInitial() {
        logger.info("【职位体系】-开始处理在职人员初定");
        List<DynamicObject> savePersonPosFileList = Lists.newArrayList();
        // 提取基本信息
        for (int i = 0; i < baseInitialData.size(); i++) {
            BaseInitialData data = baseInitialData.get(i);
            logger.info("【职位体系】-处理第{}个在职人员初定", i+1);
            
            String logPrefix = StrFormatter.format("【职位体系】-在职人员初定-人员【{}（{}）】",
                    data.person.getString(FormConstant.NAME_KEY),
                    data.person.getString(FormConstant.EMP_NUMBER_KEY));
            logger.info("{}-初定日期【{}】-职位序列【{}】-岗位【{}】-总积分【{}】",
                    logPrefix,
                    DateUtil.format(data.beginDate, DateUtil.NORM_DATE_PATTERN),
                    data.jobSeqName,
                    data.positionHr.getString(FormConstant.NAME_KEY),
                    data.allSumScore.toString());

            // 获取上年度绩效结果
            logger.info("{}-开始获取上年度绩效结果", logPrefix);
            getPreviousYearPerformance(data, logPrefix);

            // 获取学历、职称、技能对应的积分
            logger.info("{}-开始获取积分数据", logPrefix);
            ScoreData scoreData = getScoreData(data, logPrefix);

            // 计算累计积分池（生涯积分）
            logger.info("{}-开始计算累计积分池", logPrefix);
            BigDecimal sumScore = calculateSumScore(data.allSumScore, scoreData, logPrefix);

            // 如果是管理序列,则按职能序列进行初定
            logger.info("{}-开始处理职位序列转换", logPrefix);
            data.convertJobSeq = JobLevelCalculatorService.handleJobSeq(data.jobSeq);
            logger.info("{}-职位序列转换完成，convertJobSeq={}", logPrefix, data.convertJobSeq);

            // 计算职级
            //当考核结果为无时,职级定为最低级
            boolean useMinLevel = data.lastYearAppraisalResultEnum == nckd.jxccl.base.common.enums.AppraisalResultEnum.NONE;
            String perProTitleNumber = scoreData.dbProTitleLevel != null ? scoreData.dbProTitleLevel.getString(FormConstant.NUMBER_KEY) : null;
            String quaLevelNumber = scoreData.dbOcpQualLevel != null ? scoreData.dbOcpQualLevel.getString(FormConstant.NUMBER_KEY) : null;
            boolean threeElementMeet = JobLevelCalculatorService.checkThreeElementsRequirement(data.convertJobSeq, data.allSumScore, scoreData.dbProTitleLevel,
                    scoreData.dbOcpQualLevel, data.lastYearAppraisalResultEnum);
            logger.info("{}-计算职级参数: convertJobSeq={}, allSumScore={}, perProTitleNumber={}, quaLevelNumber={}, downgradeNum={}, useMinLevel={}, !threeElementMeet={}",
                       logPrefix, data.convertJobSeq, data.allSumScore, perProTitleNumber, quaLevelNumber, data.downgradeNum, useMinLevel, !threeElementMeet);
                       
            DynamicObject jobLeve = JobLevelCalculatorService.getJobLevel(
                    data.convertJobSeq, data.allSumScore, perProTitleNumber,
                    quaLevelNumber,  data.downgradeNum,useMinLevel,!threeElementMeet);
            logger.info("{}-职级计算完成，jobLeve={}", logPrefix, jobLeve);

            if(jobLeve != null) {
                // 构建职位档案并存入数据库
                logger.info("{}-开始创建并保存职位档案", logPrefix);
                DynamicObject savePersonPosFile = createAndSavePersonPosFile(data, scoreData, data.allSumScore, sumScore, jobLeve, logPrefix, "2");
                savePersonPosFileList.add(savePersonPosFile);
                //返回定级后的职级。张三：职位级为"初级（1）"
                setJobLevelResult(data.person, jobLeve);
                logger.info("{}-职位档案创建并保存完成", logPrefix);
            } else {
                logger.warn("{}-未能计算出有效职级，跳过创建职位档案", logPrefix);
            }
        }
        //职位津贴
        logger.info("【职位体系】-开始生成职位津贴，处理数量: {}", savePersonPosFileList.size());
        ManagerAllowanceService.generateMgrPostAllow(savePersonPosFileList);
        logger.info("【职位体系】-在职人员初定处理完成");
    }

    @Override
    protected void extractSpecificFields(BaseInitialData data, DynamicObject initialData) {
        // 总积分
        data.allSumScore = initialData.getBigDecimal(PositionStructureConstant.NCKD_ALLSUMSCORE);
        // 工作年限
        data.employmentYears = initialData.getInt(PositionStructureConstant.NCKD_EMPLOYMENTYEARS);
    }
    
}