package nckd.jxccl.swc.onlineperf.business.extpoint;

import com.alibaba.fastjson.JSONObject;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.MainEntityType;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.MetadataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.sdk.swc.hscs.business.extpoint.ISalaryCalExtPlugin;
import kd.sdk.swc.hscs.common.events.AfterSalaryCalEventArgs;
import kd.sdk.swc.hscs.common.events.CalRollBackEventArgs;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.QueryFieldBuilder;
import nckd.jxccl.swc.constants.SwcConstant;
import nckd.jxccl.swc.onlineperf.common.OnlinePerfConstant;

import java.math.BigDecimal;
import java.nio.file.OpenOption;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* 薪酬计算扩展（处理在线即时考核）
* @author W.Y.C
* @date 2025/12/17 21:04
* @version 1.0
*/
public class OnlinePerfSalaryCalServiceExPlugin implements ISalaryCalExtPlugin {

    private static final Log log = LogFactory.getLog(OnlinePerfSalaryCalServiceExPlugin.class);

    /**
     * 薪资计算完成后逻辑处理场景
     * @param event 薪资计算完成后事件，其中属性包括：
     * Long taskId 核算任务ID，用于获取核算任务信息
     * Long recordId 计算会话ID
     * Long batchId 核算批次ID
     * String calType 计算类型（"onlyPreTaxCal"：仅计算税前， "preTaxCal":计算税前，"afterTaxCal"：计算税后，"cal":计算(不开启个税计算开关，税前 和税后一起计算)），计算保存埋点在分段计算时或进来两次，计算税前和计算税后，计算只进来一次，可以通过计算类型进行判断是否需要进行业务处理
     * List<Long> calPersonIdList 当前批次核算名单Id集合，用于获取需要处理的明细结果信息
     * boolean isFinished 是否计算完成，判断当前次计算是否完成
     * String traceId 日志跟踪ID，可用于日志打印
     */
    @Override
    public void afterSalaryCal(AfterSalaryCalEventArgs event) {
        //锁定在线即时考核
        processOnlinePerfLock(event.getCalPersonIdList(), true);
    }

    /**
     * 计算回滚扩展场景
     */
    @Override
    public void afterCancelCalRollBack(CalRollBackEventArgs event) {
        //解锁在线即时考核
        processOnlinePerfLock(event.getCalPersonIdList(), false);
    }

    /**
     * 处理在线即时考核锁定状态
     * @param calPersonIdList 核算人员ID列表
     * @param isLocked 是否锁定
     */
    private void processOnlinePerfLock(List<Long> calPersonIdList, boolean isLocked) {
        // 构建查询字段
        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                .add(FormConstant.ID_KEY)
                .add("empnumber")
                .add("name")
                .add("org")
                .addGroup(new String[]{"caltask"}, "calcount", "payrolldate")
                .addGroup(new String[]{"caltask", "calrule"}, FormConstant.ID_KEY)
                .addGroup(new String[]{FormConstant.EMPLOYEE_KEY}, FormConstant.ID_KEY);
        
        QFilter qFilter = new QFilter("id", "in", calPersonIdList);
        DynamicObject[] load = SwcConstant.CALPERSON_HELPER.load(queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});

        // 如果没有加载到数据则直接返回
        if(load == null || load.length <= 0) {
            return;
        }
        
        Map<Long, Long> employeeToCalPersonMap = Arrays.stream(load)
                .collect(Collectors.toMap(
                        obj -> obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
                        obj -> obj.getLong(FormConstant.ID_KEY)
                ));

        long orgId = load[0].getLong(String.join(".", FormConstant.ORG_KEY, FormConstant.ID_KEY));
        DynamicObject calTask = load[0].getDynamicObject("caltask");
        Date date = calTask.getDate("payrolldate");
        int year = DateUtil.getYear(date);
        int month = DateUtil.getMonthValue(date);
        long calRuleId = calTask.getLong(String.join(".", "calrule", FormConstant.ID_KEY));
        int calCount = calTask.getInt("calcount");

        // 在线即时考核查询构建
        QueryFieldBuilder onlinePerfQueryFieldBuilder = QueryFieldBuilder.create()
                .add(FormConstant.ID_KEY)
                .addIdNumberName(OnlinePerfConstant.NCKD_CALRULE)
                .addIdNumberName(OnlinePerfConstant.NCKD_ADMINORGUNIT)
                .add(OnlinePerfConstant.NCKD_PERIODYEAR)
                .add(OnlinePerfConstant.NCKD_PERIODMONTH)
                .addIdNumberName(OnlinePerfConstant.NCKD_ENTRYENTITY, FormConstant.NCKD_PERSON)
                .addIdNumberName(OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_SALARYITEM)
                .add(OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_NMONEY);
                
        QFilter onlinePerfFilter = new QFilter(OnlinePerfConstant.NCKD_PERIODYEAR, QCP.equals, year)
                .and(OnlinePerfConstant.NCKD_PERIODMONTH, QCP.equals, month)
                .and(String.join(".", OnlinePerfConstant.NCKD_ADMINORGUNIT, FormConstant.ID_KEY),QCP.equals, orgId)
                .and(String.join(".", OnlinePerfConstant.NCKD_CALRULE, FormConstant.ID_KEY),QCP.equals, calRuleId)
                .and(String.join(".", OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_PERSON),QCP.in, employeeToCalPersonMap.keySet());
                
        DynamicObjectCollection onlinePerfColl = QueryServiceHelper.query(OnlinePerfConstant.ONLINEPERF_ENTITYID, onlinePerfQueryFieldBuilder.buildSelect(), new QFilter[]{onlinePerfFilter});
        
        // 如果查询结果为空则直接返回
        if(!onlinePerfColl.isEmpty()) {

            List<Long> ids = onlinePerfColl.stream().map(obj -> obj.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
            MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(OnlinePerfConstant.ONLINEPERF_ENTITYID);
            DynamicObject[] dbOnlinePerfArray = BusinessDataServiceHelper.load(ids.toArray(), dataEntityType);

            for (DynamicObject dynamicObject : dbOnlinePerfArray) {
                dynamicObject.set(OnlinePerfConstant.NCKD_ISCALDYNLOCK, isLocked);
            }

            // 锁定/解锁在线即时考核结果
            SaveServiceHelper.saveOperate(OnlinePerfConstant.ONLINEPERF_ENTITYID, dbOnlinePerfArray, OperateOption.create());
        }
    }
}