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

import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.ExtendedDataEntity;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperateErrorInfo;
import kd.bos.entity.operate.result.OperationResult;
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.plugin.args.EndOperationTransactionArgs;
import kd.bos.entity.validate.AbstractValidator;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
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.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.base.org.helper.OrgHelper;
import nckd.jxccl.hr.psms.common.PositionStructureConstant;
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.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * 新建管理人员任命
 * 实体标识：nckd_mgrappointmgmt
 * @author W.Y.C
 * @date 2025/12/4 21:25
 * @version 1.0
 */
public class NewAppointMentOpPlugin extends AbstractOperationServicePlugIn implements Plugin {

    @Override
    public void onPreparePropertys(PreparePropertysEventArgs e) {

        e.getFieldKeys().addAll(this.billEntityType.getAllFields().keySet());
    }

    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {
        e.addValidator(new AbstractValidator() {
            @Override
            public void validate() {
                List<Long> personIdList = new ArrayList<>();
                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                    DynamicObject data = rowDataEntity.getDataEntity();
                    long personId = data.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
                    personIdList.add(personId);

                    DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
                    if (person != null) {
                        //设置每行对应的员工名称，用于准确显示每个错误属于哪个员工的
                        getOperationResult().getCustomData().put("DataEntityIndex_" + rowDataEntity.getDataEntityIndex(), "【" + person.getString(FormConstant.NAME_KEY) + "】");
                    }
                }

                Map<Long, List<DynamicObject>> mgrAppointMgmtMap = new HashMap<>();
                //查询管理人员任命
                QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                        .add(FormConstant.ID_KEY)
                        .add(PositionStructureConstant.NCKD_BEGINDATE)
                        .add(PositionStructureConstant.NCKD_ENDDATE)
                        .add(PositionStructureConstant.NCKD_APPOINTSTATUS)
                        .addIdNumberName(PositionStructureConstant.NCKD_PERSON);
                QFilter qFilter = new QFilter(PositionStructureConstant.NCKD_PERSON, QCP.in, personIdList);
                qFilter.and(PositionStructureConstant.NCKD_TYPESTATE, QCP.equals, TypeStateEnum.MANAGEMENT_SEQUENCE_EMPLOYMENT.getCode());
                DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.NCKD_PERSONPOSFILE, queryFieldBuilder.buildSelect(), new QFilter[]{});
                // 按用户ID分组
                mgrAppointMgmtMap = query.stream()
                        .collect(Collectors.groupingBy(
                                obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY))
                        ));

                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                    DynamicObject data = rowDataEntity.getDataEntity();
                    DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
                    if(person == null){
                        this.addErrorMessage(rowDataEntity, "请选择员工。");
                        continue;
                    }
                    long personId = person.getLong(FormConstant.ID_KEY);
                    String personName = person.getString(FormConstant.NAME_KEY);
                    if(data.getDate(PositionStructureConstant.NCKD_BEGINDATE) == null){
                        this.addErrorMessage(rowDataEntity, StrFormatter.format("【{}】的开始日期不能为空。", personName));
                        continue;
                    }

