package nckd.jimin.jyyy.hr.swc.hsas.formplugin.web.helper;

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.utils.ObjectUtils;
import kd.bos.exception.KDBizException;
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.QueryServiceHelper;
import kd.fi.cal.common.util.CloneUtils;
import kd.hrmp.hrpi.business.infrastructure.utils.QFilterUtil;
import kd.sdk.swc.hcdm.common.stdtab.SalaryStdMatchResultNew;
import kd.sdk.swc.hcdm.common.stdtab.StdMatchParamWithDepEmp;
import kd.sdk.swc.hcdm.service.spi.SalaryStdQueryService;
import kd.swc.hcdm.business.salaryadjfile.DecAdjInfoServiceHelper;
import kd.swc.hsbp.common.util.SWCMServiceUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * description: 新增定调薪信息帮助类
 * @author Tyx
 * @date  2025/6/4
 */
public class AdjSalFileHelper {

    private static String onBrd_entity = "hom_onbrdinfo";
    private static String salaryAdjRecord_entity = "hcdm_salaryadjrecord";
    private static String salaryAdjRecordRel_entity = "hcdm_decadjrelperson";
    private static String adjFileInfo_entity = "hcdm_adjfileinfo";
    private static String standardItem_entity = "hsbs_standarditem";
    private static String stdScm_entity = "hcdm_stdscm";
    private static DecAdjInfoServiceHelper helper = new DecAdjInfoServiceHelper();
    private static final Log log = LogFactory.getLog(AdjSalFileHelper.class);
    private static String[] grItemNumber = new String[]{"004","005","006"};
    private static String[] grItemKey = new String[]{"nckd_jbgzyx","nckd_jngzyx","nckd_jxgzyx"};
    /**
     * 根据变动记录ID找入职单ID
     * @param chgRecordId
     * @return
     */
    public static Long getOnBrdBillId (Long chgRecordId) {
        Map<String, Object> recordResult = SWCMServiceUtils.invokeBizService("hr", "hpfs", "IHPFSPersonChgService",
                "getChgInfoByRecordId", new Object[] {chgRecordId});
        return Long.valueOf(((Map) recordResult.get("data")).get("billId").toString());
    }

    /**
     * 根据入职办理单Dyn构建待保存的定调薪信息Dyn
     * 具体规则：
     * 1.共用部分：N薪系数反写定调薪档案上
     * 2.是否药业工人入职（nckd_isgrrz） = false时：年度薪酬标准（定调薪项目） = 实习期月薪 * 12，发薪系数 = 实习期系数，
     * 或者 年度薪酬标准（定调薪项目） = 转正后年薪，发薪系数 = 试用期系数，实习期月薪 和 转正后年薪 如果都填了 只生成实习期的
     * 3.是否药业工人入职（nckd_isgrrz） = true时：基本工资（定调薪项目） = 基本工资（月薪），技能工资（定调薪项目） = 技能工资（月薪），绩效工资（定调薪项目） = 绩效工资（月薪）
     * @param onBrdBillDyn 入职单Dyn
     */
    public static Map<String, Object> execute (DynamicObject onBrdBillDyn, Map<String, Object> commonParams) {
        //分情况处理
        boolean isGr = onBrdBillDyn.getBoolean("nckd_isgrrz");
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        if(isGr) {
            dealRecordByGr(onBrdBillDyn, list, commonParams);
        }
        else {
            dealRecordByNotGr(onBrdBillDyn, list, commonParams);
        }
        //调用标准服务保存定调薪方法返回信息
        Map<String, Object> returnMap = helper.saveDecAdjRecord(list);
        return returnMap;
    }

