package nckd.jxccl.opmc.pm.plugin.operate.result;

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.args.BeginOperationTransactionArgs;
import kd.bos.entity.validate.AbstractValidator;
import kd.bos.entity.validate.ErrorLevel;
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.OperationServiceHelper;
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.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.opmc.pm.common.PerfManagerFormConstant;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * 年度绩效结果明细-归档/撤销归档
 * 实体标识：nckd_annualperfdetail
 * @author W.Y.C
 * @date 2025/11/26 17:15
 * @version 1.0
 */
public class PerfArchiveOrUnArchiveOpPlugin extends AbstractOperationServicePlugIn implements Plugin {

    /**
     * 从日期对象中提取年份
     *
     * @param date 日期对象
     * @return 年份
     */
    private int getYearFromDate(Object date) {
        if (date == null) {
            return 0;
        }
        if (date instanceof LocalDate) {
            return ((LocalDate) date).getYear();
        }
        // 如果是其他日期类型，可以添加相应的处理逻辑
        return 0;
    }

    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {
        e.addValidator(new AbstractValidator() {
            @Override
            public void validate() {
                String operateKey = this.getOption().getVariableValue("operateKey");
                Map<Long,Integer> personMap = new HashMap<>();
                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                    DynamicObject data = rowDataEntity.getDataEntity();
                    DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
                    personMap.put(person.getLong(FormConstant.ID_KEY),rowDataEntity.getDataEntityIndex());

                }

                int year = DateUtil.now().getYear();
                year = year--;
                QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                        .addIdNumberName(FormConstant.NCKD_PERSON)
                        .add(PerfManagerFormConstant.NCKD_YEAR);
                QFilter qFilter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, personMap.keySet().toArray());
                //查找已归档的记录（状态为1）
                qFilter = qFilter.and(new QFilter(PerfManagerFormConstant.NCKD_ARCHIVESTATUS, QCP.equals, "1"));

                DynamicObjectCollection perfArchiveRecordQuery = QueryServiceHelper.query(PerfManagerFormConstant.PERFARCHIVERECORD_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
                // 创建已归档人员ID和年度的映射集合
                Set<String> archivedPersonYearPairs = perfArchiveRecordQuery.stream()
                        .map(obj -> obj.getLong(String.join( ".",FormConstant.NCKD_PERSON,FormConstant.ID_KEY)) + "_" + getYearFromDate(obj.getDate(PerfManagerFormConstant.NCKD_YEAR)))
                        .collect(Collectors.toSet());
                // 处理归档操作
                if(PerfManagerFormConstant.ARCHIVE_OP.equalsIgnoreCase(operateKey)){
                    for (DynamicObject dynamicObject : perfArchiveRecordQuery) {
                        String personName = dynamicObject.getString(String.join( ".",FormConstant.NCKD_PERSON,FormConstant.NAME_KEY));
                        long personId = dynamicObject.getLong(String.join( ".",FormConstant.NCKD_PERSON,FormConstant.ID_KEY));
                        String pairKey = personId + "_" + year;

                        // 检查当前处理的数据中是否有相同的人员和年度
                        Integer dataIndex = personMap.get(personId);
                        if (dataIndex != null) {
                            DynamicObject data = getDataEntities()[dataIndex].getDataEntity();
                            String dataPairKey = personId + "_" + year;

                            if (dataPairKey.equals(pairKey)) {
                                this.addErrorMessage(getDataEntities()[personMap.get(personId)], StrFormatter.format("【{}】【{}】已归档，忽略此条处理；", personName, year));
                            }
                        }
                    }
                }
                // 处理撤销归档操作
                else if(PerfManagerFormConstant.UNARCHIVE_OP.equalsIgnoreCase(operateKey)){
                    // 找出在personMap中存在但未归档的人员
                    personMap.entrySet().stream()
                            .filter(entry -> {
                                Long personId = entry.getKey();
                                String dataPairKey = personId+"";
                                return archivedPersonYearPairs.isEmpty() || archivedPersonYearPairs.stream().noneMatch(s -> s.indexOf(dataPairKey) > -1);
                            })
                            .forEach(entry -> {
                                Long personId = entry.getKey();
                                Integer dataIndex = entry.getValue();
                                DynamicObject data = getDataEntities()[dataIndex].getDataEntity();
                                DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
                                String personName = person.getString(FormConstant.NAME_KEY);
                                this.addErrorMessage(getDataEntities()[dataIndex], StrFormatter.format("【{}】未归档无需撤销，忽略此条处理；", personName));
                            });
                }
            }
        });
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
        String operateKey = this.getOption().getVariableValue("operateKey");
        List<DynamicObject> archiveList = new ArrayList<>();
        List<Long> unArchivePersonList = new ArrayList<>();
        StringJoiner personNameList = new StringJoiner(StrFormatter.LINE_SEPARATOR);
        int year = DateUtil.now().getYear();
        year = year - 1 ;
        LocalDate localDate = LocalDate.of(year, 1, 1);
        for (DynamicObject dataEntity : e.getDataEntities()) {
            if(PerfManagerFormConstant.ARCHIVE_OP.equalsIgnoreCase(operateKey)){
                DynamicObject newPerfArchiveRecord = EntityHelper.newEntity(PerfManagerFormConstant.PERFARCHIVERECORD_ENTITYID);
                DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
                newPerfArchiveRecord.set(PerfManagerFormConstant.NCKD_PERSON, person);
                newPerfArchiveRecord.set(PerfManagerFormConstant.NCKD_ARCHIVESTATUS, "1");
                newPerfArchiveRecord.set(FormConstant.CREATOR_KEY, UserServiceHelper.getCurrentUserId());
                newPerfArchiveRecord.set(PerfManagerFormConstant.NCKD_YEAR, DateUtil.toDate(localDate));
                archiveList.add(newPerfArchiveRecord);
                personNameList.add(StrFormatter.format("【{}】归档成功；", person.getString(FormConstant.NAME_KEY)));

            }else if(PerfManagerFormConstant.UNARCHIVE_OP.equalsIgnoreCase(operateKey)){
                DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
                unArchivePersonList.add(person.getLong(FormConstant.ID_KEY));
                personNameList.add(StrFormatter.format("【{}】撤销归档成功；", person.getString(FormConstant.NAME_KEY)));
            }
        }
        if(!archiveList.isEmpty()){
            SaveServiceHelper.save(archiveList.toArray(new DynamicObject[0]));
        }
        if(!unArchivePersonList.isEmpty()){
            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().add(FormConstant.ID_KEY).add(PerfManagerFormConstant.NCKD_ARCHIVESTATUS);
            QFilter qFilter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, unArchivePersonList);
            DynamicObject[] perfArchiveRecordArray = BusinessDataServiceHelper.load(PerfManagerFormConstant.PERFARCHIVERECORD_ENTITYID,queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
            for (DynamicObject perfArchiveRecord : perfArchiveRecordArray) {
                perfArchiveRecord.set(PerfManagerFormConstant.NCKD_ARCHIVESTATUS, "2");
            }
            OperationResult result = OperationServiceHelper.executeOperate(
                    "delete",
                    "nckd_perfarchiverecord",
                    perfArchiveRecordArray,
                    OperateOption.create()
            );
            if (!result.isSuccess()) {
                StringJoiner error = new StringJoiner(StrFormatter.LINE_SEPARATOR);
                StringJoiner warningError = new StringJoiner(StrFormatter.LINE_SEPARATOR);
                for (IOperateInfo operateInfo : result.getAllErrorOrValidateInfo()) {
                    OperateErrorInfo operateErrorInfo = (OperateErrorInfo)operateInfo;
                    if(operateErrorInfo.getLevel()  == ErrorLevel.FatalError || operateErrorInfo.getLevel() == ErrorLevel.Error){
                        error.add(operateErrorInfo.getMessage());
                    }else{
                        warningError.add(operateErrorInfo.getMessage());
                    }
                }
                if(error.length() > 0){
                    error.add(warningError.toString());
                    throw new ValidationException(error.toString());
                } else if(warningError.length() > 0){
                    throw new ValidationException(warningError.toString());
                }else{
                    throw new ValidationException(result.getMessage());
                }
            }
        }
        this.getOperationResult().setMessage(personNameList.toString());
    }
}