package com.awspaas.user.apps.bnbm.datalinkup.service.impl;

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.commons.database.RowMap;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.sdk.local.SDK;
import com.awspaas.user.apps.bnbm.datalinkup.entity.DateRange;
import com.awspaas.user.apps.bnbm.datalinkup.service.DataSummaryService;
import com.awspaas.user.apps.bnbm.datalinkup.util.PurchaseUtil;
import org.apache.commons.lang3.StringUtils;
import org.docx4j.org.apache.poi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 采购汇总计算实现类
 */
public class PurchaseDataSummaryServiceImpl implements DataSummaryService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PurchaseDataSummaryServiceImpl.class);

    // 维度表名常量
    /**
     * 采购_年月采购明细
     */
    private static final String PROCUREMENT_DETAILS_YEAR_MONTH = "BO_EU_CG_NYCGMX";
    /**
     * 采购_年月日采购明细
     */
    private static final String PROCUREMENT_DETAILS_YEAR_MONTH_DAY = "BO_EU_CG_NYRCGMX";
    /**
     * 采购_基地_年月采购明细
     */
    private static final String JD_PROCUREMENT_DETAILS_YEAR_MONTH = "BO_EU_CG_JD_NYCGMX";
    /**
     *
     */
    private static final String BO_EU_CG_NYRKMX = "BO_EU_CG_NYRKMX";

    // 原始数据表名
    /**
     * 采购_采购单_汇总
     */
    private static final String PROCUREMENT_PURCHASE_ORDER_SUMMARY = "BO_EU_DWD_ORDER_CGDD_HZ";
    /**
     *
     */
    private static final String BO_EU_DWD_ORDER_RKD_HZ = "BO_EU_DWD_ORDER_RKD_HZ";

    // 日期格式化
    private static final SimpleDateFormat YEAR_MONTH_FORMAT = new SimpleDateFormat("yyyy-MM");
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");


    // 缓存物料分类列表
    private List<String> distinctMaterialList = null;
    private long lastMaterialListUpdateTime = 0;
    private static final long MATERIAL_LIST_CACHE_TIME = 30 * 60 * 1000; // 30分钟缓存

    @Override
    public void calculateSummary(DateRange dateRange, BO mainConfig) {
//        LOGGER.info("dateRange:{},mainConfig：{}",dateRange,mainConfig.toJSONObject().toJSONString());
        try {
            // 从主配置获取BKGS值
            String bkgs = mainConfig.getString("BKGS");
            if (bkgs == null || bkgs.isEmpty()) {
                LOGGER.error("主配置中BKGS为空，无法进行汇总计算");
                return;
            }

            // 获取物料分类列表（带缓存）
//            List<String> distinctList = getDistinctMaterialList();

            if (dateRange == null || dateRange.getStartDate() == null || dateRange.getEndDate() == null) {
                LOGGER.info("未提供有效时间范围，按当前日期计算");
                String startDate = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-mm-dd"));
                // 1. 计算并保存各板块物料采购总额、总量、单价(按月存储)
                newmonthlyMaterialSummaryBySegment(startDate, bkgs);
                // 2. 根据年月汇总板块、基地、年月、当期、上期、同期数据
                newmonthlyBaseSummaryBySegment(startDate, bkgs);
                // 3. 计算并保存各板块物料采购总额、总量、单价(按日存储)
                newdailyMaterialSummaryBySegment(startDate, bkgs);
                // 4. 根据日期、入库单号、物料名称分页查询 日期、入库单号、物料编码、物料名称、规格型号、
                //   （汇总）入库数量、单位、入库单价、（汇总）入库金额、供应商、订单编号、库存数
                newdailyWarehousingSummary(startDate, bkgs);
            } else {
                LOGGER.info("开始执行采购数据多维度汇总计算（时间范围: {} 至 {})",
                        dateRange.getStartDate(), dateRange.getEndDate());
                String startDate = DATE_FORMAT.format(dateRange.getStartDate());
                //计算并保存各板块物料采购总额、总量、单价(按月存储)
                newmonthlyMaterialSummaryBySegment(startDate, bkgs);
                //根据年月汇总板块、基地、年月、当期、上期、同期数据
                newmonthlyBaseSummaryBySegment(startDate, bkgs);
                //计算并保存各板块物料采购总额、总量、单价(按日存储)
                newdailyMaterialSummaryBySegment(startDate, bkgs);
                // 4. 根据日期、入库单号、物料名称分页查询 日期、入库单号、物料编码、物料名称、规格型号、
                //   （汇总）入库数量、单位、入库单价、（汇总）入库金额、供应商、订单编号、库存数
                newdailyWarehousingSummary(startDate, bkgs);

                LOGGER.info("采购数据多维度汇总计算完成");
            }
        } catch (Exception e) {
            String errorMsg = "采购数据汇总计算失败: " + e.getMessage();
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 根据日期、入库单号、物料名称分页查询 日期、入库单号、物料编码、物料名称、规格型号、
     * @param startDate
     * @param bkgs
     * @param
     */
    private void newdailyWarehousingSummary(String startDate, String bkgs) {
        LOGGER.info("开始计算{}入库明细日度汇总数据，板块公司：{}", startDate, bkgs);

        try {
            // 1. 删除该日期已存在的汇总数据（避免重复）
            String deleteSql = "DELETE FROM BO_EU_CG_NYRKMX WHERE BKGS = ? AND DATE >= ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, startDate});
            LOGGER.info("已清理{}的旧入库明细数据", startDate);
            LOGGER.info("采购_年月入库明细：{}物料采购月度汇总数据，板块公司：{}，删除了{}条数据", startDate, bkgs, update);

            // 2. 计算总记录数用于分页
            String countSql = "SELECT COUNT(1) AS total FROM " + BO_EU_DWD_ORDER_RKD_HZ + " " +
                    " WHERE BKGS = ? AND DATE(DJRQ) >= ?";
            RowMap countResult = DBSql.getMap(countSql, bkgs, startDate);
            int totalCount = countResult.getInt("total");
            LOGGER.info("共查询到{}条入库记录需要处理", totalCount);

            if (totalCount == 0) {
                LOGGER.info("无入库数据需要处理，跳过");
                return;
            }

            // 3. 分页处理数据
            int pageSize = 10000;
            int totalPages = (int) Math.ceil((double) totalCount / pageSize);
            LOGGER.info("开始分页处理入库数据，共{}页", totalPages);

            for (int page = 0; page < totalPages; page++) {
                int offset = page * pageSize;
                LOGGER.debug("正在处理第{}页入库数据，偏移量：{}", page + 1, offset);
                String querySql = "SELECT BKGS, YEARMONTH, DJRQ, DJH, WLMC, WLBM, GGXH, SLGC, SUM(RKSL) AS RKSL, " +
                        "       JLDW, HSDJHYF, SUM(JSHJHYF) AS JSHJHYF, GYSNAME, CGDDH, SUM(DHJE) AS DHJE " +
                        " FROM "+BO_EU_DWD_ORDER_RKD_HZ+" WHERE BKGS = ? AND DATE(DJRQ) >= ? " +
                        " GROUP BY YEARMONTH,DJH,WLMC " +
                        " ORDER BY DJRQ LIMIT ? OFFSET ?";

                List<RowMap> pageData = DBSql.getMaps(querySql, bkgs, startDate, pageSize, offset);
                LOGGER.debug("第{}页查询到{}条记录", page + 1, pageData.size());

                // 转换并批量插入数据
                List<BO> bos = new ArrayList<>();
                for (RowMap row : pageData) {
                    BO detailBO = new BO();
                    detailBO.set("DATE", row.getDate("DJRQ")); // 入库日期
                    detailBO.set("RKDH", row.getString("DJH")); // 入库单号
                    detailBO.set("WLBM", row.getString("WLBM")); // 物料编码
                    String wlmc = row.getString("WLMC");
                    detailBO.set("WLMC", wlmc); // 物料名称
                    detailBO.set("GGXH", row.getString("GGXH")); // 规格型号
                    detailBO.set("GC", row.getString("SLGC")); // 收料工厂
                    // 处理入库数量，防止空值
                    Double rksl = row.getDouble("RKSL");
                    detailBO.set("RKSL", rksl != null ? rksl : 0.0); // 入库数量
                    detailBO.set("DW", row.getString("JLDW")); // 单位
                    // 处理单价和金额，添加除零检查
                    if ("泰山石膏".equals(bkgs)) {
                        Double dhje = row.getDouble("DHJE");
//                        double rkdj = 0.0;
//                        if (dhje != null && dhje != 0 && rksl != null && rksl != 0) {
//                            rkdj = dhje / rksl;
//                        }
                        detailBO.set("RKDJ", row.getString("HSDJHYF")); // 入库单价
                        detailBO.set("RKJE", dhje != null ? dhje : 0.0); // 入库单价
                    } else {
                        Double jshjhyf = row.getDouble("JSHJHYF");
                        double rkdj = 0.0;
                        if (jshjhyf != null && jshjhyf != 0 && rksl != null && rksl != 0) {
                            rkdj = jshjhyf / rksl;
                        }
                        detailBO.set("RKDJ", rkdj); // 入库单价
                        detailBO.set("RKJE", jshjhyf != null ? jshjhyf : 0.0); // 入库金额
                    }
                    detailBO.set("GYS", row.getString("GYSNAME")); // 供应商
                    detailBO.set("DDBH", row.getString("CGDDH")); // 订单编号
                    detailBO.set("KCS", 0.00); // 库存数（默认为0，需后续计算）
                    detailBO.set("BKGS", bkgs); // 板块公司
                    YearMonth yearMonths = YearMonth.parse(row.getString("YEARMONTH"), DateTimeFormatter.ofPattern("yyyyMM"));
                    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
                    String yearmonth = yearMonths.format(outputFormatter);
                    detailBO.set("YEARMONTH", yearmonth); // 年月
                    bos.add(detailBO);
                }
                // 批量插入当前页数据
                if (!bos.isEmpty()) {
                    SDK.getBOAPI().createDataBO(BO_EU_CG_NYRKMX, bos, UserContext.fromUID("admin"));
                    LOGGER.debug("入库明细日度汇总数据，板块公司：{}, 第{}页数据插入成功，共{}条,数量总共{}条",
                            bkgs, page + 1, bos.size(),totalCount);
                }
            }

            LOGGER.info("{}开始入库明细日度汇总完成，共处理{}条数据", startDate, totalCount);
        } catch (Exception e) {
            String errorMsg = String.format("日度入库明细汇总失败(日期=%s,板块=%s): %s",
                    startDate, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 计算并保存各板块物料采购总额、总量、单价(按日存储)
     * @param startDate
     * @param bkgs
     * @param
     */
    private void newdailyMaterialSummaryBySegment(String startDate, String bkgs) {
        try {
            // 格式化日期字符串 (yyyy-MM-dd)
            LOGGER.info("开始计算{}物料采购日度汇总数据，板块公司：{}", startDate, bkgs);
            // 1. 删除该日期已存在的汇总数据
            String deleteSql = "DELETE FROM " + PROCUREMENT_DETAILS_YEAR_MONTH_DAY +
                    " WHERE BKGS = ? AND RQ >= ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, startDate});
            LOGGER.info("采购_年月日采购明细：{}物料采购月度汇总数据，板块公司：{}，删除了{}条数据", startDate, bkgs, update);

            String querySql = "SELECT BKGS,DJRQ,WLMC, SUM(DHJE) AS tstotalAmount,SUM(JSHJHYF) AS lptotalAmount,SUM(RKSL) AS totalQuantity" +
                    " FROM BO_EU_DWD_ORDER_RKD_HZ WHERE BKGS = ? AND DJRQ >= ?" +
                    " GROUP BY WLMC,DJRQ" +
                    " ORDER BY DJRQ";
            List<RowMap> dailyData = DBSql.getMaps(querySql, bkgs, startDate);
            // 批量插入
            if (dailyData==null){
                return;
            }
            List<BO> bos = new ArrayList<>();
            for (RowMap row : dailyData) {
                String bkgs1 = row.getString("BKGS");
                String wlmc = row.getString("WLMC");
                String djrq = row.getString("DJRQ");
                Double totalQuantity = row.getDouble("totalQuantity");
                double safeTotalQuantity = totalQuantity != null ? totalQuantity : 0.0;
                Double totalAmount = 0.0;
                double avgPrice = 0.0;
                BO summaryBO = new BO();
                summaryBO.set("BKGS", bkgs1);
                summaryBO.set("WLMC", wlmc);
                summaryBO.set("RQ", djrq);
                if (bkgs1.equals("泰山石膏")){
                    totalAmount = row.getDouble("tstotalAmount");
                    double safeTotalAmount = totalAmount != null ? totalAmount : 0.0;
                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")) {
                        double adjustedQuantity = safeTotalQuantity / 1000;
                        summaryBO.set("CGZL", adjustedQuantity);
                        // 添加除零检查
                        if (safeTotalAmount != 0 && adjustedQuantity != 0) {
                            avgPrice = safeTotalAmount / adjustedQuantity;
                        } else {
                            avgPrice = 0.0;
                        }
                    } else {
                        summaryBO.set("CGZL", safeTotalQuantity);
                        // 添加除零检查
                        if (safeTotalAmount != 0 && safeTotalQuantity != 0) {
                            avgPrice = safeTotalAmount / safeTotalQuantity;
                        } else {
                            avgPrice = 0.0;
                        }
                    }
                    summaryBO.set("CGZE", safeTotalAmount);
                }else {
                    totalAmount = row.getDouble("lptotalAmount");
                    double safeTotalAmount = totalAmount != null ? totalAmount : 0.0;
                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")) {
                        double adjustedQuantity = safeTotalQuantity / 1000;
                        summaryBO.set("CGZL", adjustedQuantity);
                        // 添加除零检查
                        if (safeTotalAmount != 0 && adjustedQuantity != 0) {
                            avgPrice = safeTotalAmount / adjustedQuantity;
                        } else {
                            avgPrice = 0.0;
                        }
                    } else {
                        summaryBO.set("CGZL", safeTotalQuantity);
                        // 添加除零检查
                        if (safeTotalAmount != 0 && safeTotalQuantity != 0) {
                            avgPrice = safeTotalAmount / safeTotalQuantity;
                        } else {
                            avgPrice = 0.0;
                        }
                    }
                    summaryBO.set("CGZE", safeTotalAmount);
                }
                summaryBO.set("PJDJ", avgPrice);
                bos.add(summaryBO);
            }
            if (!bos.isEmpty()) {
                SDK.getBOAPI().createDataBO(PROCUREMENT_DETAILS_YEAR_MONTH_DAY, bos, UserContext.fromUID("admin"));
            }

            LOGGER.info("成功保存{}条日度汇总数据，板块：{}", bos.size(), bkgs);
        } catch (Exception e) {
            String errorMsg = String.format("日度汇总计算失败(日期=%s,板块=%s): %s", startDate, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 根据年月汇总板块、基地、年月、当期、上期、同期数据
     * @param startDate
     * @param bkgs
     * @param
     */
    private void newmonthlyBaseSummaryBySegment(String startDate, String bkgs) {
        try {
            LOGGER.info("开始计算{}物料采购各基地月度汇总数据，板块公司：{}", startDate, bkgs);
            LocalDate date = LocalDate.parse(startDate);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
            String yearMonth = date.format(formatter);
            // 1. 删除该月份已存在的汇总数据（避免重复）
            String deleteSql = "DELETE FROM " + JD_PROCUREMENT_DETAILS_YEAR_MONTH +
                    " WHERE BKGS = ? AND YEARMONTH >= ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, yearMonth});
            LOGGER.info("采购_基地_年月采购明细：{}年月物料采购月度汇总数据，板块公司：{}，删除了{}条数据", yearMonth, bkgs, update);

            String currentMonthSql = "SELECT c.BKGS AS BKGS," +
                    " CONCAT(c.Year, '-', LPAD(c.Month, 2, '0')) AS ny, " +
                    " c.Year AS year, " +
                    " c.Month AS month, " +
                    " c.WLMC AS WLMC, " +
                    " c.SLGC AS SLGC, " +
                    " c.tstotalAmount AS tstotalAmount, " +
                    " c.totalQuantity AS totalQuantity, " +
                    " tstotalAmount/totalQuantity AS PJDJ " +
                    " FROM (" +
                    "    SELECT " +
                    "        WLMC, BKGS, " +
                    "        SUM(DHJE) AS tstotalAmount, " +
                    "        SUM(RKSL) AS totalQuantity, " +
                    "        SLGC, " +
                    "        YEAR(DJRQ) AS Year, " +
                    "        MONTH(DJRQ) AS Month " +
                    "    FROM BO_EU_DWD_ORDER_RKD_HZ " +
                    "    WHERE BKGS = ? " +
                    "        AND DJRQ >= CONCAT(YEAR(?), '-', LPAD(MONTH(?), 2, '0'), '-01')" +
                    "    GROUP BY WLMC, YEAR(DJRQ), MONTH(DJRQ),SLGC " +
                    " ) c " +
                    " ORDER BY c.Year, c.Month";
            List<RowMap> currentMonthData = DBSql.getMaps(currentMonthSql, bkgs, startDate,startDate);
            if (currentMonthData==null){
                return;
            }
            // 5. 批量插入
            List<BO> bos = new ArrayList<>();
            for (RowMap currentMonthRow : currentMonthData) {
                String base = currentMonthRow.getString("SLGC");
                String wlmc = currentMonthRow.getString("WLMC");
                String bkgs1 = currentMonthRow.getString("BKGS");
                BO summaryBO = new BO();
                summaryBO.set("BKGS", bkgs1);
                summaryBO.set("JD", base);
                summaryBO.set("WLMC",wlmc);
                summaryBO.set("YEARMONTH",currentMonthRow.getString("ny"));//年月（YYYYMM）
                Double tstotalAmount = currentMonthRow.getDouble("tstotalAmount");
                Double totalQuantity = currentMonthRow.getDouble("totalQuantity");
                summaryBO.set("CGZE", tstotalAmount);//采购总额
                summaryBO.set("CGZL",totalQuantity);//采购总量
                summaryBO.set("SLGC",currentMonthRow.getString("SLGC"));//收料工厂
                summaryBO.set("PJDJ",currentMonthRow.getDouble("PJDJ"));
                bos.add(summaryBO);
            }
            if (!bos.isEmpty()) {
                // 批量插入数据
                    SDK.getBOAPI().createDataBO(JD_PROCUREMENT_DETAILS_YEAR_MONTH, bos, UserContext.fromUID("admin"));
            }
            LOGGER.info("成功保存{}条月度基地汇总数据，板块：{}", bos.size(), bkgs);

        } catch (Exception e) {
            String errorMsg = String.format("月度基地汇总计算失败(开始时间=%s,板块=%s): %s", startDate, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 计算并保存各板块物料采购总额、总量、单价(按月存储)
     * 逻辑：按物料名称(WLMC)分组，计算月度采购总额(SUM(JSHJ))、采购总量(SUM(YSSL))和平均单价(采购总额/采购总量)
     * @param startDate
     * @param bkgs
     * @param
     */
    private void newmonthlyMaterialSummaryBySegment(String startDate, String bkgs) {
        try {
            LOGGER.info("开始计算{}物料采购月度汇总数据，板块公司：{}", startDate, bkgs);
            LocalDate date = LocalDate.parse(startDate);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
            String yearMonth = date.format(formatter);

            // 1. 删除该月份已存在的汇总数据（避免重复）
            String deleteSql = "DELETE FROM " + PROCUREMENT_DETAILS_YEAR_MONTH +
                    " WHERE BKGS = ? AND YEARMONTH >= ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, yearMonth});
            LOGGER.info("采购_年月采购明细：{}年月物料采购月度汇总数据，板块公司：{}，删除了{}条数据",yearMonth, bkgs, update);
            String currentMonthSql = "SELECT " +
                    " CONCAT(c.Year, '-', LPAD(c.Month, 2, '0')) AS ny, " +
                    " c.Year AS year, " +
                    " c.Month AS month, " +
                    " c.WLMC AS WLMC, " +
                    " c.tstotalAmount AS tstotalAmount, " +
                    " c.totalQuantity AS totalQuantity, " +
                    " tstotalAmount/totalQuantity AS PJDJ " +
                    " FROM (" +
                    "    SELECT " +
                    "        WLMC, " +
                    "        SUM(DHJE) AS tstotalAmount, " +
                    "        SUM(RKSL) AS totalQuantity, " +
                    "        YEAR(DJRQ) AS Year, " +
                    "        MONTH(DJRQ) AS Month " +
                    "    FROM BO_EU_DWD_ORDER_RKD_HZ " +
                    "    WHERE BKGS = ? " +
                    "        AND DJRQ >= CONCAT(YEAR(?), '-', LPAD(MONTH(?), 2, '0'), '-01')" +
                    "    GROUP BY WLMC, YEAR(DJRQ), MONTH(DJRQ) " +
                    " ) c " +
                    " ORDER BY c.Year, c.Month";
            List<RowMap> currentMonthData = DBSql.getMaps(currentMonthSql, bkgs, startDate,startDate);
            if (currentMonthData==null){
                return;
            }
            // 4. 批量插入
            List<BO> bos = new ArrayList<>();
            for (RowMap currentMonthRow : currentMonthData) {
                String wlmc = currentMonthRow.getString("WLMC");
                BO bo = new BO();
                bo.set("BKGS",bkgs);//板块
                bo.set("WLMC",wlmc);//物料名称
                bo.set("YEARMONTH",currentMonthRow.getString("ny"));//年月（YYYYMM）
                Double tstotalAmount = currentMonthRow.getDouble("tstotalAmount");
                Double totalQuantity = currentMonthRow.getDouble("totalQuantity");
                bo.set("CGZE", tstotalAmount);//采购总额
                bo.set("CGZL",totalQuantity);//采购总量
                bo.set("PJDJ",currentMonthRow.getDouble("PJDJ"));
                bos.add(bo);
            }
            if (!bos.isEmpty()) {
                SDK.getBOAPI().createDataBO(PROCUREMENT_DETAILS_YEAR_MONTH, bos, UserContext.fromUID("admin"));
            }

            LOGGER.info("成功保存{}条月度汇总数据，板块：{}", bos.size(), bkgs);

        } catch (Exception e) {
            String errorMsg = String.format("月度汇总计算失败(开始时间=%s,板块=%s): %s", startDate, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 获取物料分类列表（带缓存）
     */
    private List<String> getDistinctMaterialList() {
        long currentTime = System.currentTimeMillis();
        if (distinctMaterialList != null && (currentTime - lastMaterialListUpdateTime) < MATERIAL_LIST_CACHE_TIME) {
            return distinctMaterialList;
        }

        try {
//            List<RowMap> maps = DBSql.getMaps("SELECT WLMC FROM " + PROCUREMENT_PURCHASE_ORDER_SUMMARY + " GROUP BY WLMC");
            List<RowMap> maps = DBSql.getMaps("SELECT WLMC FROM " + BO_EU_DWD_ORDER_RKD_HZ + "  GROUP BY WLMC");
            Set<String> resultSet = new HashSet<>();
            for (RowMap row : maps) {
                String wlmc = row.getString("WLMC");
                if (StringUtils.isBlank(wlmc)) continue;

                if (wlmc.contains("|")) {
                    String[] parts = wlmc.split("\\|");
                    if (parts.length > 0 && StringUtils.isNotBlank(parts[0])) {
                        resultSet.add(parts[0].trim());
                    }
                } else {
                    resultSet.add(wlmc.trim());
                }
            }

            distinctMaterialList = new ArrayList<>(resultSet);
            lastMaterialListUpdateTime = currentTime;
            LOGGER.info("物料分类列表已更新，共{}种物料", distinctMaterialList.size());

            return distinctMaterialList;
        } catch (Exception e) {
            LOGGER.error("获取物料分类列表失败: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }

    /**
     * 按当前日期计算（无时间范围时使用）
     */
    private void calculateForCurrentDate(String bkgs, List<String> distinctList) {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        int day = cal.get(Calendar.DAY_OF_MONTH);

        // 当前年月
        String yearMonth = String.format("%04d-%02d", year, month);

        // 上月
        cal.add(Calendar.MONTH, -1);
        String yearLastMonth = String.format("%04d-%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);

        // 上年同期
        cal.add(Calendar.YEAR, 1); // 回到当前年
        cal.add(Calendar.YEAR, -1); // 再减一年
        String lastYearMonth = String.format("%04d-%02d", cal.get(Calendar.YEAR), month);

        Date currentDate = new Date(System.currentTimeMillis());

        // 1. 计算并保存各板块物料采购总额、总量、单价(按月存储)
//        monthlyMaterialSummaryBySegment(year, month, yearMonth, yearLastMonth, lastYearMonth, bkgs, distinctList);

        // 2. 根据年月汇总板块、基地、年月、当期、上期、同期数据
//        monthlyBaseSummaryBySegment(year, month, yearMonth, yearLastMonth, lastYearMonth, bkgs, distinctList);

        // 3. 计算并保存各板块物料采购总额、总量、单价(按日存储)
//        dailyMaterialSummaryBySegment(year, month, day, currentDate, bkgs, distinctList);

        // 4. 根据日期、入库单号、物料名称分页查询 日期、入库单号、物料编码、物料名称、规格型号、
        //   （汇总）入库数量、单位、入库单价、（汇总）入库金额、供应商、订单编号、库存数
//        dailyWarehousingSummary(year, month, day, currentDate, bkgs, distinctList);

    }

    /**
     * 计算月度维度数据
     */
    private void calculateMonthlyData(DateRange dateRange, String bkgs, List<String> distinctList) {
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(dateRange.getStartDate());
        startCal.set(Calendar.DAY_OF_MONTH, 1); // 设置为月份的第一天

        Calendar endCal = Calendar.getInstance();
        endCal.setTime(dateRange.getEndDate());
        endCal.set(Calendar.DAY_OF_MONTH, endCal.getActualMaximum(Calendar.DAY_OF_MONTH)); // 设置为月份的最后一天

        Calendar monthCal = (Calendar) startCal.clone();

        while (!monthCal.after(endCal)) {
            int year = monthCal.get(Calendar.YEAR);
            int month = monthCal.get(Calendar.MONTH) + 1;

            // 当前年月
            String yearMonth = String.format("%04d-%02d", year, month);

            // 上月
            Calendar lastMonthCal = (Calendar) monthCal.clone();
            lastMonthCal.add(Calendar.MONTH, -1);
            String yearLastMonth = String.format("%04d-%02d", lastMonthCal.get(Calendar.YEAR), lastMonthCal.get(Calendar.MONTH) + 1);

            // 上年同期
            Calendar lastYearMonthCal = (Calendar) monthCal.clone();
            lastYearMonthCal.add(Calendar.YEAR, -1);
            String lastYearMonth = String.format("%04d-%02d", lastYearMonthCal.get(Calendar.YEAR), lastYearMonthCal.get(Calendar.MONTH) + 1);

            LOGGER.info("计算月度汇总数据: {}-{}；上月：{}；上年同期：{}", year, month, yearLastMonth, lastYearMonth);

            // 1. 计算并保存各板块物料采购总额、总量、单价(按月存储)
//            monthlyMaterialSummaryBySegment(year, month, yearMonth, yearLastMonth, lastYearMonth, bkgs, distinctList);

            // 2. 根据年月汇总板块、基地、年月、当期、上期、同期数据
//            monthlyBaseSummaryBySegment(year, month, yearMonth, yearLastMonth, lastYearMonth, bkgs, distinctList);

            // 移动到下个月
            monthCal.add(Calendar.MONTH, 1);
        }
    }

    /**
     * 计算日度维度数据
     */
    private void calculateDailyData(DateRange dateRange, String bkgs, List<String> distinctList) {
        Calendar dayCal = Calendar.getInstance();
        dayCal.setTime(dateRange.getStartDate());

        Calendar endCal = Calendar.getInstance();
        endCal.setTime(dateRange.getEndDate());

        while (!dayCal.after(endCal)) {
            int year = dayCal.get(Calendar.YEAR);
            int month = dayCal.get(Calendar.MONTH) + 1;
            int day = dayCal.get(Calendar.DAY_OF_MONTH);
            Date currentDate = dayCal.getTime();

            LOGGER.info("计算日度汇总数据: {}-{}-{}", year, month, day);

            // 计算并保存各板块物料采购总额、总量、单价(按日存储)
//            dailyMaterialSummaryBySegment(year, month, day, currentDate, bkgs, distinctList);

            // 根据日期、入库单号、物料名称分页查询 日期、入库单号、物料编码、物料名称、规格型号、
                //（汇总）入库数量、单位、入库单价、（汇总）入库金额、供应商、订单编号、库存数
//            dailyWarehousingSummary(year, month, day, currentDate, bkgs, distinctList);

            // 下一天
            dayCal.add(Calendar.DATE, 1);
        }
    }

    /**
     * 根据年月汇总 板块、基地、年月、当期（采购总额、采购总量、采购平均价）、上期（采购总额、采购总量、采购平均价）、同期（采购总额、采购总量、采购平均价）
     * @param year
     * @param month
     * @param yearMonth
     * @param yearLastMonth
     * @param lastYearMonth
     * @param bkgs
     */
    private void monthlyBaseSummaryBySegment(int year, int month, String yearMonth, String yearLastMonth,
                                             String lastYearMonth, String bkgs, List<String> distinctList) {
        try {
            LOGGER.info("开始计算{}年{}月物料采购各基地月度汇总数据，板块公司：{}", year, month, bkgs);

            // 1. 删除该月份已存在的汇总数据（避免重复）
            String deleteSql = "DELETE FROM " + JD_PROCUREMENT_DETAILS_YEAR_MONTH +
                    " WHERE BKGS = ? AND YEARMONTH = ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, yearMonth});
            LOGGER.info("采购_基地_年月采购明细：{}年{}月物料采购月度汇总数据，板块公司：{}，删除了{}条数据", year, month, bkgs, update);

            // 2. 一次性查询当前月、上月和去年同期数据（包含基地信息）
            // 当前月数据
//            String currentMonthSql = "SELECT WLMC, XQGC, SUM(JSHJ) AS totalAmount, SUM(YSSL) AS totalQuantity " +
//                    "FROM " + PROCUREMENT_PURCHASE_ORDER_SUMMARY +
//                    " WHERE BKGS = ? AND CGRQ LIKE ? " +
//                    "GROUP BY WLMC, XQGC";
            String field = "";
            if ("泰山石膏".equals(bkgs)) {
                field = " SUM(DHJE) ";
            }else {
                field = " SUM(JSHJHYF) ";
            }
            String currentMonthSql = "SELECT WLMC, SLGC, "+field+" AS totalAmount, SUM(RKSL) AS totalQuantity " +
                    "FROM " + BO_EU_DWD_ORDER_RKD_HZ +
                    " WHERE BKGS = ? AND DJRQ LIKE ? " +
                    "GROUP BY WLMC, SLGC";
            List<RowMap> currentMonthData = DBSql.getMaps(currentMonthSql, bkgs, yearMonth + "%");

            // 上月数据
            List<RowMap> lastMonthData = Collections.emptyList();
            if (StringUtils.isNotBlank(yearLastMonth)) {
                lastMonthData = DBSql.getMaps(currentMonthSql, bkgs, yearLastMonth + "%");
            }

            // 去年同期数据
            List<RowMap> lastYearMonthData = Collections.emptyList();
            if (StringUtils.isNotBlank(lastYearMonth)) {
                lastYearMonthData = DBSql.getMaps(currentMonthSql, bkgs, lastYearMonth + "%");
            }

            // 3. 创建物料名称和基地组合键映射的数据Map
            // 当前月数据映射
            Map<String, RowMap> currentMonthMap = currentMonthData.stream()
                    .collect(Collectors.toMap(
                            row -> {
                                String wlmc = row.getString("WLMC");
                                String base = row.getString("SLGC");
                                String processedWlmc = processMaterialName(wlmc);
                                return processedWlmc + "|" + base;
                            },
                            row -> row,
                            (existing, replacement) -> {
                                double existingAmount = existing.getDouble("totalAmount");
                                double replacementAmount = replacement.getDouble("totalAmount");
                                existing.put("totalAmount", existingAmount + replacementAmount);

                                double existingQuantity = existing.getDouble("totalQuantity");
                                double replacementQuantity = replacement.getDouble("totalQuantity");
                                existing.put("totalQuantity", existingQuantity + replacementQuantity);

                                return existing;
                            }
                    ));

            // 上月数据映射
            Map<String, RowMap> lastMonthMap = lastMonthData.stream()
                    .collect(Collectors.toMap(
                            row -> {
                                String wlmc = row.getString("WLMC");
                                String base = row.getString("SLGC");
                                String processedWlmc = processMaterialName(wlmc);
                                return processedWlmc + "|" + base;
                            },
                            row -> row,
                            (existing, replacement) -> {
                                double existingAmount = existing.getDouble("totalAmount");
                                double replacementAmount = replacement.getDouble("totalAmount");
                                existing.put("totalAmount", existingAmount + replacementAmount);

                                double existingQuantity = existing.getDouble("totalQuantity");
                                double replacementQuantity = replacement.getDouble("totalQuantity");
                                existing.put("totalQuantity", existingQuantity + replacementQuantity);

                                return existing;
                            }
                    ));

            // 去年同期数据映射
            Map<String, RowMap> lastYearMonthMap = lastYearMonthData.stream()
                    .collect(Collectors.toMap(
                            row -> {
                                String wlmc = row.getString("WLMC");
                                String base = row.getString("SLGC");
                                String processedWlmc = processMaterialName(wlmc);
                                return processedWlmc + "|" + base;
                            },
                            row -> row,
                            (existing, replacement) -> {
                                double existingAmount = existing.getDouble("totalAmount");
                                double replacementAmount = replacement.getDouble("totalAmount");
                                existing.put("totalAmount", existingAmount + replacementAmount);

                                double existingQuantity = existing.getDouble("totalQuantity");
                                double replacementQuantity = replacement.getDouble("totalQuantity");
                                existing.put("totalQuantity", existingQuantity + replacementQuantity);

                                return existing;
                            }
                    ));

            // 4. 获取所有基地
//            Set<String> bases = new HashSet<>();
//            for (RowMap row : currentMonthData) {
//                bases.add(row.getString("SLGC"));
//            }

            // 5. 批量插入
            List<BO> bos = new ArrayList<>();
            for (RowMap currentMonthRow : currentMonthData) {
                String base = currentMonthRow.getString("SLGC");
                String wlmc = currentMonthRow.getString("WLMC");
                String key = wlmc + "|" + base;
                double avgPrice = 0.00;
                BO summaryBO = new BO();
                summaryBO.set("BKGS", bkgs);
                summaryBO.set("JD", base);
                summaryBO.set("WLMC",wlmc);
                if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")){
                    double totalQuantity = BigDecimal.valueOf(currentMonthRow.getDouble("totalQuantity"))
                            .divide(BigDecimal.valueOf(1000), 4, BigDecimal.ROUND_HALF_UP).doubleValue();
                    double totalAmount = currentMonthRow.getDouble("totalAmount");

                    summaryBO.set("CGZL", totalQuantity);
                    // 添加除数非零检查
                    if (totalAmount != 0 && totalQuantity != 0) {
                        avgPrice = BigDecimal.valueOf(totalAmount)
                                .divide(BigDecimal.valueOf(totalQuantity), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    } else {
                        avgPrice = 0;
                    }
                }else {
                    double totalQuantity = currentMonthRow.getDouble("totalQuantity");
                    double totalAmount = currentMonthRow.getDouble("totalAmount");

                    summaryBO.set("CGZL", totalQuantity);
                    // 添加除数非零检查
                    if (totalAmount != 0 && totalQuantity != 0) {
                        avgPrice = BigDecimal.valueOf(totalAmount)
                                .divide(BigDecimal.valueOf(totalQuantity), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    } else {
                        avgPrice = 0;
                    }
                }
                summaryBO.set("YEARMONTH", yearMonth);
                summaryBO.set("CGZE", currentMonthRow.getDouble("totalAmount"));
                summaryBO.set("PJDJ", avgPrice);

                // 添加上月数据
                RowMap lastMonthRow = lastMonthMap.get(key);
                if (lastMonthRow != null) {
                    double lastMonthAvgPrice = 0.00;
                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")){
                        double totalQuantity = BigDecimal.valueOf(lastMonthRow.getDouble("totalQuantity"))
                                .divide(BigDecimal.valueOf(1000), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        double totalAmount = lastMonthRow.getDouble("totalAmount");

                        summaryBO.set("SQCGZL", totalQuantity);
                        // 添加除数非零检查
                        if (totalAmount != 0 && totalQuantity != 0) {
                            lastMonthAvgPrice = BigDecimal.valueOf(totalAmount)
                                    .divide(BigDecimal.valueOf(totalQuantity), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        } else {
                            lastMonthAvgPrice = 0;
                        }
                    }else {
                        double totalQuantity = lastMonthRow.getDouble("totalQuantity");
                        double totalAmount = lastMonthRow.getDouble("totalAmount");

                        summaryBO.set("SQCGZL", totalQuantity);
                        // 添加除数非零检查
                        if (totalAmount != 0 && totalQuantity != 0) {
                            lastMonthAvgPrice = BigDecimal.valueOf(totalAmount)
                                    .divide(BigDecimal.valueOf(totalQuantity), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        } else {
                            lastMonthAvgPrice = 0;
                        }
                    }
                    summaryBO.set("SQCGZE", lastMonthRow.getDouble("totalAmount"));
                    summaryBO.set("SQPJDJ", lastMonthAvgPrice);
                }

                // 添加去年同期数据
                RowMap lastYearMonthRow = lastYearMonthMap.get(key);
                if (lastYearMonthRow != null) {
                    double lastYearMonthAvgPrice = 0.00;
                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")){
                        double totalQuantity = BigDecimal.valueOf(lastYearMonthRow.getDouble("totalQuantity"))
                                .divide(BigDecimal.valueOf(1000), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        double totalAmount = lastYearMonthRow.getDouble("totalAmount");

                        summaryBO.set("TQCGZL", totalQuantity);
                        // 添加除数非零检查
                        if (totalAmount != 0 && totalQuantity != 0) {
                            lastYearMonthAvgPrice = BigDecimal.valueOf(totalAmount)
                                    .divide(BigDecimal.valueOf(totalQuantity), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        } else {
                            lastYearMonthAvgPrice = 0;
                        }
                    }else {
                        double totalQuantity = lastYearMonthRow.getDouble("totalQuantity");
                        double totalAmount = lastYearMonthRow.getDouble("totalAmount");

                        summaryBO.set("TQCGZL", totalQuantity);
                        // 添加除数非零检查
                        if (totalAmount != 0 && totalQuantity != 0) {
                            lastYearMonthAvgPrice = BigDecimal.valueOf(totalAmount)
                                    .divide(BigDecimal.valueOf(totalQuantity), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        } else {
                            lastYearMonthAvgPrice = 0;
                        }
                    }
                    summaryBO.set("TQCGZE",lastYearMonthRow.getDouble("totalAmount"));
                    summaryBO.set("TQPJDJ", lastYearMonthAvgPrice);
                }
                bos.add(summaryBO);
            }
            if (!bos.isEmpty()) {
                // 批量插入数据
                int batchSize = 1000;
                for (int i = 0; i < bos.size(); i += batchSize) {
                    int end = Math.min(i + batchSize, bos.size());
                    List<BO> batch = bos.subList(i, end);
                    SDK.getBOAPI().createDataBO(JD_PROCUREMENT_DETAILS_YEAR_MONTH, batch, UserContext.fromUID("admin"));
                }
            }
            LOGGER.info("成功保存{}条月度基地汇总数据，板块：{}", bos.size(), bkgs);

        } catch (Exception e) {
            String errorMsg = String.format("月度基地汇总计算失败(年月=%s,板块=%s): %s", yearMonth, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 计算并保存各板块物料采购总额、总量、单价(按月存储)
     * 逻辑：按物料名称(WLMC)分组，计算月度采购总额(SUM(JSHJ))、采购总量(SUM(YSSL))和平均单价(采购总额/采购总量)
     * @param year 年份
     * @param month 月份
     * @param yearMonth 年月字符串(格式：yyyy-MM)
     * @param bkgs 板块公司
     */
    private void monthlyMaterialSummaryBySegment(int year, int month, String yearMonth,
                              String yearLastMonth, String lastYearMonth, String bkgs, List<String> distinctList) {
        try {
            LOGGER.info("开始计算{}年{}月物料采购月度汇总数据，板块公司：{}", year, month, bkgs);

            // 1. 删除该月份已存在的汇总数据（避免重复）
            String deleteSql = "DELETE FROM " + PROCUREMENT_DETAILS_YEAR_MONTH +
                    " WHERE BKGS = ? AND YEARMONTH = ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, yearMonth});
            LOGGER.info("采购_年月采购明细：{}年{}月物料采购月度汇总数据，板块公司：{}，删除了{}条数据", year, month, bkgs, update);

            // 当前月数据
//            String currentMonthSql = "SELECT WLMC, SUM(JSHJ) AS totalAmount, SUM(YSSL) AS totalQuantity " +
//                    "FROM " + PROCUREMENT_PURCHASE_ORDER_SUMMARY +
//                    " WHERE BKGS = ? AND CGRQ LIKE ? " +
//                    "GROUP BY WLMC";
            String field = "";
            if ("泰山石膏".equals(bkgs)) {
                field = " SUM(DHJE) ";
            }else {
                field = " SUM(JSHJHYF) ";
            }
            String currentMonthSql = "SELECT WLMC, "+field+" AS totalAmount, SUM(RKSL) AS totalQuantity " +
                    " FROM " + BO_EU_DWD_ORDER_RKD_HZ +
                    " WHERE BKGS = ? AND DJRQ LIKE ? " +
                    " GROUP BY WLMC";
            List<RowMap> currentMonthData = DBSql.getMaps(currentMonthSql, bkgs, yearMonth + "%");

            // 上月数据
            List<RowMap> lastMonthData = Collections.emptyList();
            if (StringUtils.isNotBlank(yearLastMonth)) {
                lastMonthData = DBSql.getMaps(currentMonthSql, bkgs, yearLastMonth + "%");
            }

            // 去年同期数据
            List<RowMap> lastYearMonthData = Collections.emptyList();
            if (StringUtils.isNotBlank(lastYearMonth)) {
                lastYearMonthData = DBSql.getMaps(currentMonthSql, bkgs, lastYearMonth + "%");
            }

            // 3. 创建物料名称映射的数据Map
            // 当前月数据映射
            Map<String, RowMap> currentMonthMap = currentMonthData.stream()
                    .collect(Collectors.toMap(
                            row -> processMaterialName(row.getString("WLMC")),
                            row -> row,
                            (existing, replacement) -> {
                                double existingAmount = existing.getDouble("totalAmount");
                                double replacementAmount = replacement.getDouble("totalAmount");
                                existing.put("totalAmount", existingAmount + replacementAmount);

                                double existingQuantity = existing.getDouble("totalQuantity");
                                double replacementQuantity = replacement.getDouble("totalQuantity");
                                existing.put("totalQuantity", existingQuantity + replacementQuantity);

                                return existing;
                            }
                    ));

            // 上月数据映射
            Map<String, RowMap> lastMonthMap = lastMonthData.stream()
                    .collect(Collectors.toMap(
                            row -> processMaterialName(row.getString("WLMC")),
                            row -> row,
                            (existing, replacement) -> {
                                double existingAmount = existing.getDouble("totalAmount");
                                double replacementAmount = replacement.getDouble("totalAmount");
                                existing.put("totalAmount", existingAmount + replacementAmount);

                                double existingQuantity = existing.getDouble("totalQuantity");
                                double replacementQuantity = replacement.getDouble("totalQuantity");
                                existing.put("totalQuantity", existingQuantity + replacementQuantity);

                                return existing;
                            }
                    ));

            // 去年同期数据映射
            Map<String, RowMap> lastYearMonthMap = lastYearMonthData.stream()
                    .collect(Collectors.toMap(
                            row -> processMaterialName(row.getString("WLMC")),
                            row -> row,
                            (existing, replacement) -> {
                                double existingAmount = existing.getDouble("totalAmount");
                                double replacementAmount = replacement.getDouble("totalAmount");
                                existing.put("totalAmount", existingAmount + replacementAmount);

                                double existingQuantity = existing.getDouble("totalQuantity");
                                double replacementQuantity = replacement.getDouble("totalQuantity");
                                existing.put("totalQuantity", existingQuantity + replacementQuantity);

                                return existing;
                            }
                    ));

            // 4. 批量插入
            List<BO> bos = new ArrayList<>();
//            for (String wlmc : distinctList) {
//            RowMap currentMonthRow = currentMonthMap.get(wlmc);


//            for (RowMap currentMonthRow : currentMonthData) {
//                String wlmc = currentMonthRow.getString("WLMC");
//                if (currentMonthRow == null || currentMonthRow.getDouble("totalAmount") == 0.0) continue;
//
//                double avgPrice = 0.00;
//                BO summaryBO = new BO();
//                summaryBO.set("YEARMONTH", yearMonth);
//                summaryBO.set("WLMC", wlmc);
//                if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")){
//                    Double totalQuantity1 = currentMonthRow.getDouble("totalQuantity");
//                    double totalQuantity = totalQuantity1 != null ? totalQuantity1 : 0.0;
//                    Double totalAmount1 = currentMonthRow.getDouble("totalAmount");
//                    double totalAmount = totalAmount1 != null ? totalAmount1 : 0.0;
//                    summaryBO.set("CGZL", totalQuantity!=0?totalQuantity/1000:0);
//                    if (totalAmount!=0 || totalQuantity!=0) {
//                        avgPrice = totalAmount / (totalQuantity / 1000);
//                    }else {
//                        avgPrice = 0;
//                    }
//                }else {
//                    Double totalQuantity1 = currentMonthRow.getDouble("totalQuantity");
//                    double totalQuantity = totalQuantity1 != null ? totalQuantity1 : 0.0;
//                    Double totalAmount1 = currentMonthRow.getDouble("totalAmount");
//                    double totalAmount = totalAmount1 != null ? totalAmount1 : 0.0;
//                    summaryBO.set("CGZL", totalQuantity);
//                    if (totalAmount!=0 || totalQuantity!=0) {
//                        avgPrice = totalAmount / totalQuantity;
//                    }else {
//                        avgPrice = 0;
//                    }
//                }
//                summaryBO.set("CGZE", currentMonthRow.getDouble("totalAmount"));
//                summaryBO.set("PJDJ", avgPrice);
//
//                // 添加上月数据
//                RowMap lastMonthRow = lastMonthMap.get(wlmc);
//                if (lastMonthRow != null) {
//                    Double totalQuantity1 = currentMonthRow.getDouble("totalQuantity");
//                    double totalQuantity = totalQuantity1 != null ? totalQuantity1 : 0.0;
//                    Double totalAmount1 = currentMonthRow.getDouble("totalAmount");
//                    double totalAmount = totalAmount1 != null ? totalAmount1 : 0.0;
//                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")){
//                        summaryBO.set("SQCGZL", totalQuantity!=0?totalQuantity/1000:0);
//                    }else {
//                        summaryBO.set("SQCGZL", totalQuantity);
//                    }
//                    summaryBO.set("SQCGZE", totalAmount);
//                }
//
//                // 添加去年同期数据
//                RowMap lastYearMonthRow = lastYearMonthMap.get(wlmc);
//                if (lastYearMonthRow != null) {
//                    Double totalQuantity1 = currentMonthRow.getDouble("totalQuantity");
//                    double totalQuantity = totalQuantity1 != null ? totalQuantity1 : 0.0;
//                    Double totalAmount1 = currentMonthRow.getDouble("totalAmount");
//                    double totalAmount = totalAmount1 != null ? totalAmount1 : 0.0;
//                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")){
//                        summaryBO.set("TQCGZL", totalQuantity!=0?totalQuantity/1000:0);
//                    }else {
//                        summaryBO.set("TQCGZL", totalQuantity);
//                    }
//                    summaryBO.set("TQCGZE", totalAmount);
//                }
//
//                summaryBO.set("BKGS", bkgs);
//                bos.add(summaryBO);
//            }
            for (RowMap currentMonthRow : currentMonthData) {
                String wlmc = currentMonthRow.getString("WLMC");
                if (currentMonthRow == null || currentMonthRow.getDouble("totalAmount") == 0.0) continue;

                double avgPrice = 0.00;
                BO summaryBO = new BO();
                summaryBO.set("YEARMONTH", yearMonth);
                summaryBO.set("WLMC", wlmc);

                Double totalQuantity1 = currentMonthRow.getDouble("totalQuantity");
                double totalQuantity = totalQuantity1 != null ? totalQuantity1 : 0.0;
                Double totalAmount1 = currentMonthRow.getDouble("totalAmount");
                double totalAmount = totalAmount1 != null ? totalAmount1 : 0.0;

                if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")) {
                    double adjustedQuantity = totalQuantity != 0 ? totalQuantity / 1000 : 0;
                    summaryBO.set("CGZL", adjustedQuantity);
                    // 防止除零错误
                    if (adjustedQuantity != 0 && totalAmount != 0) {
                        avgPrice = totalAmount / adjustedQuantity;
                    }
                } else {
                    summaryBO.set("CGZL", totalQuantity);
                    // 防止除零错误
                    if (totalQuantity != 0 && totalAmount != 0) {
                        avgPrice = totalAmount / totalQuantity;
                    }
                }

                summaryBO.set("CGZE", totalAmount);
                summaryBO.set("PJDJ", avgPrice);

                // 添加上月数据（注意：这里应使用lastMonthRow的数据，而非currentMonthRow）
                RowMap lastMonthRow = lastMonthMap.get(wlmc);
                if (lastMonthRow != null) {
                    Double lastTotalQuantity1 = lastMonthRow.getDouble("totalQuantity");
                    double lastTotalQuantity = lastTotalQuantity1 != null ? lastTotalQuantity1 : 0.0;
                    Double lastTotalAmount1 = lastMonthRow.getDouble("totalAmount");
                    double lastTotalAmount = lastTotalAmount1 != null ? lastTotalAmount1 : 0.0;

                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")) {
                        summaryBO.set("SQCGZL", lastTotalQuantity != 0 ? lastTotalQuantity / 1000 : 0);
                    } else {
                        summaryBO.set("SQCGZL", lastTotalQuantity);
                    }
                    summaryBO.set("SQCGZE", lastTotalAmount);
                }

                // 添加去年同期数据（注意：这里应使用lastYearMonthRow的数据，而非currentMonthRow）
                RowMap lastYearMonthRow = lastYearMonthMap.get(wlmc);
                if (lastYearMonthRow != null) {
                    Double lastYearTotalQuantity1 = lastYearMonthRow.getDouble("totalQuantity");
                    double lastYearTotalQuantity = lastYearTotalQuantity1 != null ? lastYearTotalQuantity1 : 0.0;
                    Double lastYearTotalAmount1 = lastYearMonthRow.getDouble("totalAmount");
                    double lastYearTotalAmount = lastYearTotalAmount1 != null ? lastYearTotalAmount1 : 0.0;

                    if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")) {
                        summaryBO.set("TQCGZL", lastYearTotalQuantity != 0 ? lastYearTotalQuantity / 1000 : 0);
                    } else {
                        summaryBO.set("TQCGZL", lastYearTotalQuantity);
                    }
                    summaryBO.set("TQCGZE", lastYearTotalAmount);
                }

                summaryBO.set("BKGS", bkgs);
                bos.add(summaryBO);
            }


            if (!bos.isEmpty()) {
                // 批量插入数据
                int batchSize = 1000;
                for (int i = 0; i < bos.size(); i += batchSize) {
                    int end = Math.min(i + batchSize, bos.size());
                    List<BO> batch = bos.subList(i, end);
                    SDK.getBOAPI().createDataBO(PROCUREMENT_DETAILS_YEAR_MONTH, batch, UserContext.fromUID("admin"));
                }
            }

            LOGGER.info("成功保存{}条月度汇总数据，板块：{}", bos.size(), bkgs);

        } catch (Exception e) {
            String errorMsg = String.format("月度汇总计算失败(年月=%s,板块=%s): %s", yearMonth, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 计算并保存各板块物料采购总额、总量、单价(按日存储)
     * 逻辑：按物料名称(WLMC)分组，计算当日采购总额(SUM(JSHJ))、采购总量(SUM(YSSL))和平均单价(采购总额/采购总量)
     * @param year 年份
     * @param month 月份
     * @param day 日期
     * @param currentDate 当前日期对象
     * @param bkgs 板块公司
     */
    private void dailyMaterialSummaryBySegment(int year, int month, int day, Date currentDate,
                                               String bkgs, List<String> distinctList) {
        try {
            // 格式化日期字符串 (yyyy-MM-dd)
            String dateStr = String.format("%04d-%02d-%02d", year, month, day);
            LOGGER.info("开始计算{}物料采购日度汇总数据，板块公司：{}", dateStr, bkgs);

            // 1. 删除该日期已存在的汇总数据
            String deleteSql = "DELETE FROM " + PROCUREMENT_DETAILS_YEAR_MONTH_DAY +
                    " WHERE BKGS = ? AND RQ = ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, dateStr});
            LOGGER.info("采购_年月日采购明细：{}年{}月物料采购月度汇总数据，板块公司：{}，删除了{}条数据", year, month, bkgs, update);

            // 2. 查询当天数据
//            String querySql = "SELECT WLMC, SUM(JSHJ) AS totalAmount, SUM(YSSL) AS totalQuantity " +
//                    "FROM " + PROCUREMENT_PURCHASE_ORDER_SUMMARY +
//                    " WHERE BKGS = ? AND CGRQ = ? " +
//                    "GROUP BY WLMC";
            String field = "";
            if ("泰山石膏".equals(bkgs)) {
                field = " SUM(DHJE) ";
            }else {
                field = " SUM(JSHJHYF) ";
            }
            String querySql = "SELECT WLMC, "+field+" AS totalAmount, SUM(RKSL) AS totalQuantity " +
                    "FROM " + BO_EU_DWD_ORDER_RKD_HZ +
                    " WHERE BKGS = ? AND DJRQ = ? " +
                    "GROUP BY WLMC";
            List<RowMap> dailyData = DBSql.getMaps(querySql, bkgs, dateStr);

            // 3. 创建物料数据映射
            Map<String, RowMap> dailyMap = dailyData.stream()
                    .collect(Collectors.toMap(
                            row -> processMaterialName(row.getString("WLMC")),
                            row -> row,
                            (existing, replacement) -> {
                                double existingAmount = existing.getDouble("totalAmount");
                                double replacementAmount = replacement.getDouble("totalAmount");
                                existing.put("totalAmount", existingAmount + replacementAmount);

                                double existingQuantity = existing.getDouble("totalQuantity");
                                double replacementQuantity = replacement.getDouble("totalQuantity");
                                existing.put("totalQuantity", existingQuantity + replacementQuantity);

                                return existing;
                            }
                    ));

            // 4. 批量插入
            List<BO> bos = new ArrayList<>();
            for (String wlmc : distinctList) {
                RowMap row = dailyMap.get(wlmc);
                if (row == null) continue;

                // 安全获取数值并处理空值，默认值为0.0
                Double totalQuantity = row.getDouble("totalQuantity");
                Double totalAmount = row.getDouble("totalAmount");
                double safeTotalQuantity = totalQuantity != null ? totalQuantity : 0.0;
                double safeTotalAmount = totalAmount != null ? totalAmount : 0.0;

                // 如果总金额为0则跳过
                if (safeTotalAmount == 0.0) continue;

                double avgPrice = 0.0;
                BO summaryBO = new BO();
                summaryBO.set("RQ", dateStr);
                summaryBO.set("WLMC", wlmc);

                if (wlmc.equals("乳液") || wlmc.equals("钛白粉") || wlmc.equals("重钙")) {
                    double adjustedQuantity = safeTotalQuantity / 1000;
                    summaryBO.set("CGZL", adjustedQuantity);

                    if (safeTotalAmount != 0 && adjustedQuantity != 0) {
                        avgPrice = safeTotalAmount / adjustedQuantity;
                    }
                } else {
                    summaryBO.set("CGZL", safeTotalQuantity);
                    if (safeTotalAmount != 0 && safeTotalQuantity != 0) {
                        avgPrice = safeTotalAmount / safeTotalQuantity;
                    }
                }

                summaryBO.set("CGZE", safeTotalAmount);
                summaryBO.set("PJDJ", avgPrice);
                summaryBO.set("BKGS", bkgs);
                bos.add(summaryBO);
            }

            if (!bos.isEmpty()) {
                // 批量插入数据
                int batchSize = 1000;
                for (int i = 0; i < bos.size(); i += batchSize) {
                    int end = Math.min(i + batchSize, bos.size());
                    List<BO> batch = bos.subList(i, end);
                    SDK.getBOAPI().createDataBO(PROCUREMENT_DETAILS_YEAR_MONTH_DAY, batch, UserContext.fromUID("admin"));
                }
            }

            LOGGER.info("成功保存{}条日度汇总数据，板块：{}", bos.size(), bkgs);
        } catch (Exception e) {
            String errorMsg = String.format("日度汇总计算失败(日期=%s,板块=%s): %s", currentDate, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * // 根据日期、入库单号、物料名称分页查询 日期、入库单号、物料编码、物料名称、规格型号、
     *          （汇总）入库数量、单位、入库单价、（汇总）入库金额、供应商、订单编号、库存数
     * @param year 年
     * @param month 月
     * @param day 日
     * @param currentDate 开始时间
     * @param bkgs 板块公司
     * @param distinctList 物料名称数组
     */
    private void dailyWarehousingSummary(int year, int month, int day, Date currentDate,
                                         String bkgs, List<String> distinctList) {
        String dateStr = String.format("%04d-%02d-%02d", year, month, day);
        String yearMonth = String.format("%04d%02d", year, month); // 年月格式YYYYMM
        LOGGER.info("开始计算{}入库明细日度汇总数据，板块公司：{}", dateStr, bkgs);

        try {
            // 1. 删除该日期已存在的汇总数据（避免重复）
            String deleteSql = "DELETE FROM BO_EU_CG_NYRKMX WHERE BKGS = ? AND DATE = ?";
            int update = DBSql.update(deleteSql, new Object[]{bkgs, dateStr});
            LOGGER.info("已清理{}的旧入库明细数据", dateStr);
            LOGGER.info("采购_年月入库明细：{}年{}月物料采购月度汇总数据，板块公司：{}，删除了{}条数据", year, month, bkgs, update);

            // 2. 计算总记录数用于分页
            String countSql = "SELECT COUNT(1) AS total FROM " + BO_EU_DWD_ORDER_RKD_HZ + " " +
                    "WHERE BKGS = ? AND DATE(DJRQ) = ?";
            RowMap countResult = DBSql.getMap(countSql, bkgs, dateStr);
            int totalCount = countResult.getInt("total");
            LOGGER.info("共查询到{}条入库记录需要处理", totalCount);

            if (totalCount == 0) {
                LOGGER.info("无入库数据需要处理，跳过");
                return;
            }

            // 3. 分页处理数据
            int pageSize = 1000;
            int totalPages = (int) Math.ceil((double) totalCount / pageSize);
            LOGGER.info("开始分页处理入库数据，共{}页", totalPages);

            for (int page = 0; page < totalPages; page++) {
                int offset = page * pageSize;
                LOGGER.debug("正在处理第{}页入库数据，偏移量：{}", page + 1, offset);

                String querySql = "SELECT DJRQ, DJH, WLMC, WLBM, GGXH, SLGC, SUM(RKSL) AS RKSL, " +
                        " JLDW, HSDJHYF, SUM(JEHYF) AS JEHYF, GYSNAME, CGDDH, DHJE " +
                        " FROM "+BO_EU_DWD_ORDER_RKD_HZ+" WHERE BKGS = ? AND DATE(DJRQ) = ? " +
                        " GROUP BY DJRQ,DJH,WLMC "+
                        " ORDER BY DJH LIMIT ? OFFSET ?";

                List<RowMap> pageData = DBSql.getMaps(querySql, bkgs, dateStr, pageSize, offset);
                LOGGER.debug("第{}页查询到{}条记录", page + 1, pageData.size());

                // 转换并批量插入数据
                List<BO> bos = new ArrayList<>();
                for (RowMap row : pageData) {
                    BO detailBO = new BO();
                    detailBO.set("DATE", row.getDate("DJRQ")); // 入库日期
                    detailBO.set("RKDH", row.getString("DJH")); // 入库单号
                    detailBO.set("WLBM", row.getString("WLBM")); // 物料编码
                    String wlmc = row.getString("WLMC");
                    detailBO.set("WLMC", wlmc); // 物料名称
                    detailBO.set("GGXH", row.getString("GGXH")); // 规格型号
                    detailBO.set("GC", row.getString("SLGC")); // 收料工厂
                    detailBO.set("RKSL", row.getDouble("RKSL")); // 入库数量
                    detailBO.set("DW", row.getString("JLDW")); // 单位
                    if ("泰山石膏".equals(bkgs)) {
                        detailBO.set("RKDJ", row.getDouble("HSDJHYF")); // 入库单价（含税单价含运费）
                        detailBO.set("RKJE", row.getDouble("DHJE")); // 入库金额（金额含运费）
                    }else {
                        detailBO.set("RKDJ", row.getDouble("HSDJHYF")); // 入库单价（含税单价含运费）
                        detailBO.set("RKJE", row.getDouble("JSHJHYF")); // 入库金额（金额含运费）
                    }
                    detailBO.set("GYS", row.getString("GYSNAME")); // 供应商
                    detailBO.set("DDBH", row.getString("CGDDH")); // 订单编号
                    detailBO.set("KCS", 0.00); // 库存数（默认为0，需后续计算）
                    detailBO.set("BKGS", bkgs); // 板块公司
                    detailBO.set("YEARMONTH", yearMonth); // 年月
                    bos.add(detailBO);
                }
                // 批量插入当前页数据
                if (!bos.isEmpty()) {
                    SDK.getBOAPI().createDataBO(BO_EU_CG_NYRKMX, bos, UserContext.fromUID("admin"));
                    LOGGER.debug("入库明细日度汇总数据，板块公司：{}, 第{}页数据插入成功，共{}条,数量总共{}条",
                            bkgs, page + 1, bos.size(),totalCount);
                }
            }

            LOGGER.info("{}入库明细日度汇总完成，共处理{}条数据", dateStr, totalCount);
        } catch (Exception e) {
            String errorMsg = String.format("日度入库明细汇总失败(日期=%s,板块=%s): %s",
                    dateStr, bkgs, e.getMessage());
            LOGGER.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 处理物料名称（提取竖线前的部分）
     */
    private String processMaterialName(String wlmc) {
        if (StringUtils.isBlank(wlmc)) {
            return "";
        }
        if (wlmc.contains("|")) {
            String[] parts = wlmc.split("\\|");
            return parts[0].trim();
        }
        return wlmc.trim();
    }
}