    /**
     * 工人入职：
     * 定调薪项目：基本工资 004，技能工资 005，绩效工资 006，年度薪酬标准 001
     * 入职单上字段：基本工资 nckd_jbgzyx，技能工资 nckd_jngzyx，绩效工资 nckd_jxgzyx
     * @param onBrdBillDyn
     * @param dynList
     */
    public static void dealRecordByGr(DynamicObject onBrdBillDyn, List<Map<String,Object>> dynList, Map<String, Object> commonParams) {
        Long personId = getPersonId(commonParams);
        for(int i = 0; i < 3; i++) {
            //档案基本信息Id - 取定调薪档案boid
            DynamicObject salaryAdjFile = getSalaryAdjFile(personId);
            //薪酬结构ID
            Long salaystructureId = salaryAdjFile.getLong("salaystructure.id");
            Map map = dealCommonFields(onBrdBillDyn, personId, commonParams, salaryAdjFile);
            map.put("salaryadjfile", salaryAdjFile.getLong("boid"));
            //薪酬体系ID
            Long stdscmId = salaryAdjFile.getLong("stdscm.id");
            //定调薪项目
            DynamicObject standardItem = getStandardItem(grItemNumber[i]);
            map.put("standarditem", standardItem.getPkValue());
            //定调薪项目ID
            Long standardItemId = standardItem.getLong("id");
            //频度
            Long frequencyId = getFrequency(salaystructureId, stdscmId, standardItemId);
            map.put("frequency", frequencyId);
            //匹配薪等薪档
            matchStdTable(map, personId, stdscmId, salaystructureId, standardItemId);
            //金额 发薪系数
            map.put("amount", onBrdBillDyn.getBigDecimal(grItemKey[i]));
            map.put("nckd_fxxs", onBrdBillDyn.getBigDecimal("nckd_syqxs"));
            dynList.add(map);
        }
    }

    /**
     * 非工人入职：
     * 定调薪项目：年度薪酬标准 001
     * 入职单上字段：实习期系数 nckd_sxqxs，实习期月薪 nckd_sxqyx，试用期系数 nckd_syqxs，转正后年薪 nckd_zzhnx
     * 入职单上如果填写了实习期月薪 年度薪酬标准（定调薪项目） = 实习期月薪 * 12，发薪系数 = 实习期系数，
     * 如果填写了转正后年薪 年度薪酬标准（定调薪项目） = 转正后年薪，发薪系数 = 试用期系数
     * @param onBrdBillDyn
     * @param dynList
     */
    public static void dealRecordByNotGr(DynamicObject onBrdBillDyn, List<Map<String,Object>> dynList, Map<String, Object> commonParams) {
        Long personId = getPersonId(commonParams);
        //档案基本信息Id - 取定调薪档案boid
        DynamicObject salaryAdjFile = getSalaryAdjFile(personId);
        //薪酬结构ID
        Long salaystructureId = salaryAdjFile.getLong("salaystructure.id");

        Map map = dealCommonFields(onBrdBillDyn, personId, commonParams, salaryAdjFile);
        map.put("salaryadjfile", salaryAdjFile.getLong("boid"));
        //薪酬体系ID
        Long stdscmId = salaryAdjFile.getLong("stdscm.id");
        //填写了实习期月薪的情况
        if(onBrdBillDyn.getBigDecimal("nckd_sxqyx").compareTo(BigDecimal.ZERO) == 1) {
            //定调薪项目
            DynamicObject standardItem = getStandardItem("001");
            map.put("standarditem", standardItem.getPkValue());
            //定调薪项目ID
            Long standardItemId = standardItem.getLong("id");
            //频度
            Long frequencyId = getFrequency(salaystructureId, stdscmId, standardItemId);
            map.put("frequency", frequencyId);
            //匹配薪等薪档
            matchStdTable(map, personId, stdscmId, salaystructureId, standardItemId);
            //金额 发薪系数
            map.put("amount", onBrdBillDyn.getBigDecimal("nckd_sxqyx").multiply(new BigDecimal("12")));
            map.put("nckd_fxxs", onBrdBillDyn.getBigDecimal("nckd_sxqxs"));
        }
        //未填写实习期月薪的情况
        else {
            //定调薪项目
            DynamicObject standardItem = getStandardItem("001");
            map.put("standarditem", standardItem.getPkValue());
            //定调薪项目ID
            Long standardItemId = standardItem.getLong("id");
            //频度
            Long frequencyId = getFrequency(salaystructureId, stdscmId, standardItemId);
            //匹配薪等薪档
            matchStdTable(map, personId, stdscmId, salaystructureId, standardItemId);
            map.put("frequency", frequencyId);
            //金额 发薪系数
            map.put("amount", onBrdBillDyn.getBigDecimal("nckd_zzhnx"));
            map.put("nckd_fxxs", onBrdBillDyn.getBigDecimal("nckd_syqxs"));
        }
        dynList.add(map);
    }

