package nckd.jxccl.sit.hcsi.business.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.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
import nckd.jxccl.sit.hcsi.common.constant.SitConstant;

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

/**
 * Tyx 2025-11-20
 * 社保年度收入计算服务
 */
public class AnnualIncomeCalculateService {

    DynamicObject welfarePayer = null;
    Date year = null;

    IDataModel model;

    IFormView view;

    public AnnualIncomeCalculateService(DynamicObject welfarePayer, Date year, IDataModel model, IFormView view) {
        this.welfarePayer = welfarePayer;
        this.year = year;
        this.model = model;
        this.view = view;
    }

    /**
     * 已确认的数据不做调整，未确认的数据更新
     * 计算步骤：
     * 1.根据参保单位获取到人员
     * 2.根据1获取到的人员去取薪酬模块-年收入统计中的薪酬数据
     * 3.根据年份+人员去业务数据提报下取外单位年收入数据
     *
     * @return
     */
    public int calculate() {
        // 获取社保档案
        Map<Long, DynamicObject> fileMap = getSinSurFile();
        // 根据参保单位获取人员
        Set<Long> employeeIds = fileMap.keySet();
        // 根据参保单位+年度获取到现在已经生成数据的人员，用于排除
        Set<Long> excludeEmployee = getExcludeEmployee();
        employeeIds.removeAll(excludeEmployee);
        // 取薪酬-年收入统计单中的数据
        Map<Long, Map> incomeBillData = getSalIncomeBillData(employeeIds);
        // 业务项目
        Map<Long, DynamicObject> bizItemMap = getBizItem();
        // 取业务数据提报中的数据
        Map<Long, Map<Long, String>> bizData = getBizData(bizItemMap);
        // 处理页面数据
        int successCount = dealData(fileMap, employeeIds, incomeBillData, bizItemMap, bizData);
        // 更新年收入统计单状态
        updateSalIncomeBillStatus(incomeBillData.keySet());

        return successCount;
    }


    /**
     * 根据参保单位+年度获取已确认的年收入证明单数据
     *
     * @return
     */
    public Set<Long> getExcludeEmployee() {
        QFilter filter = new QFilter("nckd_year", QCP.equals, year);
        filter.and("nckd_welfarepayer", QCP.equals, welfarePayer.getLong("id"));
        filter.and("billstatus", QCP.in, new String[]{"C", "H"});
        String selectFields = "nckd_employee.id";
        DynamicObjectCollection cols = SitConstant.SITINCOMEBILL_HELPER.queryOriginalCollection(selectFields, new QFilter[]{filter});
        return cols.stream().map(dyx -> dyx.getLong("nckd_employee.id")).collect(Collectors.toSet());
    }

    /**
     * 根据参保单位+年度获取需要更新的单据数据
     * k = employee.id , v = 单据数据包
     * @return
     */
    public Map<Long, DynamicObject> getExistBillInfos() {
        QFilter filter = new QFilter("nckd_year", QCP.equals, year);
        filter.and("nckd_welfarepayer", QCP.equals, welfarePayer.getLong("id"));
        filter.and("billstatus", QCP.in, new String[]{"A", "B"});
        String selectFields = "billstatus,auditstatus,nckd_year,nckd_employee,nckd_datastatus,nckd_welfarepayer,nckd_sinsurfile,org,billno,nckd_sysmonth,nckd_sysyearamount,nckd_outmonth,nckd_outyearamount,nckd_totalamount";
        DynamicObject[] cols = SitConstant.SITINCOMEBILL_HELPER.load(selectFields, new QFilter[]{filter});
        return Arrays.stream(cols).collect(Collectors.toMap((dyx) -> {
            return dyx.getLong("nckd_employee.id");
        }, (dyx) -> {
            return dyx;
        }, (key1, key2) -> {
            return key2;
        }));
    }

    /**
     * 更新年收入统计单状态
     * @param employeeIds
     */
    private void updateSalIncomeBillStatus(Set<Long> employeeIds) {
        QFilter filter = new QFilter("nckd_entryentity.nckd_employee.id", QCP.in, employeeIds);
        filter.and("nckd_calyear", QCP.equals, year);
        filter.and("nckd_entryentity.nckd_pushstatus", QCP.equals, "0");
        DynamicObject[] billDyns = SitConstant.SALINCOMEBILL_HELPER.load(SitConstant.SALINCOMEBILL_SELECTFIELDS, new QFilter[]{filter});
        for(DynamicObject bill : billDyns) {
            DynamicObjectCollection entryCols = bill.getDynamicObjectCollection("nckd_entryentity");
            for (DynamicObject entry : entryCols) {
                if(employeeIds.contains(entry.getLong("nckd_employee.id"))) {
                    entry.set("nckd_pushstatus", "1");
                }
            }
        }
        SitConstant.SALINCOMEBILL_HELPER.update(billDyns);
    }

