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.exception.ValidationException;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.StrFormatter;
import nckd.jxccl.hr.psms.business.JobLevelCalculatorService;
import nckd.jxccl.hr.psms.business.ManagerAllowanceService;
import nckd.jxccl.hr.psms.helper.PositionFileHelper;

import java.math.BigDecimal;
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;

/**
 * 新入职人员初定-确认定级操作OP
 * @author W.Y.C
 * @date 2025/9/10 16:54
 * @version 1.0
 */
public class NewHireInitialOperationPlugIn 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> newHireInitialDataList =  extractBasicInfo(data);

                    int dataEntityIndex = rowDataEntity.getDataEntityIndex();
                    // 检查人员ID重复
                    for (BaseInitialData newHireInitialData : newHireInitialDataList) {
                        if (newHireInitialData.person != null) {
                            Long personId = newHireInitialData.person.getLong(FormConstant.ID_KEY);
                            if (!personIds.add(personId)) {
                                Integer i = personDataEntityMap.get(personId);
                                if(i != null){
                                    //将上一个重复人员也标记为错误
                                    addFatalErrorMessage(getDataEntities()[i],
                                            StrFormatter.format("人员【{}】在列表中重复，请保留一条信息",
                                                    newHireInitialData.person.getString(FormConstant.NAME_KEY)));
                                }
                                addFatalErrorMessage(rowDataEntity,
                                        StrFormatter.format("人员【{}】在列表中重复，请保留一条信息",
                                                newHireInitialData.person.getString(FormConstant.NAME_KEY)));
                            }
                            personDataEntityMap.put(personId,dataEntityIndex);
                        }
                    }



                    for (BaseInitialData newHireInitialData : newHireInitialDataList) {
                        Date beginDate = newHireInitialData.beginDate;
                        DynamicObject person = newHireInitialData.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(newHireInitialData.empPosOrgRel == null){
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】无任职信息",person.getString(FormConstant.NAME_KEY)));
                        }
                        if (beginDate == null) {
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能为空",person.getString(FormConstant.NAME_KEY)));
                        }
                        DynamicObject positionHr = newHireInitialData.positionHr;
                        DynamicObject jobSeq = newHireInitialData.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(newHireInitialData.joinComDate == null){
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("无本次加入集团日期，请检查当前人员【{}】服务年限信息",person.getString(FormConstant.NAME_KEY)));
                        }
                        if (newHireInitialData.joinComDate != null && newHireInitialData.joinComDate.after(beginDate)) {
                            addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能早于本次加入集团日期，本次加入集团时间：【{}】",person.getString(FormConstant.NAME_KEY),DateUtil.format(newHireInitialData.joinComDate, DateUtil.NORM_DATE_PATTERN)));
                        }
                        if (beginDate != null && beginDate.after(currentDate)) {
                            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
            logger.info("【职位体系】-新入职人员初定-开始");
            processNewHireInitialData();
        }
    }

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

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

    /**
     * 处理单个在职人员初定
     */
    private void processNewHireInitialData() {
        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));

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

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

            // 优秀生得2分
            BigDecimal excellentScore = data.isExcellent ? new BigDecimal(2) : BigDecimal.ZERO;

            // 累计总积分 = 学历分 + 职称/技能分 + 优秀生分
            BigDecimal allSumScore = scoreData.educationScore.add(scoreData.proTitleScore).add(scoreData.perOcpQualScore).add(excellentScore);
            logger.info("{}-学历分 + 职称/技能分 + 优秀生分 = {}", logPrefix, allSumScore);
            // 计算累计积分池（生涯积分）
            logger.info("{}-开始计算累计积分池", logPrefix);
            BigDecimal sumScore = calculateSumScore(allSumScore, scoreData, logPrefix);

            // 计算职级
            //当考核结果为无时,职级定为最低级
            boolean useMinLevel = data.lastYearAppraisalResultEnum == nckd.jxccl.base.common.enums.AppraisalResultEnum.NONE;
            // 如果是管理序列,则按职能序列进行初定
            logger.info("{}-开始处理职位序列转换", logPrefix);
            data.convertJobSeq = JobLevelCalculatorService.handleJobSeq(data.jobSeq);
            logger.info("{}-职位序列转换完成，convertJobSeq={}", logPrefix, data.convertJobSeq);
            
            //【三期需求】-不满足三要素（聘任职称/技能、考核结果、积分）按"无职级"初定
            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, allSumScore, scoreData.dbProTitleLevel,
                    scoreData.dbOcpQualLevel, data.lastYearAppraisalResultEnum);
                    
            logger.info("{}-计算职级参数: convertJobSeq={}, allSumScore={}, perProTitleNumber={}, quaLevelNumber={}, downgradeNum={}, useMinLevel={}, !threeElementMeet={}",
                       logPrefix, data.convertJobSeq, allSumScore, perProTitleNumber, quaLevelNumber, data.downgradeNum, useMinLevel, !threeElementMeet);

            DynamicObject jobLeve = JobLevelCalculatorService.getJobLevel(
                    data.convertJobSeq, allSumScore, perProTitleNumber,
                    quaLevelNumber,data.downgradeNum,useMinLevel,!threeElementMeet);
            logger.info("{}-职级计算完成，jobLeve={}", logPrefix, jobLeve);
            
            if(jobLeve != null) {
                // 构建职位档案并存入数据库
                logger.info("{}-开始创建并保存职位档案", logPrefix);
                DynamicObject savePersonPosFile = createAndSavePersonPosFile(data, scoreData, allSumScore, sumScore, jobLeve, logPrefix, "1");
                savePersonPosFileList.add(savePersonPosFile);
                //返回定级后的职级
                setJobLevelResult(data.person, jobLeve);
                logger.info("{}-职位档案创建并保存完成", logPrefix);

                //TODO 【待修改】-职位体系-这里可能有协同，初定完成后需要将待办任务置为已完成
            } else {
                logger.warn("{}-未能计算出有效职级，跳过创建职位档案", logPrefix);
            }
        }
        //职位津贴
        logger.info("【职位体系】-开始生成职位津贴，处理数量: {}", savePersonPosFileList.size());
        ManagerAllowanceService.generateMgrPostAllow(savePersonPosFileList);
        logger.info("【职位体系】-新入职人员初定处理完成");

    }

    @Override
    protected void extractSpecificFields(BaseInitialData data, DynamicObject initialData) {
    }
}