    /**
     * 处理定调薪信息公用字段
     * @param onBrdBillDyn
     * @param personId
     * @return
     */
    public static Map dealCommonFields (DynamicObject onBrdBillDyn, Long personId, Map<String, Object> commonParams, DynamicObject salaryAdjFile) {
        Map info = new HashMap();
        //数据模式 1-变更 2-禁用
        info.put("datamode", "1");
        //UUID码
        String uuid = UUID.randomUUID().toString().replace("-", "");
        info.put("uuid", uuid);
        //唯一识别码
        info.put("uniquecode", uuid);
        //频度 根据定调薪档案-薪酬结构 + 定调薪项目 取 薪酬体系中的频度
        //调薪方式
        info.put("calctype", "2");
        //info.put("frequency", 0L);
        //币别 默认人民币
        info.put("currency", 1L);
        //定调薪类型 默认入职定薪
        info.put("salaryadjrsn", 1030L);
        //生效日期 取入职办理-入职日期
        info.put("bsed", onBrdBillDyn.getDate("effectdate"));
        //定调薪数据来源 TODO 标品是下拉 看是否增加一个选项
        info.put("datasource", "4");
        //业务数据来源ID-入职单ID
        info.put("businessid", onBrdBillDyn.getPkValue().toString());
        //处理人员相关信息
        dealRelPersonFields(onBrdBillDyn, personId, info, commonParams, salaryAdjFile);
        return info;
    }

    /**
     * 处理人员相关信息
     * @param onBrdBillDyn
     * @param personId
     * @param map
     */
    private static void dealRelPersonFields(DynamicObject onBrdBillDyn, Long personId, Map map, Map<String, Object> commonParams, DynamicObject salaryAdjFile) {
        Map relperson_data = new HashMap();
        relperson_data.put("personname", onBrdBillDyn.getString("name"));
        relperson_data.put("empnumber", onBrdBillDyn.getString("employeeno"));
        Long orgId = Long.valueOf(((Map) commonParams.get("executeInfoMap")).get("orgId").toString());
        Long depEmpId = Long.valueOf(((Map) commonParams.get("executeInfoMap")).get("depEmpId").toString());
        relperson_data.put("org", orgId);
        relperson_data.put("depemp", depEmpId);
        //定调薪管理属地 默认中国 1000001L
        relperson_data.put("country", 1000001L);
        //职级
        DynamicObject jobLevel = getjobLevel(personId);
        relperson_data.put("joblevel",jobLevel.getLong("joblevel.id"));
        //薪酬结构
        relperson_data.put("salaystructure", salaryAdjFile.getLong("salaystructure.id"));
        //薪酬体系
        relperson_data.put("stdscm", salaryAdjFile.getLong("stdscm.id"));
        //行政组织
        relperson_data.put("adminorg", salaryAdjFile.getLong("adminorg.id"));
        relperson_data.put("assoadminorg", salaryAdjFile.getLong("adminorg.id"));
        //薪酬管理人员组
        relperson_data.put("empgroup", 1019L);
        map.put("relperson_data", relperson_data);
    }

    /**
     * 更新N薪系数
     * @param onBrdBillDyn
     * @param commonParams
     * @return
     */
    public static Map<String, Object> updateNXXS (DynamicObject onBrdBillDyn, Map<String, Object> commonParams) {
        List<Map<String,Object>> dynList = new ArrayList<Map<String,Object>>();
        //分情况处理
        boolean isGr = onBrdBillDyn.getBoolean("nckd_isgrrz");
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        if(isGr) {
            dealRecordByGr(onBrdBillDyn, list, commonParams);
        }
        else {
            dealRecordByNotGr(onBrdBillDyn, list, commonParams);
        }
        //调用标准服务保存定调薪方法返回信息
        Map<String, Object> returnMap = helper.saveDecAdjRecord(list);
        return returnMap;
    }



