package nckd.jxccl.swc.hcdm.formplugin.annualincome;

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.ObjectUtils;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.form.IFormView;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.operate.FormOperate;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.swc.hcdm.business.annualincome.AnnualIncomeService;
import nckd.jxccl.swc.utils.SwcUtils;

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

/**
 * Tyx 2025-11-05
 * 年收入证明统计单表单插件 【nckd_salinnualincomebill】
 */
public class SalAnnualIncomeBillEdit extends AbstractFormPlugin implements Plugin {


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

    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        super.beforeDoOperation(args);
        FormOperate formOperate = (FormOperate)args.getSource();
        String key = formOperate.getOperateKey();
        switch (key) {
            case "donothing_query":
                beforeDoQueryVerify(args);
                break;
        }
    }

    private void beforeDoQueryVerify(BeforeDoOperationEventArgs args) {
        IDataModel model = this.getModel();
        DynamicObject dyn = model.getDataEntity();
        DynamicObjectCollection payRollGrps = (DynamicObjectCollection)model.getValue("nckd_mulpayrollgrp");
        if(ObjectUtils.isEmpty(payRollGrps)) {
            args.setCancel(true);
            this.getView().showTipNotification("请先选择薪资核算组！");
        }

        Date calYear = dyn.getDate("nckd_calyear");
        if(ObjectUtils.isEmpty(calYear)) {
            args.setCancel(true);
            this.getView().showTipNotification("请先选择年度！");
        }
    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
        super.afterDoOperation(afterDoOperationEventArgs);
        IDataModel model = this.getModel();
        IFormView view = this.getView();
        String key = afterDoOperationEventArgs.getOperateKey();
        switch (key) {
            case "donothing_query":
                model.deleteEntryData("nckd_entryentity");
                doQuery();
                break;
        }
    }

    private void doQuery() {
        IDataModel model = this.getModel();
        DynamicObject dyn = model.getDataEntity();
        DynamicObjectCollection payRollGrps = (DynamicObjectCollection)model.getValue("nckd_mulpayrollgrp");
        List<Long> groupIds = payRollGrps.stream().map(obj -> obj.getDynamicObject("fbasedataid").getLong("id")).collect(Collectors.toList());
        // 单据上选择的年度字段，实际值是yyyy-01-01
        Date calYear = dyn.getDate("nckd_calyear");
        // 排除薪资核算组
        List<Long> excludeGroupIds = SwcUtils.getExcludePayRollGroupIds(calYear);
        groupIds.removeAll(excludeGroupIds);

        if(groupIds.size() == 0) {
            this.getView().showMessage("当前核算组已生成过数据，请勿重复生成！");
            return;
        }

        // 获取年度最后一天
        Date endDate = SwcUtils.getLastDayOfYear(calYear);
        // 声明service
        AnnualIncomeService service = new AnnualIncomeService(groupIds, calYear, endDate);
        DynamicObjectCollection resultDyns = service.querySalaryDetailBySql();

        // 界面赋值
        for (DynamicObject result : resultDyns) {
            int rowIndex = model.createNewEntryRow("nckd_entryentity");
            model.setValue("nckd_payrollgrp", result.get("groupId"), rowIndex);
            model.setValue("nckd_employee", result.get("employeeId"), rowIndex);
            model.setValue("nckd_idcardno", result.get("idCardNo"), rowIndex);
            model.setValue("nckd_totalsalary", result.get("amount"), rowIndex);
            model.setValue("nckd_month", result.get("monthCount"), rowIndex);
        }

        // 排除人员ID
        // List<Long> excludeEmployeeId = service.queryIncomeBillEmployeeId();

        // 获取核算人员信息，一个核算人员一条记录
//        DynamicObjectCollection calPersonDyns = service.queryCalPersonByPayRollGroup();
//        List<Long> calPersonIds = calPersonDyns.stream().map((o) -> {
//            return o.getLong("id");
//        }).collect(Collectors.toList());
//        // 获取薪酬项目ID，这里固定为应发工资 JT_283
//        List<String> itemNos = new ArrayList<String>();
//        itemNos.add("JT_283");
//        List<Long> itemIds = SwcUtils.getSalaryItemIdByNumber(itemNos);
//        // 获取薪资明细数据 一个核算人员一条<k1,v1<k2,v2>>，k1=核算人员ID，k2=薪酬项目ID，v2=金额
//        Map<Long, Map<Long, Object>> salaryMap = service.querySalaryDetail(calPersonIds, itemIds);
//
//        // 把核算人员相关信息和薪资明细合并在一起
//        Map<Long, Map<String, Object>> unionMap = (Map) calPersonDyns.stream().collect(Collectors.toMap((dyx) -> {
//            return dyx.getLong("id");
//        }, (dyx) -> {
//            Map map = new HashMap();
//            map.put("employeeId", dyx.getLong("hsbs_employee.id"));
//            map.put("idCardNo", dyx.getString("hsbs_percre.number"));
//            map.put("payRollDate", dyx.getDate("hsas_calpayrolltask.payrolldate"));
//            map.put("amount", salaryMap.get(dyx.getLong("id")).get(itemIds.get(0)));
//            return map;
//        }, (key1, key2) -> {
//            return key2;
//        }));
//        // 按照employeeId提取出来
//        List<Map<String, Object>> finalResult = dealGroupData(unionMap);
//        // 排除人员ID
//        List<Long> excludeEmployeeId = service.queryIncomeBillEmployeeId();
//
//        // 界面赋值
//        for (Map map : finalResult) {
//            if(excludeEmployeeId.contains(map.get("employeeId"))) {
//                continue;
//            }
//            int rowIndex = model.createNewEntryRow("nckd_entryentity");
//            model.setValue("nckd_employee", map.get("employeeId"), rowIndex);
//            model.setValue("nckd_idcardno", map.get("idCardNo"), rowIndex);
//            model.setValue("nckd_totalsalary", map.get("totalAmount"), rowIndex);
//            model.setValue("nckd_month", map.get("uniqueDateCount"), rowIndex);
//        }

    }

    public List<Map<String, Object>> dealGroupData (Map<Long, Map<String, Object>> unionMap) {
        Map<String, Map<String, Object>> result = new HashMap<>();
        Iterator<Long> it = unionMap.keySet().iterator();
        while(it.hasNext()) {
            Map<String, Object> record = unionMap.get(it.next());
            String key = record.get("employeeId") + "_" + record.get("idCardNo");

            if (!result.containsKey(key)) {
                Map<String, Object> summary = new HashMap<>();
                summary.put("employeeId", record.get("employeeId"));
                summary.put("idCardNo", record.get("idCardNo"));
                summary.put("totalAmount", new BigDecimal("0"));
                summary.put("uniqueDates", new HashSet<String>());
                result.put(key, summary);
            }

            Map<String, Object> summary = result.get(key);
            // 累加金额
            BigDecimal currentAmount = (BigDecimal) summary.get("totalAmount");
            summary.put("totalAmount", currentAmount.add((BigDecimal) record.get("amount")));

            // 添加日期到集合中（自动去重）
            @SuppressWarnings("unchecked")
            Set<Date> uniqueDates = (Set<Date>) summary.get("uniqueDates");
            uniqueDates.add((Date) record.get("payRollDate"));
        }

        // 转换结果格式，将Set的大小作为日期计数
        List<Map<String, Object>> finalResult = new ArrayList<>();
        for (Map<String, Object> summary : result.values()) {
            Map<String, Object> finalRecord = new HashMap<>();
            finalRecord.put("employeeId", summary.get("employeeId"));
            finalRecord.put("idCardNo", summary.get("idCardNo"));
            finalRecord.put("totalAmount", summary.get("totalAmount"));
            @SuppressWarnings("unchecked")
            Set<Date> uniqueDates = (Set<Date>) summary.get("uniqueDates");
            finalRecord.put("uniqueDateCount", uniqueDates.size());
            finalResult.add(finalRecord);
        }

        return finalResult;
    }
}