package nckd.jxccl.swc.init.plugin.operate;

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
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.ext.fi.bei.util.EmptyUtil;
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.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.sdk.plugin.Plugin;
import kd.sdk.swc.hcdm.business.helper.HCDMAdjFileServiceHelper;
import kd.sdk.swc.hcdm.business.helper.HCDMApplyBillServiceHelper;
import kd.sdk.swc.hcdm.business.helper.HCDMSalaryStdServiceHelper;
import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableGradeRankRangeMatchParam;
import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableGradeRankRangeMatchResult;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.utils.ConvertUtil;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.entity.helper.EntityHelper;
import nckd.jxccl.base.swc.helper.SWCHelper;

import java.util.*;
import java.util.stream.Collectors;

/**
 * hcdm_applybill 生成定调薪申请单，单据操作插件
 * hom_personhasonbrd  入职单
 * hdm_transferapply   调动申请
 * author: turborao
 * date: 2025/11/24 9:05
 */
public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn implements Plugin {

    private static final Log logger = LogFactory.getLog(BuildApplyBillOpPlugin.class);
    /**
     * 员工待定调薪清单  员工ID
     */
    private static final String EmployeesField = "nckd_employeefield.id";
    private static final String EmployeesNameField = "nckd_employeefield.name";
    private static final String BillTypeField = "nckd_billtype";
    private static final String OrgField = "nckd_hrorg.id";

    /**
     * 定调薪申请单  定调薪明细字段显示方案   员工调薪
     * select b.fname ,a.fid,a.fbillformid  from t_bas_billtype a
     * left join t_bas_billtype_l b on a.fid = b.fid
     * where a.fbillformid  like 'hcdm_applybill'
     */
//    private static final Long changeSalaryBillTypeId = 2215975998602655744L;
    /**
     * 定调薪申请单  定调薪明细字段显示方案   员工定薪
     */
//    private static final Long setSalaryBillEntryTypeId = 2215982957338868736L;
    /**
     * 定调薪项目   岗位工资标准   t_hsbs_standarditem
     */
//    private static final Long salaryStdItemId = 2321899710350111744L;
    /**
     * 频度  月   t_hsbs_calfrequency
     */
//    private static final Long frequencyItemId = 1095454108284088320L;
    /**
     * 汇率表   通用汇率   T_BD_ExRateTable
     */
//    private static final Long exchangeTableId = 2321965096026258432L;
    /**
     * 国家   中国   T_BD_Country
     */
//    private static final Long countryItemId = 1000001L;
    /**
     * 定调薪方案   t_hcdm_adjapprovescm
     */
//    private static final Long salaryAdjScmItemId = 2322515162646457344L;
    /**
     * 默认币种   人民币   select * from T_BD_Currency
     */
//    private static final Long currencyItemId = 1L;



    /**
     * this.getDataEntities()中需要加载的字段，增加员工待定调薪清单中员工ID
     *
     */
    @Override
    public void onPreparePropertys(PreparePropertysEventArgs e) {
        e.getFieldKeys().add(EmployeesField);
        e.getFieldKeys().add(EmployeesNameField);
        e.getFieldKeys().add(BillTypeField);
        e.getFieldKeys().add("nckd_newposition.id");
        e.getFieldKeys().add("nckd_newsalaryrank.id");
        e.getFieldKeys().add("nckd_newhradminorg.id");
        e.getFieldKeys().add(OrgField);
        e.getFieldKeys().add("nckd_applybillid");
        e.getFieldKeys().add("billstatus");

    }

    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {
        super.onAddValidators(e);
        e.addValidator(new SalaryAdjDelivaryDateValidator());
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
        super.beginOperationTransaction(e);
        DynamicObject[] datas = e.getDataEntities();

        List<Long> employeeIDs  =  getSelectedEmployees(datas);

        Map<String,Object> papams = new HashMap<>();
        List<Map<String,Object>> applyBillData = new ArrayList<>();
        Map<String,Object> applyBill = new HashMap<>();

        /**
         * 必填字段
         * "billname", "billtype", "org", "billcountry", "salaryadjrsn", "salaryadjscm", "billcurrency", "effectivedate", "exchangeratedate", "exctable"
         */
        applyBill.put("billname",generateBillName(datas));

        DynamicObjectCollection salaryTypeDyns = SWCHelper.getSalaryTypeDyns();

        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
        Long billTypeId = EntityHelper.getIdByNumber(FormConstant.BOS_BILLTYPE, FormConstant.HCDM_APPLYBILL_BT_ADJ);
        Long countryId = EntityHelper.getIdByNumber(FormConstant.BD_COUNTRY, "001");
        Long currencyId = EntityHelper.getIdByNumber(FormConstant.BD_CURRENCY, "CNY");
        Long adjApproveScmId = EntityHelper.getLatestIdByNumber(FormConstant.HCDM_ADJAPPROVESCM, "dingtiaoxin");
        Long exRateTableId = EntityHelper.getIdByNumber(FormConstant.BD_EXRATETABLE, "ERT-01");
        Long calFrequencyId = EntityHelper.getIdByNumber(FormConstant.HSBS_CALFREQUENCY, "000_m_001");
        String uniquecode = UUID.randomUUID().toString().replace("-", "");
        applyBill.put("_uniquecode", uniquecode);
        //applyBill.put("org",orgId);
        //applyBill.put("billtype", 2215975998602655744L);   //定调薪明细字段显示方案   调薪明细字段
        applyBill.put("billcountry", countryId);                //国家
        //applyBill.put("salaryadjrsn", 2352340656979984384L);  //定调薪类型
        applyBill.put("billcurrency", currencyId);           //默认币种
        applyBill.put("salaryadjscm", adjApproveScmId);   //定调薪方案
        applyBill.put("exchangeratedate", new Date());   //汇率日期
        applyBill.put("exctable", exRateTableId);  //汇率表
        applyBill.put("effectivedate", new Date());   //默认生效日期
        applyBill.put("isdraft", "1"); //草稿状态
        applyBill.put("auditstatus", "A"); //审核状态
        applyBill.put("datasource", "2");  //申请单数据来源   //1:手工新增  2:接口写入

        List<Map<String,Object>> applyBillEntryData = new ArrayList<>();

        /**
         * 必填字段
         * "adjfile", "standarditem", "frequency"
         */
        for (DynamicObject data : datas) {
            Map<String,Object> applyBillEntry = new HashMap<>();
            Long employeeId = data.getLong(EmployeesField);
            // 组织
            applyBill.put("org",data.getLong(OrgField));
            String billType = data.getString(BillTypeField);
            //定调薪明细字段显示方案   调薪明细字段
            if(billType.equals("调动单")){
                //定调薪明细字段显示方案
                applyBill.put("billtype", billTypeId);
                //定调薪类型
                applyBill.put("salaryadjrsn", salaryTypeDyns.get(1).getLong("id"));
            }else if(billType.equals("入职单")){
                applyBill.put("billtype", billTypeId);
                applyBill.put("salaryadjrsn", salaryTypeDyns.get(0).getLong("id"));
            }

            Long positionId = data.getLong("nckd_newposition.id");
            DynamicObject salaryfile  = SWCHelper.getSalaryFileInfo(employeeId,positionId);

            applyBillEntry.put("adjfile", salaryfile.getLong("id"));
            applyBillEntry.put("employee", employeeId);
            applyBillEntry.put("standarditem", salaryItemId);    //定调薪项目   岗位工资标准
            applyBillEntry.put("frequency", calFrequencyId);       //频度  月
            //applyBillEntry.put("amount", BigDecimal.ZERO);
            Long postgradeId = salaryfile.getLong("position.nckd_postgrade.id");
            applyBillEntry.put("nckd_postgrade", postgradeId);  //岗级
            applyBillEntry.put("position", positionId);    //岗位
            /**
             * 获取标准表
             */
            Long salaryStandardId = getSalarystandard(salaryfile.getLong("stdscm.id"),salaryItemId);
            /**
             * 获取薪等
             */
            Long salaryGradeId = getSalaryGradeID(postgradeId,salaryStandardId);
            applyBillEntry.put("salarygrade", salaryGradeId);
            applyBillEntry.put("salaryrank", data.getLong("nckd_newsalaryrank.id"));
            applyBillEntryData.add(applyBillEntry);
        }
        applyBill.put("applybillent", applyBillEntryData);
        applyBillData.add(applyBill);
        papams.put("data", applyBillData);

        logger.info("生成定调薪申请单参数:"+papams.toString());
        Map<String, Object> result = HCDMApplyBillServiceHelper.saveDraftApplyBill(papams);
        System.out.println("生成定调薪申请单:"+result.toString());
        logger.info("生成定调薪申请单:"+result.toString());
        // 判断整体操作是否成功
        Boolean overallSuccess = (Boolean) result.get("success");
        String errorCode = (String) result.get("errorCode");
        String errorMessage = (String) result.get("message");
        Map<String, String> params = new HashMap<>();
        if (overallSuccess != null && overallSuccess && "success".equals(errorCode)) {
            // 提取数据部分
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) result.get("data");

            if (dataList != null && !dataList.isEmpty()) {
                Map<String, Object> dataMap = dataList.get(0);
                // 安全地提取 id 值
                Long idValue = ((Number) dataMap.get("id")).longValue();
                System.out.println("提取的ID值为: " + idValue); // 输出 2360318043084569600
                logger.info("员工待定调薪清单 操作成功，" + idValue);

                for(DynamicObject data : datas) {
                    data.set("nckd_applybillid", idValue);
                    data.set("billstatus", "D");  //处理中
                }
                Object[] update = SaveServiceHelper.save(datas);

                params.put("applyID",idValue.toString());
                //区别：绿色提示语显示时间较短。红色一直存在。
                this.operationResult.setSuccess(true);
                ///返回界面的数据
                this.operationResult.setCustomData(params);
                // TODO: 可以在这里使用提取到的 idValue 进行后续操作
            } else {
                //区别：绿色提示语显示时间较短。红色一直存在。
                this.operationResult.setSuccess(false);
                //异常提示语
                this.operationResult.setMessage("操作失败，没有生成定调薪申请单，" + errorMessage);
                logger.info("员工待定调薪清单 操作失败，没有生成定调薪申请单，" + errorMessage);
                //显示结果
                this.operationResult.setShowMessage(true);
                System.out.println("操作失败或返回错误码不为success");
            }
        } else {
            //区别：绿色提示语显示时间较短。红色一直存在。
            this.operationResult.setSuccess(false);
            //异常提示语
            this.operationResult.setMessage("操作失败，没有生成定调薪申请单，" + errorMessage);
            logger.info("员工待定调薪清单 操作失败，没有生成定调薪申请单，" + errorMessage);
            //显示结果
            this.operationResult.setShowMessage(true);
            System.out.println("操作失败或返回错误码不为success");
        }

    }

    /**
     * 获取薪等，通过 岗级和标准表ID
     * @param postgradeId
     * @param salarystandardId
     * @return
     */
    public Long getSalaryGradeID(Long postgradeId,Long salarystandardId){
        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);

        List<StdTableGradeRankRangeMatchParam> matchParams = new ArrayList<>();
        StdTableGradeRankRangeMatchParam stdTableGradeRankMatchParam = new StdTableGradeRankRangeMatchParam();
        /*
         * 标准表   hcdm_salarystandard
         */
        //DynamicObject salarystandardTable = getLastDecAdjRecords(employeeId,salaryStdItemId);
        stdTableGradeRankMatchParam.setStdTableId(salarystandardId);
        /*
         * 定调薪项目  hsbs_standarditem
         */
        stdTableGradeRankMatchParam.setStdItemId(salaryItemId);
        /**
         * 匹配类型 为0 时
         * 定调薪人员属性 key 为  定调薪人员属性配置（hcdm_contrastpropconf）的ID
         * Object为 定调薪人员属性配置（hcdm_contrastpropconf）的属性值  岗级的值
         */
        DynamicObject postgradeprop = SWCHelper.getSalaryPersonProperty("岗级");
        Map<Long, List<Object>> personProp = new HashMap<>();
        List<Object> postgradeList = new ArrayList<>();
        postgradeList.add(postgradeId);
        personProp.put(postgradeprop.getLong("id"), postgradeList);
        stdTableGradeRankMatchParam.setPersonPropValue(personProp);
        /**
         * 匹配类型   0 对照属性匹配  1 标准数据匹配
         */
        stdTableGradeRankMatchParam.setMatchType("0");

        matchParams.add(stdTableGradeRankMatchParam);
        //获取标准表中的薪酬项目、薪等、薪档
        List<StdTableGradeRankRangeMatchResult> stdTableGradeRankRangeMatchResults = HCDMSalaryStdServiceHelper.matchStdTableGradeRankRange(matchParams);
        logger.info("获取标准表中的薪酬项目、薪等、薪档:{}",stdTableGradeRankRangeMatchResults.toString());
        if (!stdTableGradeRankRangeMatchResults.isEmpty()) {
            for(StdTableGradeRankRangeMatchResult result : stdTableGradeRankRangeMatchResults){
               return result.getGradeId();
            }
        }

        return 0L;
    }

    /**
     * 获取员工最新的定调薪记录，如果没有，为了拿到标准表数据
     * @param adjFileId
     * @param standardItemId
     */
    public DynamicObject getLastDecAdjRecords(Long adjFileId,Long standardItemId ){

        //构建定调薪记录查询条件
        Map<String, Object> adjRecordParams = new HashMap<>();
        List<Map<String, Object>> dataList = new ArrayList<>();

        Map<String, Object> dataItem = new HashMap<>();
        // 调薪档案ID
        dataItem.put("adjfile", adjFileId);
        // 调薪项目ID
        dataItem.put("standarditem", standardItemId);
        // 查询基准日期
        dataItem.put("startdate", new Date());
        // 唯一标识
        String uniquecode = UUID.randomUUID().toString().replace("-", "");
        dataItem.put("_uniquecode", uniquecode);
        dataList.add(dataItem);

        adjRecordParams.put("data", dataList);
        adjRecordParams.put("selprops", "salarystdv.rankentry.rank.id,salarystdv.rankentry.rank.name,salarystdv.rankentry.rank.number,salarystdv.rankentry.rank.index,salarystdv.rankentry.frankindex,company.id,company.name,");
        //查询定调薪记录
        Map<String, Object> lastDecAdjRecordMap = HCDMAdjFileServiceHelper.getLastDecAdjRecords(adjRecordParams);
        logger.info("员工最新的定调薪记录 查询结果：{}", lastDecAdjRecordMap.toString());
        if (ConvertUtil.toBoolean(lastDecAdjRecordMap.get("success"))) {
            List<Map> datas = ConvertUtil.toList(lastDecAdjRecordMap.get("data"), ArrayList::new);
            for (Map data : datas) {
                if (ConvertUtil.toBoolean(data.get("success"))) {
                    List<DynamicObject> adjRecordList = ConvertUtil.toList(data.get("data"), ArrayList::new);
                    for (DynamicObject dynamicObject : adjRecordList) {
                        // 人员
                        //DynamicObject employee = dynamicObject.getDynamicObject("adjfile").getDynamicObject("employee");

                        //薪酬标准表版本
                        DynamicObject salaryStDv = dynamicObject.getDynamicObject("salarystdv");
                        //薪等（01岗、02岗）
                        //DynamicObject salaryGrade = dynamicObject.getDynamicObject("salarygrade");
                        //薪档（1档、2档）
                        //DynamicObject salaryRank = dynamicObject.getDynamicObject("salaryrank");
                        //金额
                        //BigDecimal amount = dynamicObject.getBigDecimal("amount");
                        //定调薪档案对象
                        //DynamicObject adjFileInfo = dynamicObject.getDynamicObject("adjfile");
                        return salaryStDv;
                    }
                }
            }
        } else {
            logger.error("查询员工最新的定调薪记录失败");
            this.operationResult.setSuccess(false);
            this.operationResult.setMessage("查询员工最新的定调薪记录失败");
        }
        return null;
    }

    /**
     * 获取标准表，通过薪酬体系，定调薪项目
     * @param stdscmId   薪酬体系
     * @param salaryStdItemId   定调薪项目
     */
    public Long getSalarystandard( Long stdscmId, Long salaryStdItemId) {
        String selectField = "id,entryentity.salarystandard.id";
        QFilter qFilter1 = new QFilter("id", QCP.equals, stdscmId);
        QFilter qFilter2 = new QFilter("entryentity.standarditem.id", QCP.equals, salaryStdItemId);
        DynamicObject salarystandardDyn = QueryServiceHelper.queryOne(FormConstant.HCDM_STDSCM, selectField, new QFilter[]{qFilter1,qFilter2});
        return salarystandardDyn.getLong("entryentity.salarystandard.id");
    }

    /**
     * 生成单据名称
     * @param datas   DynamicObject[]
     */
    public String  generateBillName(DynamicObject[] datas) {
        StringBuilder billname = new StringBuilder();
        int index = 0;
        for(DynamicObject data : datas){
            billname.append(data.getString(EmployeesNameField)).append(",");
            index++;
            if(index == 2) break;
        }
        String billnameStr = billname.substring(0, billname.length()-1);

        String billnameMonth = DateUtil.format(DateUtil.now(), "yyyyMM");
        String re = "";
        if(index >= 2) {
            re = "【" + billnameStr + "...等】" + billnameMonth + "-员工待定调薪清单-生成";
        }else{
            re = "【" + billnameStr + "】" + billnameMonth + "-员工待定调薪清单-生成";
        }
        return re;
    }

    /**
     * 获取员工待定调薪清单中员工ID
     * @param datas   DynamicObject[]
     */
    public List<Long> getSelectedEmployees(DynamicObject[] datas){

        Map<Long, DynamicObject> employeeMap =
                Arrays.stream(datas)
                        .collect(Collectors.toMap(
                                detail -> detail.getLong(EmployeesField),
                                detail -> detail, // 整个 DynamicObject 作为 value
                                (existing, replacement) -> existing // 保留前面的值
                        ));

        List<Long> employeeIDs = employeeMap.keySet().stream().collect(Collectors.toList());
        return employeeIDs;
    }



}