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

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.LocaleString;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.form.control.Control;
import kd.bos.form.control.Label;
import kd.bos.form.control.grid.DataGrid;
import kd.bos.form.control.grid.DataGridRow;
import kd.bos.form.control.grid.DataGridRowBuilder;
import kd.bos.form.control.grid.column.AmountDataGridColumn;
import kd.bos.form.control.grid.column.DataGridColumn;
import kd.bos.form.control.grid.events.BeforeCreateDataGridColumnsEvent;
import kd.bos.form.control.grid.events.BeforeCreateDataGridColumnsListener;
import kd.bos.form.control.grid.events.DataGridBindDataEvent;
import kd.bos.form.control.grid.events.DataGridBindDataListener;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.swc.helper.SWCHelper;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 员工薪酬查询 WEB  动态表单插件
 * 薪酬项目-实发  JT_331 薪酬项目-应发  JT_283 薪酬项目-扣款小计  JT_408
 * @author turborao
 * @date 2025/11/28 16:01
 */
public class EmpSalaryQueryWebFormPlugin extends AbstractFormPlugin implements  Plugin,BeforeCreateDataGridColumnsListener, DataGridBindDataListener {


    private static final String KEY_LAB_EMP_NAME = "nckd_name";
    private static final String KEY_LAB_EMP_DESCRIPTION = "nckd_desc";
    private static final String KEY_LAB_REALAMT = "nckd_realamt";
    private static final String KEY_LAB_GROSSAMT = "nckd_grossamt";
    private static final String KEY_LAB_SUBAMT = "nckd_subamt";
    private static String KEY_CTL_STARTDATE = "startmonth";
    private static String KEY_CTL_ENDDATE = "endmonth";
    private static Long KEY_EMPID = 0L;
    private static Date KEY_STARTDATE = new Date();
    private static Date KEY_ENDDATE = new Date();
    private static String KEY_TYPE = "10";

    Map<String, String> itemNameMap = new LinkedHashMap<>();
    Map<String, BigDecimal> calItemAmtMap = new HashMap<>();
    Map<Long, Map<String, BigDecimal>> calItemAmtMapByTask = new HashMap<>();
    Map<Long, Map<String, String>> calItemStrMapByTask = new HashMap<>();
    Map<Long, DynamicObject> calPersonIdMap = new HashMap<>();

    private static final String CTL_DATAGRID = "nckd_datagridap";

    @Override
    public void initialize() {
        super.initialize();

        Long userId = UserServiceHelper.getCurrentUserId();

        DynamicObject personUserDyn = SWCHelper.queryOne(FormConstant.HRPI_PERSONUSERREL, "employee.id","user",userId);

        if(personUserDyn == null){
            /**
             * 没有员工信息时，返回常量，用于测试
             */
            KEY_EMPID = 2313784485549715456L;

        }else {
            KEY_EMPID = personUserDyn.getLong("employee.id");
        }

    }


    @Override
    public void beforeBindData(EventObject e) {
        super.beforeBindData(e);
        this.getModel().setValue(KEY_CTL_STARTDATE, KEY_STARTDATE);
        this.getModel().setValue(KEY_CTL_ENDDATE, KEY_ENDDATE);
        Long userId = UserServiceHelper.getCurrentUserId();
        this.getModel().setValue("nckd_user", userId);

    }

    @Override
    public void afterBindData(EventObject e) {
        super.afterBindData(e);

    }

    /**
     * 注册监听事件
     * @param event
     */
    @Override
    public void registerListener(EventObject event) {
        registerDataGridListener();
        // 添加箭头点击事件监控
        this.addClickListeners("nckd_query");
    }

    /**
     * 通过事件监听，注册数据表格监听事件
     */
    private void registerDataGridListener() {
        DataGrid dataGrid = this.getControl(CTL_DATAGRID);
        // 注册创建列监听事件
        dataGrid.addBeforeCreateDataGridColumnsListener(this);
        // 注册绑定数据监听事件
        dataGrid.addBindDataListener(this);

    }

    @Override
    public void click(EventObject e) {
        super.click(e);
        Control source = (Control) e.getSource();
        if("nckd_query".equals(source.getKey())) {
            KEY_STARTDATE = (Date) this.getModel().getValue(KEY_CTL_STARTDATE);
            KEY_ENDDATE = (Date) this.getModel().getValue(KEY_CTL_ENDDATE);
            KEY_TYPE = (String) this.getModel().getValue("nckd_type");
            showData();

            this.getView().updateView(CTL_DATAGRID);

        }
    }