    /**
     * 根据PersonId获取定调薪档案
     * @param personId
     * @return
     */
    public static DynamicObject getSalaryAdjFile (Long personId) {
        QFilter filter = QFilterUtil.getCurrentQf();
        filter.and("person.id", QCP.equals, personId);
        DynamicObject[] cols = BusinessDataServiceHelper.load(adjFileInfo_entity, "id,boid,adminorg.id,stdscm.id,salaystructure.id,nckd_ncoefficient", new QFilter[]{filter});
        if(cols.length == 0) {
            log.info("根据personId查询定调薪档案失败： {}", personId);
            throw new KDBizException("未找到对应的定调薪档案，终止执行");
        }
        else {
            return cols[0];
        }
    }

    /**
     * 获取定调薪项目 001-年度薪酬标准 002-岗位工资 004-基本工资 005-技能工资 006-绩效工资
     * @param number
     * @return
     */
    public static DynamicObject getStandardItem (String number) {
        QFilter filter = new QFilter("number", QCP.equals, number);
        DynamicObject[] cols = BusinessDataServiceHelper.load(standardItem_entity, "id,number,name", new QFilter[]{filter});
        if(cols.length == 0) {
            log.info("根据number查询定调薪项目失败： {}", number);
            throw new KDBizException("未找到对应的定调薪项目，终止执行");
        }
        else {
            return cols[0];
        }
    }

    /**
     * 根据薪酬体系+薪酬结构+定条调薪项目取薪酬体系分录中的频度，薪酬标准.频度
     * @param salaystructureId
     * @param stdscmId
     * @param standardItemId
     */
    public static Long getFrequency(Long salaystructureId, Long stdscmId, Long standardItemId) {
        QFilter currentQf = QFilterUtil.getCurrentQf();
        QFilter dataStatusFilter = QFilterUtil.getDataStatusFilter();
        QFilter filter = new QFilter("entryentity.salstructurent.id", "=", salaystructureId);
        filter.and("entryentity.standarditem.id", "=", standardItemId);
        filter.and("id", "=", stdscmId);
        DynamicObject stdScm = QueryServiceHelper.queryOne(stdScm_entity, "entryentity.salarystandard.frequency.id", new QFilter[]{currentQf, dataStatusFilter, filter});
        if(ObjectUtils.isEmpty(stdScm)) {
            log.info("查询频度失败");
            throw new KDBizException("未找到对应的频度，终止执行");
        }
        else {
            return stdScm.getLong("entryentity.salarystandard.frequency.id");
        }
    }

    /**
     * 获取入职办理单Dyn
     * @param onBrdBillId 入职ID
     * @return
     */
    public static DynamicObject getOnBrdBillDyn (Long onBrdBillId) {
        return BusinessDataServiceHelper.loadSingle(onBrdBillId, onBrd_entity);
    }

    /**
     * 获取人员Id
     * @param commonParams
     * @return
     */
    public static Long getPersonId (Map<String, Object> commonParams) {
        return Long.valueOf(((Map) commonParams.get("executeInfoMap")).get("personId").toString());
    }

    /**
     * 根据人员获取职级职等
     * @param personId
     * @return
     */
    public static DynamicObject getjobLevel(Long personId) {
        QFilter filter = QFilterUtil.getCurrentQf();
        filter.and(QFilterUtil.getDataStatusFilter());
        filter.and("person.id", QCP.equals, Long.valueOf(personId));
        DynamicObject bill = QueryServiceHelper.queryOne("hrpi_empjobrel", "joblevel.id,joblevel.number", new QFilter[]{filter});
        if(ObjectUtils.isEmpty(bill)) {
            log.info("查询职级失败");
            throw new KDBizException("未找到对应的职级，终止执行");
        }
        else {
            return bill;
        }
    }