    /**
     * 处理页面数据
     *
     * @param employeeIds
     * @param incomeBillData
     * @param bizItemMap
     * @param bizData
     * @return
     */
    public int dealData(Map<Long, DynamicObject> fileMap, Set<Long> employeeIds, Map<Long, Map> incomeBillData, Map<Long, DynamicObject> bizItemMap, Map<Long, Map<Long, String>> bizData) {
        //DynamicObjectCollection billCols = new DynamicObjectCollection();
        List<DynamicObject> addnewCols = new ArrayList<>();
        List<DynamicObject> updateCols = new ArrayList<>();
        Map<Long, DynamicObject> existBillInfosMap = getExistBillInfos();
        Set<Long> existEmployeeIds = existBillInfosMap.keySet();
        for(Long employeeId : employeeIds) {
            DynamicObject dyn;
            boolean exists = false;
            if(existEmployeeIds.contains(employeeId)) {
                exists = true;
                dyn = existBillInfosMap.get(employeeId);
            }
            else {
                exists = false;
                dyn = SitConstant.SITINCOMEBILL_HELPER.generateEmptyDynamicObject();
                dyn.set("billstatus", "A");
                dyn.set("auditstatus", "A");
                dyn.set("nckd_datastatus", "A");
                dyn.set("billno", UUID.randomUUID().toString().substring(0,29));
            }
            // 默认值字段
            dyn.set("nckd_year", year);
            dyn.set("nckd_employee", employeeId);
            dyn.set("nckd_welfarepayer", welfarePayer);
            dyn.set("nckd_sinsurfile", fileMap.get(employeeId).getLong("id"));
            dyn.set("org", fileMap.get(employeeId).getLong("org.id"));

            BigDecimal amount1 = BigDecimal.ZERO;
            BigDecimal amount2 = BigDecimal.ZERO;
            BigDecimal month1 = BigDecimal.ZERO;
            BigDecimal month2 = BigDecimal.ZERO;

            Map incomeBillMap = incomeBillData.get(employeeId);
            if(!ObjectUtils.isEmpty(incomeBillMap)) {
                dyn.set("nckd_sysmonth", incomeBillMap.get("totalMonth"));
                dyn.set("nckd_sysyearamount", incomeBillMap.get("totalAmount"));
                amount1 = (BigDecimal) incomeBillMap.get("totalAmount");
                month1 = BigDecimal.valueOf((int) incomeBillMap.get("totalMonth"));
            }
            Map<Long, String> bizDataMap = bizData.get(employeeId);
            if(!ObjectUtils.isEmpty(bizDataMap)) {
                for(Long bizItemId : bizItemMap.keySet()) {
                    String matchKey = bizItemMap.get(bizItemId).getString("entryentity.bizitem.nckd_incomematchkey");
                    switch(matchKey) {
                        case "nckd_outmonth":
                            int month = Integer.parseInt(bizDataMap.get(bizItemId));
                            dyn.set(matchKey, month);
                            month2 = new BigDecimal(month);
                            break;
                        case "nckd_outyearamount":
                            BigDecimal amount = new BigDecimal(bizDataMap.get(bizItemId));
                            dyn.set(matchKey, amount);
                            amount2 = amount;
                            break;
                    }
                }
            }
            // 申报年度社保缴费基数 = （江铜内年度收入 + 江铜外年度收入） / （江铜内发放月数 + 外单位发放月数）
            BigDecimal totalAmount = calculateTotalAmount(amount1, amount2, month1, month2);
            dyn.set("nckd_totalamount", totalAmount);
            if(exists) {
                updateCols.add(dyn);
            }
            else {
                addnewCols.add(dyn);
            }
        }
        // 保存数据
        int successCount = 0;
        if(addnewCols.size() > 0) {
            Object[] addnewDyns = SaveServiceHelper.save(addnewCols.stream().toArray(DynamicObject[]::new));
            successCount += addnewDyns.length;
        }
        // 更新数据
        if(updateCols.size() > 0) {
            Object[] updateDyns = SaveServiceHelper.save(updateCols.stream().toArray(DynamicObject[]::new));
            successCount += updateDyns.length;
        }
        return successCount;
    }


    public BigDecimal calculateTotalAmount (BigDecimal amount1,BigDecimal amount2, BigDecimal month1, BigDecimal month2) {
        // 分子
        BigDecimal numerator = amount1.add(amount2);
        // 分母
        BigDecimal denominator = month1.add(month2);
        if (denominator.compareTo(BigDecimal.ZERO) == 0) {
            // 分母为零，无法进行除法运算，返回0
            return BigDecimal.ZERO;
        }
        return numerator.divide(denominator, 0, RoundingMode.HALF_UP);
    }

    /**
     * 获取计薪人员ID
     * @return
     */
    public List<Long> getEmployee(DynamicObjectCollection cols) {
        return cols.stream().map(dynamicObject -> dynamicObject.getLong("employee.id")).collect(Collectors.toList());
    }