    /**
     * 显示薪酬数据
     * caltask.paydate       预计支付日期  发放口径
     * caltask.payrolldate   薪资所属年月  统计口径
     */
    public void showData() {
        // 获取单据头日期范围，开始时间、结束时间
        Date startdate = KEY_STARTDATE;
        Date enddate = KEY_ENDDATE;
        String type = KEY_TYPE;

        if(KEY_EMPID == 0L) {
            this.getView().showMessage("未找到员工！");
            return;
        }
        String selectFields1 = "id,company.name,adminorg.name,employee.id,employee.name";
        QFilter filter1 = new QFilter("isprimary", QCP.equals, "1");
        QFilter filter2 = new QFilter("iscurrentdata", QCP.equals, "1");
        QFilter filter3 = new QFilter("employee.id", QFilter.equals, KEY_EMPID);
        DynamicObject employeeDyn = QueryServiceHelper.queryOne(FormConstant.HRPI_EMPPOSORGREL,selectFields1, new QFilter[]{filter1, filter2, filter3});

        if(employeeDyn == null){
            this.getView().showMessage("未找到员工！");
            return;
        }

        calPersonIdMap = SWCHelper.queryCalPersonList(KEY_EMPID);
        if(calPersonIdMap == null && calPersonIdMap.size() <= 0) {
            this.getView().showMessage("未找到员工！");
            return;
        }

        //将Map转换为List
        List<Long> calPersonIds = calPersonIdMap.keySet().stream().collect(Collectors.toList());

        Label label = this.getView().getControl(KEY_LAB_EMP_NAME);
        label.setText(employeeDyn.getString("employee.name"));

        Label labelDesc = this.getView().getControl(KEY_LAB_EMP_DESCRIPTION);
        String companyName = employeeDyn.getString("company.name");
        String adminorgName = employeeDyn.getString("adminorg.name");
        String desc = "";
        if(companyName != null){
            desc = "公司：" + companyName;
        }
        if(adminorgName != null){
            desc = desc + "   部门：" + adminorgName;
        }
        labelDesc.setText( desc);

        // 获取核算列表信息
        DynamicObjectCollection calTableDyns = SWCHelper.querySalaryList(calPersonIds, startdate, enddate, type) ;
        calItemAmtMap = getCalItemAmt(calTableDyns);
        itemNameMap = getItemName(calTableDyns);
        getCalItemAmtByPeriod(calTableDyns);

        if(calItemAmtMap != null && calItemAmtMap.size() > 0 && itemNameMap != null && !itemNameMap.isEmpty()){
            DecimalFormat df = new DecimalFormat("#,##0.00");
            Label label1 = this.getView().getControl(KEY_LAB_REALAMT);
            if(calItemAmtMap.get(FormConstant.SALARYITEM_REAL) == null){
                label1.setText("0.00");
            }else {
                label1.setText(df.format(calItemAmtMap.get(FormConstant.SALARYITEM_REAL)));    //实发合计
            }

            Label label2 = this.getView().getControl(KEY_LAB_GROSSAMT);
            if(calItemAmtMap.get(FormConstant.SALARYITEM_GROSS) == null){
                label2.setText("0.00");
            }else {
                label2.setText(df.format(calItemAmtMap.get(FormConstant.SALARYITEM_GROSS)));   //应发合计
            }
            Label label3 = this.getView().getControl(KEY_LAB_SUBAMT);
            if(calItemAmtMap.get(FormConstant.SALARYITEM_SUB) == null){
                label3.setText("0.00");
            }else {
                label3.setText(df.format(calItemAmtMap.get(FormConstant.SALARYITEM_SUB)));
            }

        }else{
            Label label1 = this.getView().getControl(KEY_LAB_REALAMT);
            label1.setText("0.00");
            Label label2 = this.getView().getControl(KEY_LAB_GROSSAMT);
            label2.setText("0.00");
            Label label3 = this.getView().getControl(KEY_LAB_SUBAMT);
            label3.setText("0.00");
        }

    }