    /**
     * 匹配薪等薪档
     * @param map
     * @param personId
     * @param stdscmId
     * @param salaystructureId
     * @param standardItemId
     */
    private static void matchStdTable(Map map, Long personId, Long stdscmId, Long salaystructureId, Long standardItemId) {
        List paramList = new ArrayList<>();
        StdMatchParamWithDepEmp param = new StdMatchParamWithDepEmp();
        param.setStdScmId(stdscmId);
        param.setSalayStructureId(salaystructureId);
        param.setStandardItemId(standardItemId);
        param.setUnionId(UUID.randomUUID().toString().replace("-", ""));

        DynamicObject jobLevel = getjobLevel(personId);

        List<Long> list = new ArrayList<Long>();
        list.add(jobLevel.getLong("jobLevel.id"));
        Map personPropValue = new HashMap();
        personPropValue.put(1050L,list);
        param.setPersonPropValue(personPropValue);
        paramList.add(param);
        //标品匹配方法
        List<SalaryStdMatchResultNew> resultList = SalaryStdQueryService.get().batchMatchStdTableWithDepEmp(paramList);
        if(resultList.size() > 0) {
            SalaryStdMatchResultNew matchResult = resultList.get(0);
            if("0".equals(matchResult.getIsMatchGradeRank())) {
                log.info("薪酬体系是否显示薪等薪档为否");
                throw new KDBizException("薪酬体系是否显示薪等薪档未打开，终止执行");
            }
            if(matchResult.getGradeId() == null) {
                log.info("薪等为空");
                throw new KDBizException("未匹配到薪等，终止执行");
            }
            if(matchResult.getRankId() == null) {
                log.info("薪档为空");
                throw new KDBizException("未匹配到薪档，终止执行");
            }
            map.put("grade", matchResult.getGradeId());
            map.put("rank", matchResult.getRankId());
        }
        else {
            log.info("匹配薪等薪档失败");
            throw new KDBizException("未匹配到对应的薪等薪档，终止执行");
        }
    }

    /**
     * 匹配薪等薪档-职级调整单用
     * @param stdscmId
     * @param salaystructureId
     * @param standardItemId
     * @param jobLevelId
     */
    public static Map matchStdTableForBill(Long stdscmId, Long salaystructureId, Long standardItemId, Long jobLevelId) {
        Map map = new HashMap();
        List paramList = new ArrayList<>();
        StdMatchParamWithDepEmp param = new StdMatchParamWithDepEmp();
        param.setStdScmId(stdscmId);
        param.setSalayStructureId(salaystructureId);
        param.setStandardItemId(standardItemId);
        param.setUnionId(UUID.randomUUID().toString().replace("-", ""));

        List<Long> list = new ArrayList<Long>();
        list.add(jobLevelId);
        Map personPropValue = new HashMap();
        personPropValue.put(1050L,list);
        param.setPersonPropValue(personPropValue);
        paramList.add(param);
        //标品匹配方法
        List<SalaryStdMatchResultNew> resultList = SalaryStdQueryService.get().batchMatchStdTableWithDepEmp(paramList);
        if(resultList.size() > 0) {
            SalaryStdMatchResultNew matchResult = resultList.get(0);
            if("0".equals(matchResult.getIsMatchGradeRank()) || matchResult.getIsMatchGradeRank() == null) {
                map.put("success",false);
                map.put("msg", "薪酬体系是否显示薪等薪档为否");
                log.info("薪酬体系是否显示薪等薪档为否");
                return map;
            }
            if(matchResult.getGradeId() == null) {
                map.put("success",false);
                map.put("msg", "匹配结果薪等为空");
                log.info("匹配结果薪等为空");
                return map;
            }
            if(matchResult.getRankId() == null) {
                map.put("success",false);
                map.put("msg", "匹配结果薪档为空");
                log.info("匹配结果薪档为空");
                return map;
            }
            else {
                map.put("success", true);
                map.put("grade", matchResult.getGradeId());
                map.put("rank", matchResult.getRankId());
                return map;
            }
        }
        else {
            map.put("success",false);
            map.put("msg", "匹配薪等薪档失败");
            log.info("匹配薪等薪档失败");
            return map;
        }
    }


}