    public Map<Long, DynamicObject> getSinSurFile() {
        QFilter filter = new QFilter("welfarepayer.id", QCP.equals, welfarePayer.getLong("id"));
        filter.and(QFilterCommonHelper.getCurrentVersionFilter());
        filter.and(QFilterCommonHelper.getDataStatusFilter());
        DynamicObjectCollection cols = SitConstant.SINSURFILE_HELPER.queryOriginalCollection("id,employee.id,org.id", new QFilter[]{filter});
        return cols.stream().collect(Collectors.toMap((dyx) -> {
            return dyx.getLong("employee.id");
        }, (dyx) -> {
            return dyx;
        }, (key1, key2) -> {
            return key2;
        }));
    }




    /**
     * 获取薪酬模块-年收入统计中的数据
     * 只取 推送状态 = 社保未拉取 的数据
     * @param employeeIds
     * @return
     */
    public Map<Long, Map> getSalIncomeBillData(Set<Long> employeeIds) {
        QFilter filter = new QFilter("nckd_entryentity.nckd_employee.id", QCP.in, employeeIds);
        filter.and("nckd_calyear", QCP.equals, year);
        filter.and("nckd_entryentity.nckd_pushstatus", QCP.equals, "0");
        DynamicObjectCollection cols = SitConstant.SALINCOMEBILL_HELPER.queryOriginalCollection(SitConstant.SALINCOMEBILL_SELECTFIELDS, new QFilter[]{filter});

        //按照人员汇总
        Map<Long, Map> incomeMap = cols.stream().collect(Collectors.groupingBy(
                dyx -> dyx.getLong("nckd_entryentity.nckd_employee"),
                Collectors.collectingAndThen(
                        Collectors.toList(),
                        list -> {
                            int totalMonth = list.stream().mapToInt(dyx -> dyx.getInt("nckd_entryentity.nckd_month")).sum();
                            BigDecimal totalAmount = list.stream().map(dyx -> dyx.getBigDecimal("nckd_entryentity.nckd_totalsalary")).reduce(BigDecimal.ZERO, BigDecimal::add);
                            Map map = new HashMap();
                            map.put("totalMonth", totalMonth);
                            map.put("totalAmount", totalAmount);
                            return map;
                        }
                )
        ));

        return incomeMap;

    }

    public Map<Long, Map<Long, String>> getBizData(Map<Long, DynamicObject> bizItemMap) {
        Set<Long> bizItemIds = bizItemMap.keySet();
        //年份转日期
        String yearStr = yearToStr(year);

        // 前台是显示一行，但实际存储是多行，这里用BusinessDataServiceHelper查
        QFilter filter = new QFilter("entryentity.bizitem.id", QCP.in, bizItemIds);
        filter.and("entryentity.value", QCP.equals, yearStr);
        String selectFields = "id";
        // 这里不知道什么原因查不出分录业务项目ID，取出ID再调用标准查询
        DynamicObjectCollection cols = SitConstant.BIZDATABILLENT_HELPER.queryOriginalCollection(selectFields, new QFilter[]{filter});
        List<Long> entryIds = cols.stream().map(dyx -> dyx.getLong("id")).collect(Collectors.toList());
        filter = new QFilter("id", QCP.in, entryIds);
        DynamicObject[] bizDatas = SitConstant.BIZDATABILLENT_HELPER.queryOriginalArray("empposorgrel.employee.id,entryentity.bizitem.id,entryentity.value", new QFilter[]{filter});
        // 根据employeeId提取出来，k = employeeid, v = Map(k1,v1), k1 = 业务项目ID， v1 = 业务项目值
        Map<Long, Map<Long, String>> dataMap = Arrays.stream(bizDatas).collect(Collectors.groupingBy(
                dyx -> dyx.getLong("empposorgrel.employee.id"),
                Collectors.toMap((dyx) -> {
                    return dyx.getLong("entryentity.bizitem.id");
                }, (dyx) -> {
                    return dyx.getString("entryentity.value");
                }, (key1, key2) -> {
                    return key2;
                })));
        return dataMap;
    }
    /**
     * 获取业务项目ID
     *
     * @return
     */
    public Map<Long, DynamicObject> getBizItem() {
        QFilter filter = new QFilter("number", "=", SitConstant.WDWSR_NUMBER);
        filter.and("enable", "=", "1");
        filter.and("status", "=", "C");
        String selectFields = "id, name, entryentity.bizitem, entryentity.bizitem.id, entryentity.bizitem.name, entryentity.bizitem.number, entryentity.bizitem.nckd_incomematchkey";
        DynamicObjectCollection bizItemGrpColl = SitConstant.BIZITEMGROUP_HELPER.queryOriginalCollection(selectFields, new QFilter[]{filter});

        Map<Long, DynamicObject> map = bizItemGrpColl.stream().collect(Collectors.toMap((dyx) -> {
            return dyx.getLong("entryentity.bizitem.id");
        }, (dyx) -> {
            return dyx;
        }, (key1, key2) -> {
            return key2;
        }));
        return map;
    }

    public String yearToStr(Date year) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(year);
        return String.valueOf(calendar.get(Calendar.YEAR));
    }


}