    /**
     * 生成表格  汇总金额数据
     * @param calTableDyns
     * @return
     */
    public Map<String, BigDecimal> getCalItemAmt(DynamicObjectCollection calTableDyns) {
        // 按 salaryitem.number 分组汇总金额
        Map<String, BigDecimal> groupedAmounts = new HashMap<>();

        for (DynamicObject item : calTableDyns) {
            String salaryItemNumber = item.getString("hsas_caltableentry.salaryitem.number");
            BigDecimal amount = item.getBigDecimal("hsas_caltableentry.calamountvalue");
            if (amount == null) {
                amount = BigDecimal.ZERO;
            }else{
                amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP);
            }

            if (salaryItemNumber != null) {
                groupedAmounts.put(salaryItemNumber, groupedAmounts.getOrDefault(salaryItemNumber, BigDecimal.ZERO) .add(amount != null ? amount : BigDecimal.ZERO));
            }
        }
        return groupedAmounts;
    }

    /**
     * 按 生成表格明细数据
     * @param calTableDyns 薪酬数据集合
     * @return Map<period, Map<itemnumber, amount>> 嵌套Map结构
     */
    public void getCalItemAmtByPeriod(DynamicObjectCollection calTableDyns) {

        /**
         * 按日期排序
         */
        Collections.sort(calTableDyns , new Comparator<DynamicObject>(){
            @Override
            public int compare(DynamicObject stu1, DynamicObject stu2) {
                return stu1.getDate("bizdate").compareTo(stu2.getDate("bizdate"));
            }
        });

        // 按 period 分组，每个 period 再按 salaryitem.number 分组汇总金额
        Map<Long, Map<String, BigDecimal>> resultAmt = new LinkedHashMap<>();
        Map<Long, Map<String, String>> resultStr = new LinkedHashMap<>();

        for (DynamicObject item : calTableDyns) {
            Date bizPeriod = item.getDate("bizdate");
            String period = DateUtil.format(bizPeriod, "yyyy-MM");
            Long caltaskId = item.getLong("caltask.id");
            String salaryItemNumber = item.getString("hsas_caltableentry.salaryitem.number");
            BigDecimal amount = item.getBigDecimal("hsas_caltableentry.calamountvalue");

            if (amount == null) {
                amount = BigDecimal.ZERO;
            } else {
                amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP);
            }

            if (period != null && salaryItemNumber != null) {
                // 获取当前 period 的子 map，如果不存在则创建新的
                Map<String, BigDecimal> periodMap = resultAmt.computeIfAbsent(caltaskId, k -> new HashMap<>());
                // 在 period 子 map 中累加 salaryItemNumber 对应的金额
                periodMap.put(salaryItemNumber, periodMap.getOrDefault(salaryItemNumber, BigDecimal.ZERO).add(amount != null ? amount : BigDecimal.ZERO));
            }

            Map<String, String> resultMap = resultStr.computeIfAbsent(caltaskId, k -> new HashMap<>());
            resultMap.put("nckd_org", item.getString("caltask.org.name"));
            resultMap.put("nckd_calcount", item.getString("caltask.calcount"));
            resultMap.put("nckd_rulename", item.getString("caltask.calrule.name"));

            if(calPersonIdMap != null && !calPersonIdMap.isEmpty()){
                Long calperson = item.getLong("calpersonid");
                DynamicObject dyn = calPersonIdMap.get(calperson);
                resultMap.put("nckd_period", period);
                resultMap.put("calperson", calperson.toString());
                resultMap.put("nckd_position", dyn.getString("empposorgrelsndet.position.name"));
                StringBuilder orgName = new StringBuilder();
                if(dyn.getString("adminorg.nckd_secondorg.name") != null){
                    orgName.append(dyn.getString("adminorg.nckd_secondorg.name"));
                }
                if(dyn.getString("adminorg.nckd_thirdorg.name") != null){
                    orgName.append( "_");
                    orgName.append(dyn.getString("adminorg.nckd_thirdorg.name"));
                }
                if(dyn.getString("adminorg.nckd_fourthorg.name") != null) {
                    orgName.append( "_");
                    orgName.append(dyn.getString("adminorg.nckd_fourthorg.name"));
                }
                if(dyn.getString("adminorg.nckd_fifthorg.name") != null){
                    orgName.append( "_");
                    orgName.append(dyn.getString("adminorg.nckd_fifthorg.name"));
                }
                if(dyn.getString("adminorg.nckd_sixthorg.name") != null){
                    orgName.append( "_");
                    orgName.append(dyn.getString("adminorg.nckd_sixthorg.name"));
                }

                resultMap.put("nckd_calorg", orgName.toString());
            }
        }

        calItemAmtMapByTask = resultAmt.isEmpty() ? null : resultAmt;
        calItemStrMapByTask = resultStr.isEmpty() ? null : resultStr;

    }

    /**
     * 按 生成表格列数据
     * @param calTableDyns
     * @return
     */
    public Map<String, String> getItemName(DynamicObjectCollection calTableDyns) {
        Map<String, String> itemNameMap = new LinkedHashMap<>();
        for (DynamicObject item : calTableDyns) {
            String salaryItemNumber = item.getString("hsas_caltableentry.salaryitem.number");
            String salaryItemName = item.getString("hsas_caltableentry.salaryitem.name");

            if (salaryItemNumber != null) {
                itemNameMap.put(salaryItemNumber, salaryItemName);
            }
        }
        return itemNameMap;
    }

    @Override
    public void propertyChanged(PropertyChangedArgs e) {
        super.propertyChanged(e);
        String fieldKey = e.getProperty().getName();
        if (fieldKey.equals(KEY_CTL_STARTDATE) || fieldKey.equals(KEY_CTL_ENDDATE)){
            //KEY_STARTDATE = (Date)this.getModel().getValue(KEY_CTL_STARTDATE);
            //KEY_ENDDATE = (Date)this.getModel().getValue(KEY_CTL_ENDDATE);
            //showData();
            //this.getView().updateView();
        }
        if (fieldKey.equals("nckd_type")){

            //KEY_TYPE = (String)this.getModel().getValue("nckd_type");
            //showData();
            //this.getView().updateView();
        }
    }

    /**
     * 监听创建列事件
     * @param event
     */
    @Override
    public void beforeCreateDataGridColumns(BeforeCreateDataGridColumnsEvent event) {
        // 所有列集合
        List<DataGridColumn> dataGridColumns = event.getDataGridColumns();

        if (itemNameMap != null && !itemNameMap.isEmpty()) {
            // itemNameMap 为空或者为 null
            for (String key : itemNameMap.keySet()){
                // 动态创建金额列
                AmountDataGridColumn amountColumn = new AmountDataGridColumn();
                amountColumn.setKey(key);
                amountColumn.setCaption(new LocaleString(itemNameMap.get( key)));

                // 加入列集合
                dataGridColumns.add(amountColumn);
            }
        }

    }

    /**
     * 数据绑定
     */
    @Override
    public void dataGridBindData(DataGridBindDataEvent e) {
        List<Object> list = new ArrayList<>();
        int index = 0;
        if(calItemAmtMapByTask !=  null && !calItemAmtMapByTask.isEmpty() && calItemStrMapByTask != null && !calItemStrMapByTask.isEmpty()) {
            DataGridRowBuilder builder = e.getDataGridRowBuilder();
            // 遍历每个周期
            for (Map.Entry<Long, Map<String, BigDecimal>> taskEntry : calItemAmtMapByTask.entrySet()) {
                Long taskID = taskEntry.getKey();
                Map<String, BigDecimal> itemAmountMap = taskEntry.getValue();

                Map<String, String> itemStrMap  = calItemStrMapByTask.get( taskID);
                // 为每个周期构建一行数据
                DataGridRow row = builder.buildRow();

                // 设置系统保留字段
                row.setValue("rk", index);  // rk必须存在且唯一不能重复
                row.setValue("seq", taskID);

                // 设置周期字段（假设用"period"字段表示）
                row.setValue("nckd_period", itemStrMap.get("nckd_period"));
                row.setValue("nckd_org", itemStrMap.get("nckd_org"));
                row.setValue("nckd_calcount", itemStrMap.get("nckd_calcount"));
                row.setValue("nckd_rulename", itemStrMap.get("nckd_rulename"));
                row.setValue("nckd_position", itemStrMap.get("nckd_position"));
                row.setValue("nckd_calorg", itemStrMap.get("nckd_calorg"));

                // 遍历该项目的所有薪资项，按itemnumber设置列值
                for (Map.Entry<String, BigDecimal> itemEntry : itemAmountMap.entrySet()) {
                    String itemNumber = itemEntry.getKey();
                    BigDecimal amount = itemEntry.getValue();

                    // 按itemnumber设置对应列的值
                    row.setValue(itemNumber, amount);
                }

                list.add(row.get());
                index++;
                
            }
            if(calItemAmtMap != null && calItemAmtMap.size() > 0) {
                DataGridRow row = builder.buildRow();
                row.setValue("rk", index + 1);  // rk必须存在且唯一不能重复
                row.setValue("seq", index + 2);
                row.setValue("nckd_period", "_合计_");
                for(String key : calItemAmtMap.keySet()){
                    row.setValue(key, calItemAmtMap.get( key));
                }
                list.add(row.get());
            }
            // 重要: 传递列表数据
            e.setData(list);

        }
    }


}