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

import kd.bos.common.enums.EnableEnum;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.ExtendedDataEntity;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.AddValidatorsEventArgs;
import kd.bos.entity.plugin.PreparePropertysEventArgs;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
import kd.bos.entity.validate.AbstractValidator;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
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.orm.helper.QFilterCommonHelper;
import nckd.jxccl.hr.psms.business.ManagerAllowanceService;
import nckd.jxccl.hr.psms.common.PositionStructureConstant;
import nckd.jxccl.hr.psms.helper.PositionFileHelper;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;

/**
* 年度调整【生效】OP
* @author W.Y.C
* @date 2025/10/14 20:45
* @version 1.0
*/
public class AnnualEffectiveOpPlugin extends AbstractOperationServicePlugIn implements Plugin {

    /** 需要生效的数据（key：id，value：生效日期）*/
    private Map<Long,Date> dataMap;
    private StringJoiner message = new StringJoiner(StrFormatter.LINE_SEPARATOR);

    @Override
    public void onPreparePropertys(PreparePropertysEventArgs e) {
        super.onPreparePropertys(e);
    }

    @Override
    public void onAddValidators(AddValidatorsEventArgs e){
        dataMap = new HashMap<>();
        e.addValidator(new AbstractValidator() {
            @Override
            public void validate() {
                if(!getOperationResult().isSuccess()){
                    return;
                }
                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                    int dataEntityIndex = rowDataEntity.getDataEntityIndex();
                    DynamicObject data = rowDataEntity.getDataEntity();
                    List<Long> personIds = new ArrayList<Long>();
                    Date adjustDate = data.getDate(PositionStructureConstant.NCKD_BEGINDATE);
                    if(adjustDate == null){
                        addFatalErrorMessage(rowDataEntity,"生效日期不能为空");
                    }else {
                        LocalDateTime adjustDateTime = DateUtil.toLocalDateTime(adjustDate);
                        if (adjustDateTime.getMonthValue() == 1 && adjustDateTime.getDayOfMonth() == 1) {
                            //前端只选年份，这里默认为XXX-07-01
                            adjustDate = DateUtil.toDate(adjustDateTime.withMonth(7).withDayOfMonth(1));
                        }

                        DynamicObjectCollection mulSelectPersonPosFile = data.getDynamicObjectCollection(PositionStructureConstant.NCKD_MULSELEPERSONPOSFILE);
                        if(mulSelectPersonPosFile.isEmpty()){
                            addFatalErrorMessage(rowDataEntity,"请选择要“生效”的职位档案");
                        }
                        //获取多选基础资料
                        for (DynamicObject item : mulSelectPersonPosFile) {
                            // 获取基础资料的动态对象（包含基础资料的详细信息，如名称、编码等）
                            DynamicObject mulData = item.getDynamicObject(FormConstant.BASEDATAID_KEY);
                            // 获取基础资料的ID（即基础资料本身的主键）
                            long id = item.getLong(FormConstant.FBASEDATAID_ID_KEY);
                            String adjustStatus = mulData.getString(PositionStructureConstant.NCKD_ADJUSSTATUS);
                            String typeState = mulData.getString(PositionStructureConstant.NCKD_TYPESTATE);
                            TypeStateEnum typeStateEnum = TypeStateEnum.getByCode(typeState);
                            DynamicObject person = mulData.getDynamicObject(FormConstant.NCKD_PERSON);

                            //校验是否是“年度调整”
                            if (TypeStateEnum.ANNUAL_ADJUSTMENT.getCode().equalsIgnoreCase(typeState)) {
                                //校验是否是未生效的
                                if (!EnableEnum.YES.getCode().equals(adjustStatus)) {
                                    //只有未生效的才需要执行生效
                                    personIds.add(person.getLong(FormConstant.ID_KEY));
                                    dataMap.put(id, adjustDate);
                                }else{
                                    message.add(StrFormatter.format("【{}】的年度调整已是“生效”状态，忽略此条处理。", person.getString("name")));
                                }
                            }else{
                                //其他类型不能生效
                                addFatalErrorMessage(rowDataEntity, StrFormatter.format("【{}】不能生效，只有年度调整才能操作生效!", typeStateEnum.getName()));
                            }

                        }
                        //TODO 【待修改】-职位体系-测试完打开注释
                        /*if(!personIds.isEmpty()) {
                            List<DynamicObject> latsPersonPosFileByPerson = PositionStructureHelper.getLatsPersonPosFileByPerson(null, personIds.toArray(new Long[0]));
                            for (DynamicObject personPosFileByPerson : latsPersonPosFileByPerson) {
                                //校验生效日期是否在上一条档案之后
                                Date lastBeginDate = personPosFileByPerson.getDate(PositionStructureConstant.NCKD_BEGINDATE);
                                DynamicObject person = personPosFileByPerson.getDynamicObject(FormConstant.NCKD_PERSON);
                                String typeState = personPosFileByPerson.getString(PositionStructureConstant.NCKD_TYPESTATE);
                                TypeStateEnum typeStateEnum = TypeStateEnum.getByCode(typeState);
                                //判断当前日期是否早于或等于上一条档案的生效日期
                                if (adjustDate.compareTo(lastBeginDate) <= 0) {
                                    addFatalErrorMessage(rowDataEntity, StrFormatter.format("员工【{}】的生效日期必须在上一档案【{}】之后，上一档案生效日期【{}】；", person.getString(FormConstant.NAME_KEY),typeStateEnum.getName(),DateUtil.format(lastBeginDate, DateUtil.NORM_DATE_PATTERN)));
                                }
                            }
                        }*/
                    }
                }
                //所有情况校验完再校验是否被锁定，比较友好。不然先校验锁等用户解锁之后又发现其他情况而不能继续处理
                if(this.getValidateResult().isSuccess()) {
                    for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                        DynamicObject data = rowDataEntity.getDataEntity();
                        DynamicObjectCollection mulSelectPersonPosFile = data.getDynamicObjectCollection(PositionStructureConstant.NCKD_MULSELEPERSONPOSFILE);
                        for (DynamicObject item : mulSelectPersonPosFile) {
                            DynamicObject mulData = item.getDynamicObject(FormConstant.BASEDATAID_KEY);
                            String typeState = mulData.getString(PositionStructureConstant.NCKD_TYPESTATE);
                            TypeStateEnum typeStateEnum = TypeStateEnum.getByCode(typeState);
                            DynamicObject person = mulData.getDynamicObject(FormConstant.NCKD_PERSON);
                            //校验是否已被“锁定”
                            boolean lockStatus = mulData.getBoolean(PositionStructureConstant.NCKD_LOCKSTATUS);
                            if (lockStatus) {
                                addFatalErrorMessage(rowDataEntity, StrFormatter.format("【{}】的{}已“锁定”，不能生效。请先“解锁”。", person.getString(FormConstant.NAME_KEY), typeStateEnum.getName()));
                            }
                        }
                    }
                }
            }
        });
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                .add(FormConstant.ID_KEY)
                .add(PositionStructureConstant.NCKD_PERSON)
                .add(PositionStructureConstant.NCKD_BEGINDATE)
                .add(PositionStructureConstant.NCKD_ADJUSSTATUS)
                .add(PositionStructureConstant.NCKD_DEP)
                .add(PositionStructureConstant.NCKD_JOBLEVELHR)
                .add(PositionStructureConstant.NCKD_JOBSEQHR)
                .add(PositionStructureConstant.NCKD_PROTITLELEVEL)
                .addGroup(new String[]{FormConstant.NCKD_PERSON},FormConstant.ID_KEY);
        //本次需要生效的id
        Set<Long> ids = dataMap.keySet();
        DynamicObject[] load = BusinessDataServiceHelper.load(PositionStructureConstant.PERSONPOSFILE_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{QFilterCommonHelper.getIdInFilter(ids)});
        List<Long> personIds = new ArrayList<>();
        for (DynamicObject dynamicObject : load) {
            long id = dynamicObject.getLong(FormConstant.ID_KEY);
            Date date = dataMap.get(id);
            dynamicObject.set(PositionStructureConstant.NCKD_BEGINDATE, date);
            dynamicObject.set(PositionStructureConstant.NCKD_ADJUSSTATUS, EnableEnum.YES.getCode());
            personIds.add(dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY));
        }
        SaveServiceHelper.update(load);
        if(message.length() > 0){
            if (this.getOperationResult().getCustomData() == null) {
                this.getOperationResult().setCustomData(new HashMap<>());
            }
            this.getOperationResult().getCustomData().put("message", message.toString());
        }

        //将人员所有职位档案标记为非最新
        PositionFileHelper.markAsNotCurrentNewest(personIds.toArray(new Long[0]));
        //将当前人员最新档案（初定 或者 （年度调整 并且 已生效） 或者 (动态调整) 生效时间为最新的那一条）标记为最新的
        PositionFileHelper.markAsCurrentNewest(null,personIds.toArray(new Long[0]));
        //职位津贴
        ManagerAllowanceService.generateMgrPostAllow(Arrays.asList(load));
    }
}