                    //管理人员任命校验
                    List<DynamicObject> dbmgrAppointMgmtList = mgrAppointMgmtMap.get(personId);
                    if (dbmgrAppointMgmtList != null) {
                        //1、判断有没有状态为【任命中=1】中的
                        boolean hasAppointingStatus = dbmgrAppointMgmtList.stream()
                                .anyMatch(obj -> "1".equals(obj.getString(PositionStructureConstant.NCKD_APPOINTSTATUS)));
                        if (hasAppointingStatus) {
                            this.addErrorMessage(rowDataEntity, StrFormatter.format("存在状态为【{}】的记录，不能任命。", "任命中"));
                        }

                        //2、判断有没有任命日期在有效时间内的
                        if (!hasAppointingStatus) {
                            Date beginDate = data.getDate(PositionStructureConstant.NCKD_BEGINDATE);

                            Optional<DynamicObject> lastAppointment = dbmgrAppointMgmtList.stream()
                                    .filter(obj -> {
                                        Date endDate = obj.getDate(PositionStructureConstant.NCKD_ENDDATE);
                                        // 新的任命开始时间必须在上一条记录的结束时间之后
                                        return endDate != null && beginDate != null && !beginDate.after(endDate);
                                    })
                                    .findFirst();

                            if (lastAppointment.isPresent()) {
                                DynamicObject appointment = lastAppointment.get();
                                Date endDate = appointment.getDate(PositionStructureConstant.NCKD_ENDDATE);
                                String periodMessage = StrFormatter.format("新的任命开始时间不能早于或等于上一任命的结束时间【{}】。",
                                        endDate != null ? DateUtil.format(endDate, "yyyy-MM-dd") : "");
                                // 提示用户时间段信息
                                this.addErrorMessage(rowDataEntity, periodMessage);
                            }
                        }

                    }
                }
            }
        });
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
        List<Long> personidList = new ArrayList<>();
        for (DynamicObject dataEntity : e.getDataEntities()) {
            long personId = dataEntity.getLong(String.join(".", PositionStructureConstant.NCKD_PERSON, FormConstant.ID_KEY));
            personidList.add(personId);
        }
        DynamicObject[] empPosOrgRelArray = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployees(personidList);
        Map<Long, DynamicObject> empPosOrgRelMap = Arrays.stream(empPosOrgRelArray)
                .collect(Collectors.toMap(
                        empPosOrgRelObj -> empPosOrgRelObj.getLong(String.join(".", PositionStructureConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
                        empPosOrgRelObj -> empPosOrgRelObj,
                        (existing, replacement) -> replacement // 如果有重复的key，使用新的值替换旧的值
                ));
        List<DynamicObject> newEntityList = new ArrayList<>();


        for (DynamicObject entry : e.getDataEntities()) {
            DynamicObject newEntity = EntityHelper.newEntity(PositionStructureConstant.NCKD_PERSONPOSFILE);
            DynamicObject person = entry.getDynamicObject(PositionStructureConstant.NCKD_PERSON);
            long personId = person.getLong(FormConstant.ID_KEY);
            String personName = person.getString(FormConstant.NAME_KEY);
            DynamicObject empPosOrgRel = empPosOrgRelMap.get(personId);

            newEntity.set(FormConstant.NCKD_PERSON, entry.get(FormConstant.NCKD_PERSON));
            Date beginDate = entry.getDate(PositionStructureConstant.NCKD_BEGINDATE);
            LocalDateTime beginDateDateTime = DateUtil.toLocalDateTime(beginDate);
            newEntity.set(PositionStructureConstant.NCKD_BEGINDATE, beginDate);
            newEntity.set(PositionStructureConstant.NCKD_TYPESTATE, TypeStateEnum.MANAGEMENT_SEQUENCE_EMPLOYMENT.getCode());
            newEntity.set(PositionStructureConstant.NCKD_DEP, empPosOrgRel.get(PositionStructureConstant.ADMINORG));
            newEntity.set(PositionStructureConstant.NCKD_POSITIONHR, empPosOrgRel.get(PositionStructureConstant.POSITION_KEY));
            newEntity.set(PositionStructureConstant.NCKD_EXECUTEYEAR, beginDateDateTime.getYear());
            newEntity.set(PositionStructureConstant.NCKD_APPOINTSTATUS, "1");
            newEntity.set(FormConstant.CREATOR_KEY, UserServiceHelper.getCurrentUserId());
            newEntity.set(FormConstant.DESCRIPTION_KEY, entry.get(FormConstant.DESCRIPTION_KEY));
            newEntityList.add(newEntity);
        }
        OperateOption operateOption = OperateOption.create();
        operateOption.setVariableValue(PositionStructureConstant.NCKD_TYPESTATE, TypeStateEnum.MANAGEMENT_SEQUENCE_EMPLOYMENT.getCode());
        OperationResult operationResult = SaveServiceHelper.saveOperate(PositionStructureConstant.PERSONPOSFILE_ENTITYID, newEntityList.toArray(new DynamicObject[0]), operateOption);

        if(operationResult != null && !operationResult.isSuccess()){
            StringJoiner errorMsgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
            if(operationResult.getAllErrorOrValidateInfo() != null && !operationResult.getAllErrorOrValidateInfo().isEmpty()){
                Iterator<IOperateInfo> iterator = operationResult.getAllErrorOrValidateInfo().iterator();
                while (iterator.hasNext()) {
                    IOperateInfo operateInfo = iterator.next();
                    if(operateInfo instanceof OperateErrorInfo){
                        OperateErrorInfo operateErrorInfo = (OperateErrorInfo) operateInfo;
                        int dataEntityIndex = operateErrorInfo.getDataEntityIndex();
                        String prefix = operationResult.getCustomData().get("DataEntityIndex_" + dataEntityIndex);
                        if(StringUtils.isNotBlank(prefix)){
                            operateErrorInfo.setMessage(prefix + operateErrorInfo.getMessage());
                        }
                    }
                    errorMsgJoiner.add(operateInfo.getMessage());
                }
            }
            // 如果没有具体的错误详情，则使用操作结果中的通用消息
            if (StringUtils.isBlank(operationResult.getMessage())) {
                errorMsgJoiner.add(operationResult.getMessage());
            }
            throw new ValidationException(errorMsgJoiner.toString());
        }
    }

    @Override
    public void endOperationTransaction(EndOperationTransactionArgs e) {
        for (DynamicObject dataEntity : e.getDataEntities()) {
            long id = dataEntity.getLong(FormConstant.ID_KEY);
            DynamicObject dynamicObject = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
            if(dynamicObject != null) {
                this.getOperationResult().getCustomData().put(id + "", "【" + dynamicObject.getString(FormConstant.NAME_KEY) + "】");
            }
        }
    }
}