package com.ruoyi.excel.wecom.helper;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.excel.wecom.domain.*;
import com.ruoyi.excel.wecom.mapper.*;
import com.ruoyi.excel.wecom.model.WecomCustomer;
import com.ruoyi.excel.wecom.model.WecomTagGroup;
import com.ruoyi.excel.wecom.service.CustomerExportService;
import com.ruoyi.excel.wecom.service.WecomContactService;
import com.ruoyi.excel.wecom.service.WecomTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Component public class HandleAllData {
    @Autowired
    private WecomContactService wecomContactService;
    @Autowired
    private WecomTagService wecomTagService;
    @Autowired
    private CorpDepartmentMapper departmentMapper;

    @Autowired
    private CustomerExportService customerExportService;
    @Autowired
    private CorpUserMapper userMapper;
    @Autowired
    private CustomerExportDataMapper customerExportDataMapper;

    @Autowired
    private CustomerStatisticsDataMapper dataMapper;

    @Autowired
    private DepartmentStatisticsDataMapper departmentStatisticsDataMapper;

    /**
     * 线程池配置 - 用于并行处理客户数据
     */
    private final ExecutorService executorService = Executors.newFixedThreadPool(
            Runtime.getRuntime().availableProcessors() * 2,
            new ThreadFactory() {
                private final AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread thread = new Thread(r, "customer-data-handler-" + threadNumber.getAndIncrement());
                    thread.setDaemon(false);
                    return thread;
                }
            }
    );

    /**
     *  抓取客户列表数据（多线程版本）
     *  注意：由于使用多线程，移除了 @Transactional 注解，事务管理在 handleData 方法中处理
     */
    public void handleAllData() throws IOException {
        //暂时不考虑 员工和部门变动情况下的场景 获取所有批量详情接口数
        //1.获取所有配置了客户联系功能的员工列表
        List<String> followUserList = wecomContactService.getFollowUserList();


        int batchSize = 30;
        int totalSize = followUserList.size();

        // 创建任务列表
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        for (int i = 0; i < totalSize; i += batchSize) {
            // 计算当前批次的结束位置，防止越界
            int end = Math.min(i + batchSize, totalSize);

            // 获取当前批次的数据
            List<String> batch = followUserList.subList(i, end);

            // 提交异步任务
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    processBatch(batch);
                } catch (IOException e) {
                    throw new RuntimeException("处理批次数据失败: " + e.getMessage(), e);
                }
            }, executorService);

            futures.add(future);
        }

        // 等待所有任务完成
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        } catch (Exception e) {
            throw new IOException("多线程处理客户数据时发生错误: " + e.getMessage(), e);
        }
    }

    /**
     * 处理单个批次的员工客户数据
     * @param batch 员工ID列表
     */
    private void processBatch(List<String> batch) throws IOException {
        List<WecomCustomer> wecomCustomers = new ArrayList<>();
        String tmpCursor = null;

        do {
            tmpCursor = wecomContactService.batchGetCustomerDetails(batch, wecomCustomers, tmpCursor, 100);
            // 处理当前批次的客户数据
            customerExportService.handleData(wecomCustomers);
            wecomCustomers.clear();
        } while(tmpCursor != null);

        customerExportService.handleData(wecomCustomers);
    }

    /**
     * 关闭线程池（在应用关闭时调用）
     */
    public void shutdown() {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 创建所有日期的流量看板数据（包含当日统计）- 多线程版本
     */
    public void createAllReportData() {
        List<Date> allDate = customerExportService.getAllDate();

        // 创建任务列表
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        // 为每个日期创建异步任务
        for (Date date : allDate) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    createReportData(date);
                } catch (Exception e) {
                    throw new RuntimeException("处理日期 " + date + " 的报表数据失败: " + e.getMessage(), e);
                }
            }, executorService);

            futures.add(future);
        }

        // 等待所有任务完成
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        } catch (Exception e) {
            throw new RuntimeException("多线程处理流量看板数据时发生错误: " + e.getMessage(), e);
        }
    }

    /**
     * 创建所有部门指标数据 - 多线程版本
     */
    public void createAllDepartmentReportData() {
        List<Date> allDate = customerExportService.getAllDate();

        // 创建任务列表
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        // 为每个日期创建异步任务
        for (Date date : allDate) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    createDepartmentReportData(date);
                } catch (Exception e) {
                    throw new RuntimeException("处理日期 " + date + " 的部门报表数据失败: " + e.getMessage(), e);
                }
            }, executorService);

            futures.add(future);
        }

        // 等待所有任务完成
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        } catch (Exception e) {
            throw new RuntimeException("多线程处理部门报表数据时发生错误: " + e.getMessage(), e);
        }
    }

    /**
     * 创建流量看板数据（包含当日统计）
     * @param date 统计日期
     */
    public  void createReportData(Date date) {
        List<CustomerStatisticsData> oneDateData = calculateStatistics(date);
        oneDateData.forEach(item->{
            dataMapper.insert(item);
        });
    }

    /**初始化基础数据 如果需要同步 需要删除老数据数据*/
    public boolean initData() throws IOException {
        List<CorpDepartment> departmentList;
        Map<Long,String> cacheDepartMap = new HashMap<>();
        Map<Long,Long> parentCacheMap = new HashMap<>();
        try {
            //存入部门id
            departmentList = wecomContactService.getDepartmentList(null);
            //循环获取部门详情数据
            for (CorpDepartment item : departmentList) {
                String departmentDetail = null;
                departmentDetail = wecomContactService.getDepartmentDetail(item.getId());

                item.setName(departmentDetail);
                cacheDepartMap.put(item.getId(),departmentDetail);
                parentCacheMap.put(item.getId(), item.getParentid());
                //保存部门数据
                departmentMapper.insert(item);
            }
        } catch (Exception e) {
            throw new RuntimeException("存储部门数据失败！");
        }

        try {
            //根据部门id循环获取下面的员工信息
            departmentList.forEach(item -> {
                try {
                    List<CorpUser> departmentMemberList = wecomContactService.getDepartmentMemberList(item.getId(), null, null);
                    departmentMemberList.forEach(oneUser -> {
                        oneUser.setDepartId(item.getId());
                        oneUser.setDepartmentName(getDepartmentFullPath(item.getId(),cacheDepartMap,parentCacheMap));
                        userMapper.insert(oneUser);
                    });
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        } catch (Exception e) {
            throw new RuntimeException("存储员工数据失败！");
        }

        try {
            //查询所有标签信息 存储标签信息
            List<WecomTagGroup> tagGroupList = wecomContactService.getCorpTagList();

            // 同步标签库到数据库
            wecomTagService.syncCorpTagList(tagGroupList);
        } catch (Exception e) {
            throw new RuntimeException("存储标签数据失败！");
        }

        customerExportService.refreshCache();
        return true;
    }


    /**
     * 创建部门报表数据（包含当日统计）
     * @param date 统计日期
     */
    public void createDepartmentReportData(Date date) {
        List<DepartmentStatisticsData> oneDateData = calculateDepartmentStatistics(date);
        oneDateData.forEach(item -> {
            departmentStatisticsDataMapper.insert(item);
        });
    }

    /**
     * 计算部门历史累计指标
     * @param departmentPath 部门路径
     * @return 历史累计指标（作为一条记录返回）
     */
    public List<DepartmentStatisticsData> calculateDepartmentHistoricalStatistics(String departmentPath) {
        List<DepartmentStatisticsData> results = new ArrayList<>();

        // 1. 查询历史总承接数
        Map<String, Object> acceptSumMap = departmentStatisticsDataMapper.selectHistoricalAcceptSum(departmentPath);
        int historicalAcceptCount = 0;
        if (acceptSumMap != null && acceptSumMap.get("total_value") != null) {
            historicalAcceptCount = ((BigDecimal) acceptSumMap.get("total_value")).intValue();
        }

        // 2. 查询历史总成单数
        Map<String, Object> orderSumMap = departmentStatisticsDataMapper.selectHistoricalOrderSum(departmentPath);
        int historicalOrderCount = 0;
        if (orderSumMap != null && orderSumMap.get("total_value") != null) {
            historicalOrderCount = ((BigDecimal) orderSumMap.get("total_value")).intValue();
        }

        // 3. 计算渗透率
        BigDecimal penetrationRate = calculateRateBigDecimal(historicalOrderCount, historicalAcceptCount);

        // 生成一条历史累计记录
        Date now = new Date();
        DepartmentStatisticsData vo = new DepartmentStatisticsData();
        vo.setStatDate(now);
        vo.setDepartmentPath(departmentPath);
        vo.setSortNo(0);

        results.add(vo);

        return results;
    }


    /**===================================以下为私有方法============================================*/
    /**
     * 递归获取部门完整路径
     * @param departId 部门id
     * @param cacheDepartMap 部门id对应部门名称的缓存
     * @param parentCacheMap 部门id对应上级部门id的缓存
     * @return 完整部门路径，用"/"分隔，例如：公司/技术部/研发组
     */
    private String getDepartmentFullPath(Long departId, Map<Long, String> cacheDepartMap, Map<Long, Long> parentCacheMap) {
        // 如果部门id为空或不存在，返回空字符串
        if (departId == null || !cacheDepartMap.containsKey(departId)) {
            return "";
        }

        // 获取当前部门名称
        String currentDepartName = cacheDepartMap.get(departId);

        // 获取父部门id
        Long parentId = parentCacheMap.get(departId);

        // 如果没有父部门或父部门id为0（根部门），返回当前部门名称
        if (parentId == null || parentId == 0) {
            return currentDepartName;
        }

        // 递归获取父部门路径
        String parentPath = getDepartmentFullPath(parentId, cacheDepartMap, parentCacheMap);

        // 拼接父部门路径和当前部门名称
        if (parentPath.isEmpty()) {
            return currentDepartName;
        } else {
            return parentPath + "/" + currentDepartName;
        }
    }



    /**
     * 统计客户数据（支持日期参数）
     * @param targetDate 目标日期，格式：yyyy-MM-dd，如 "2026-01-03" 表示1月3日
     * @return 统计结果列表
     */
    /**
     * 计算统计数据 - 使用分页查询+单次遍历方案
     * @param date 目标日期 (格式: yyyy-MM-dd)
     * @return 统计结果列表
     */
    private List<CustomerStatisticsData> calculateStatistics(Date date) {
        // 1. 初始化累加器
        StatisticsAccumulator accumulator = new StatisticsAccumulator();

        // 2. 分页查询并累加统计
        int pageSize = 1000;  // 每页1000条
        int pageNum = 1;

        while (true) {
            // 分页查询（不在SQL层过滤，在Java层过滤以保证准确性）
            Page<CustomerExportData> page = new Page<>(pageNum, pageSize);
            Page<CustomerExportData> pageData = customerExportDataMapper.selectPage(page, null);

            // 处理当前页数据
            for (CustomerExportData data : pageData.getRecords()) {
                // 处理该条数据，累加到所有相关组的统计中
                processDataRecord(data, date, accumulator);
            }

            // 检查是否还有下一页
            if (!pageData.hasNext()) {
                break;
            }
            pageNum++;
        }

        // 3. 从累加器生成最终结果
        return generateStatisticsResults(date,accumulator);
    }


    /**
     * 计算部门维度的统计数据（当日）
     * @param targetDate 目标日期 (格式: yyyy-MM-dd)
     * @return 部门统计结果列表
     */
    private List<DepartmentStatisticsData> calculateDepartmentStatistics(Date targetDate) {
        // 1. 初始化部门累加器
        DepartmentStatisticsAccumulator accumulator = new DepartmentStatisticsAccumulator();

        // 2. 分页查询并累加统计
        int pageSize = 1000;
        int pageNum = 1;

        while (true) {
            // 分页查询
            Page<CustomerExportData> page = new Page<>(pageNum, pageSize);
            Page<CustomerExportData> pageData = customerExportDataMapper.selectPage(page, null);

            // 处理当前页数据
            for (CustomerExportData data : pageData.getRecords()) {
                // 获取部门路径
                String departmentPath = data.getAddUserDepartment();
                if (departmentPath == null || departmentPath.trim().isEmpty()) {
                    continue;
                }

                // 提取组级别路径和员工级别路径
                // 例如：苏州曼普/销售部/二组/盛宇婷
                // 组级别：苏州曼普/销售部/二组
                // 员工级别：苏州曼普/销售部/二组/盛宇婷
                String[] pathParts = departmentPath.split("/");

                // 处理组级别统计（前3级）
                if (pathParts.length >= 3) {
                    String groupPath = pathParts[0] + "/" + pathParts[1] + "/" + pathParts[2];
                    processDepartmentRecord(data, targetDate, accumulator.getDepartmentStats(groupPath));
                }

                // 处理员工级别统计（完整路径）
                if (pathParts.length >= 4) {
                    processDepartmentRecord(data, targetDate, accumulator.getDepartmentStats(departmentPath));
                }
            }

            // 检查是否还有下一页
            if (!pageData.hasNext()) {
                break;
            }
            pageNum++;
        }

        // 3. 从累加器生成最终结果
        return generateDepartmentStatisticsResults(accumulator, targetDate);
    }

    /**
     * 组名到字段名的映射
     */
    private static final Map<String, String> GROUP_FIELD_MAP = new LinkedHashMap<>();
    static {
        GROUP_FIELD_MAP.put("N组", "tagGroup1");
        GROUP_FIELD_MAP.put("O组", "tagGroup2");
        GROUP_FIELD_MAP.put("P组", "tagGroup3");
        GROUP_FIELD_MAP.put("W组", "tagGroup10");
        GROUP_FIELD_MAP.put("X组", "tagGroup11");
        GROUP_FIELD_MAP.put("Y组", "tagGroup12");
        GROUP_FIELD_MAP.put("Z组", "tagGroup13");
        GROUP_FIELD_MAP.put("AA组", "tagGroup14");
        GROUP_FIELD_MAP.put("AC组", "tagGroup16");
        GROUP_FIELD_MAP.put("AD组", "tagGroup17");
        GROUP_FIELD_MAP.put("AE组", "tagGroup18");
    }

    /**
     * 字段反射缓存
     */
    private static final Map<String, java.lang.reflect.Field> FIELD_CACHE = new java.util.concurrent.ConcurrentHashMap<>();

    /**
     * 检查数据是否匹配日期和来源条件
     */
    private boolean matchesDate(CustomerExportData data, Date date) {
        // 条件1: 日期匹配
        if (data.getAddDate() != null && date != null) {
            if (date.compareTo(data.getAddDate()) != 0) {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    private boolean matchesSource(CustomerExportData data) {
        // 条件: 排除"由管理员XXX分配"
        if (data.getSource() != null &&
                data.getSource().contains("管理员") &&
                data.getSource().contains("分配")) {
            return false;
        }

        return true;
    }

    private boolean matchesQValue(CustomerExportData data,Date curDate) {
        String orderDate = data.getTagGroup4();  // Q列：成交日期，格式：2.3

        // 基础校验
        if (orderDate == null || orderDate.trim().isEmpty()) {
            return false;
        }

        try {
            //由于可能是多个逗号拼成的多个日期 任意一个日期符合都可以
            String[] dates = orderDate.trim().split(",");
            // 解析订单日期：2.3 -> [2, 3]
            String[] parts = dates[dates.length - 1].trim().split("[.\\-/]");
            if (parts.length < 2) {
                return false;
            }

            int orderMonth = Integer.parseInt(parts[0].trim());
            int orderDay = Integer.parseInt(parts[1].trim());

            // 构建成交日期（基于addTime的年份）
            Calendar orderCal = Calendar.getInstance();
            orderCal.setTime(curDate);
            orderCal.set(Calendar.MONTH, orderMonth - 1);
            orderCal.set(Calendar.DAY_OF_MONTH, orderDay);
            orderCal.set(Calendar.HOUR_OF_DAY, 0);
            orderCal.set(Calendar.MINUTE, 0);
            orderCal.set(Calendar.SECOND, 0);
            orderCal.set(Calendar.MILLISECOND, 0);

            // 跨年处理：如果成交日期早于添加日期，年份+1
            if (orderCal.getTime().before(curDate)) {
                orderCal.add(Calendar.YEAR, 1);
            }

            // 标准化目标日期（清除时分秒）
            Calendar targetCal = Calendar.getInstance();
            targetCal.setTime(curDate);
            targetCal.set(Calendar.HOUR_OF_DAY, 0);
            targetCal.set(Calendar.MINUTE, 0);
            targetCal.set(Calendar.SECOND, 0);
            targetCal.set(Calendar.MILLISECOND, 0);

            boolean b = orderCal.getTimeInMillis() == targetCal.getTimeInMillis();
            if (b) {
                return true;
            }

        } catch (Exception e) {
            return false;
        }
        return false;
    }

    private boolean matchOrderCompleted(CustomerExportData data,Date curDate) {
        String orderStatus = data.getTagGroup7(); // T列：成交状态
        // 校验成交状态
        if (!orderStatus.contains("已成交及时单9元+") && !orderStatus.contains("已成交非及时单9元+")) {
            return false;
        }
        return true;
    }
    /**
     * 处理单条数据记录，累加到所有相关组的统计中
     */
    private void processDataRecord(CustomerExportData data, Date date, StatisticsAccumulator accumulator) {
        // 遍历所有组
        for (Map.Entry<String, String> entry : GROUP_FIELD_MAP.entrySet()) {
            String groupName = entry.getKey();
            String fieldName = entry.getValue();

            // 获取该组的标签值
            String tagValue = getFieldValue(data, fieldName);

            // 如果该组标签为空，跳过
            if (tagValue == null || tagValue.trim().isEmpty()) {
                continue;
            }

            // 获取该组的统计器
            StatisticsAccumulator.GroupStatistics stats = accumulator.getGroupStats(groupName);

            // 累加各项统计指标
            accumulateGroupStatistics(data, date, stats);
        }
    }

    /**
     * 使用反射获取字段值（带缓存）
     */
    private String getFieldValue(CustomerExportData data, String fieldName) {
        try {
            java.lang.reflect.Field field = FIELD_CACHE.computeIfAbsent(fieldName, fn -> {
                try {
                    java.lang.reflect.Field f = CustomerExportData.class.getDeclaredField(fn);
                    f.setAccessible(true);
                    return f;
                } catch (NoSuchFieldException e) {
                    throw new RuntimeException(e);
                }
            });

            Object value = field.get(data);
            return value == null ? "" : value.toString();
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 累加单条数据的统计指标
     */
    private void accumulateGroupStatistics(CustomerExportData data, Date date, StatisticsAccumulator.GroupStatistics stats) {
        if(matchesQValue(data,date)) {
            stats.setOrderCount(stats.getOrderCount() + 1);
            String orderStatus = data.getTagGroup7();
            if (orderStatus != null) {
                if (orderStatus.contains("已成交及时单9元+")) {
                    stats.setTimelyOrderCount(stats.getTimelyOrderCount() + 1);
                } else if (orderStatus.contains("已成交非及时单9元+")) {
                    stats.setNonTimelyOrderCount(stats.getNonTimelyOrderCount() + 1);
                }
            }
        }

        // 1. 成单数和及时单/非及时单
        //来源筛选
        if(!matchesSource(data) || !matchesDate(data,date)) {
            return;
        }
        // 2. 进粉数
        stats.setCustomerCount(stats.getCustomerCount() + 1);

        // 3. 客户属性统计
        String customerAttr = data.getTagGroup6();
        if (customerAttr != null && !customerAttr.trim().isEmpty()) {
            stats.setTotalCustomerAttr(stats.getTotalCustomerAttr() + 1);

            if (customerAttr.contains("家长")) {
                stats.setParentCount(stats.getParentCount() + 1);
                //todo 存在订单未完成 但是有标签的场景
                stats.setParentOrderCount(stats.getParentOrderCount() + 1);

            } else if (customerAttr.contains("学生")) {
                stats.setStudentCount(stats.getStudentCount() + 1);

                stats.setStudentOrderCount(stats.getStudentOrderCount() + 1);

            } else {
                stats.setUnknownAttrCount(stats.getUnknownAttrCount() + 1);
            }
        }

        // 4. 意向度统计
        String intention = data.getTagGroup15();
        if (intention != null && !intention.trim().isEmpty() && !"空白".equals(intention)) {
            stats.setTotalIntention(stats.getTotalIntention() + 1);

            if (intention.contains("主动报价")) {
                stats.setActiveQuoteCount(stats.getActiveQuoteCount() + 1);
            } else if (intention.contains("被动报价")) {
                stats.setPassiveQuoteCount(stats.getPassiveQuoteCount() + 1);
            } else if (intention.contains("未开口")) {
                stats.setNoQuoteCount(stats.getNoQuoteCount() + 1);
            } else if (intention.contains("已删除")) {
                stats.setDeletedQuoteCount(stats.getDeletedQuoteCount() + 1);
            }
        }

        // 5. 年级统计
        String grade = data.getTagGroup5();
        if (grade != null && !grade.trim().isEmpty() && !"空白".equals(grade)) {
            stats.setTotalGrade(stats.getTotalGrade() + 1);

            if (isPrimarySchool(grade)) {
                stats.setPrimaryCount(stats.getPrimaryCount() + 1);
            } else if (isMiddleSchool(grade)) {
                stats.setMiddleCount(stats.getMiddleCount() + 1);
            } else if (isHighSchool(grade)) {
                stats.setHighCount(stats.getHighCount() + 1);
            }
        }
    }


    /**
     * 判断是否为小学
     */
    private boolean isPrimarySchool(String grade) {
        return grade.contains("小学") || grade.contains("一年级") || grade.contains("二年级") ||
               grade.contains("三年级") || grade.contains("四年级") || grade.contains("五年级") ||
               grade.contains("六年级");
    }

    /**
     * 判断是否为初中
     */
    private boolean isMiddleSchool(String grade) {
        return grade.contains("初中") || grade.contains("初一") ||
               grade.contains("初二") || grade.contains("初三");
    }

    /**
     * 判断是否为高中
     */
    private boolean isHighSchool(String grade) {
        return grade.contains("高中") || grade.contains("高一") ||
               grade.contains("高二") || grade.contains("高三");
    }

    /**
     * 从累加器生成最终统计结果
     */
    private List<CustomerStatisticsData> generateStatisticsResults(Date curDate,StatisticsAccumulator accumulator) {
        // 使用 Map 来存储每个指标对应的 CustomerStatisticsData
        // key: 指标名称（不带组名前缀），value: CustomerStatisticsData 对象
        Map<String, CustomerStatisticsData> indicatorMap = new LinkedHashMap<>();
        //设置一个默认排序
        int sortNo = 0;
        // 为每个组生成23个统计指标
        for (Map.Entry<String, StatisticsAccumulator.GroupStatistics> entry : accumulator.getGroupStatsMap().entrySet()) {
            String groupName = entry.getKey();
            StatisticsAccumulator.GroupStatistics stats = entry.getValue();

            // 21-23. 成本相关（需要手工填写）
            setIndicatorValue(indicatorMap,curDate, "总成本（当日）", groupName, "需手工填写",(10*sortNo++));
            setIndicatorValue(indicatorMap,curDate, "单条成本（当日）", groupName, "需手工填写",(10*sortNo++));
            setIndicatorValue(indicatorMap,curDate, "成单成本（当日）", groupName, "需手工填写",(10*sortNo++));

            // 1. 成单数
            setIndicatorValue(indicatorMap,curDate, "成单数（当日）", groupName, String.valueOf(stats.getOrderCount()),(10*sortNo++));

            // 2. 进粉数
            setIndicatorValue(indicatorMap,curDate, "进粉数（当日）", groupName, String.valueOf(stats.getCustomerCount()),(10*sortNo++));

            // 3. 转化率
            String conversionRate = calculateRate(stats.getOrderCount(), stats.getCustomerCount());
            setIndicatorValue(indicatorMap,curDate, "转化率(当日)", groupName, conversionRate,(10*sortNo++));

            // 4. 及时单占比
            String timelyRate = calculateRate(stats.getTimelyOrderCount(), stats.getCustomerCount());
            setIndicatorValue(indicatorMap,curDate, "及时单占比(当日)", groupName, timelyRate,(10*sortNo++));

            // 5. 非及时单占比
            String nonTimelyRate = calculateRate(stats.getNonTimelyOrderCount(), stats.getCustomerCount());
            setIndicatorValue(indicatorMap,curDate, "非及时单占比(当日)", groupName, nonTimelyRate,(10*sortNo++));

            // 6. 客户属性数量
            setIndicatorValue(indicatorMap,curDate, "客户属性数量（当日）", groupName, String.valueOf(stats.getTotalCustomerAttr()),(10*sortNo++));

            // 7. 家长占比
            String parentRate = calculateRate(stats.getParentCount(), stats.getTotalCustomerAttr());
            setIndicatorValue(indicatorMap,curDate, "家长占比（当日）", groupName, parentRate,(10*sortNo++));

            // 8. 学生占比
            String studentRate = calculateRate(stats.getStudentCount(), stats.getTotalCustomerAttr());
            setIndicatorValue(indicatorMap,curDate, "学生占比（当日）", groupName, studentRate,(10*sortNo++));

            // 9. 未知占比
            String unknownRate = calculateRate(stats.getUnknownAttrCount(), stats.getTotalCustomerAttr());
            setIndicatorValue(indicatorMap,curDate, "未知占比（当日）", groupName, unknownRate,(10*sortNo++));

            // 10. 意向度数量
            setIndicatorValue(indicatorMap,curDate, "意向度数量（当日）", groupName, String.valueOf(stats.getTotalIntention()),(10*sortNo++));

            // 11. 主动报价占比
            String activeQuoteRate = calculateRate(stats.getActiveQuoteCount(), stats.getTotalIntention());
            setIndicatorValue(indicatorMap,curDate, "主动报价占比（当日）", groupName, activeQuoteRate,(10*sortNo++));

            // 12. 被动报价占比
            String passiveQuoteRate = calculateRate(stats.getPassiveQuoteCount(), stats.getTotalIntention());
            setIndicatorValue(indicatorMap,curDate, "被动报价占比（当日）", groupName, passiveQuoteRate,(10*sortNo++));

            // 13. 未开口报价占比
            String noQuoteRate = calculateRate(stats.getNoQuoteCount(), stats.getTotalIntention());
            setIndicatorValue(indicatorMap,curDate, "未开口报价占比（当日）", groupName, noQuoteRate,(10*sortNo++));

            // 14. 已删除报价占比
            String deletedQuoteRate = calculateRate(stats.getDeletedQuoteCount(), stats.getTotalIntention());
            setIndicatorValue(indicatorMap,curDate, "已删除报价占比（当日）", groupName, deletedQuoteRate,(10*sortNo++));

            // 15. 年级数量
            setIndicatorValue(indicatorMap,curDate, "年级数量（当日）", groupName, String.valueOf(stats.getTotalGrade()),(10*sortNo++));

            // 16. 小学占比
            String primaryRate = calculateRate(stats.getPrimaryCount(), stats.getTotalGrade());
            setIndicatorValue(indicatorMap,curDate, "小学占比（当日）", groupName, primaryRate,(10*sortNo++));

            // 17. 初中占比
            String middleRate = calculateRate(stats.getMiddleCount(), stats.getTotalGrade());
            setIndicatorValue(indicatorMap,curDate, "初中占比（当日）", groupName, middleRate,(10*sortNo++));

            // 18. 高中占比
            String highRate = calculateRate(stats.getHighCount(), stats.getTotalGrade());
            setIndicatorValue(indicatorMap,curDate, "高中占比（当日）", groupName, highRate,(10*sortNo++));

            // 19. 家长出单占比
            String parentOrderRate = calculateRate(stats.getParentOrderCount(), stats.getParentCount());
            setIndicatorValue(indicatorMap,curDate, "家长出单占比（当日）", groupName, parentOrderRate,(10*sortNo++));

            // 20. 学生出单占比
            String studentOrderRate = calculateRate(stats.getStudentOrderCount(), stats.getStudentCount());
            setIndicatorValue(indicatorMap,curDate, "学生出单占比（当日）", groupName, studentOrderRate,(10*sortNo++));


        }

        // 将 Map 转换为 List 返回
        return new ArrayList<>(indicatorMap.values());
    }

    /**
     * 设置指标值到对应的 CustomerStatisticsData 对象
     * @param indicatorMap 指标映射表
     * @param indicatorName 指标名称（不带组名前缀）
     * @param groupName 组名
     * @param value 指标值
     */
    private void setIndicatorValue(Map<String, CustomerStatisticsData> indicatorMap,Date curDate,
                                   String indicatorName, String groupName, String value,int sortNo) {
        // 获取或创建该指标对应的 CustomerStatisticsData 对象
        CustomerStatisticsData vo = indicatorMap.computeIfAbsent(indicatorName, k -> {
            CustomerStatisticsData newVo = new CustomerStatisticsData();
            newVo.setIndicatorName(indicatorName);
            newVo.setCurDate(curDate);
            newVo.setSortNo(sortNo);
            return newVo;
        });

        // 根据组名设置对应的字段值
        setGroupValue(vo, groupName, value);
    }

    /**
     * 根据组名设置对应字段的值
     * @param vo CustomerStatisticsData 对象
     * @param groupName 组名
     * @param value 要设置的值
     */
    private void setGroupValue(CustomerStatisticsData vo, String groupName, String value) {
        switch (groupName) {
            case "N组":
                vo.setNtfGroup(value);
                break;
            case "O组":
                vo.setOfhGroup(value);
                break;
            case "P组":
                vo.setPswGroup(value);
                break;
            case "W组":
                vo.setWa1Group(value);
                break;
            case "X组":
                vo.setXb1Group(value);
                break;
            case "Y组":
                vo.setYc1Group(value);
                break;
            case "Z组":
                vo.setZd1Group(value);
                break;
            case "AA组":
                vo.setAaGroup(value);
                break;
            case "AC组":
                vo.setAcGroup(value);
                break;
            case "AD组":
                vo.setAdGroup(value);
                break;
            case "AE组":
                vo.setAeGroup(value);
                break;
        }
    }

    /**
     * 计算百分比
     */
    private String calculateRate(int count, int total) {
        if (total == 0) {
            return "0%";
        }
        BigDecimal rate = new BigDecimal(count)
                .multiply(new BigDecimal(100))
                .divide(new BigDecimal(total), 2, RoundingMode.HALF_UP);
        return rate.toString() + "%";
    }


    /**
     * 处理单条数据记录，累加到部门统计中
     */
    private void processDepartmentRecord(CustomerExportData data, Date targetDate,
                                        DepartmentStatisticsAccumulator.DepartmentStats stats) {
        if(matchesQValue(data,targetDate)) {
            stats.setTotalOrderCount(stats.getTotalOrderCount() + 1);

            // 及时单和非及时单统计
            String orderStatus = data.getTagGroup7();
            if (orderStatus != null) {
                String[] split = orderStatus.split(",");
                if (split[split.length-1].contains("已成交及时单9元+")) {
                    stats.setTimelyOrderCount(stats.getTimelyOrderCount() + 1);
                } else if (split[split.length-1].contains("已成交非及时单9元+")) {
                    stats.setNonTimelyOrderCount(stats.getNonTimelyOrderCount() + 1);
                }
            }
        }

        if (matchesDate(data,targetDate)) {
            if(matchesSource(data)) {
                // 2. 总承接数（当日）- 排除"由管理员XXX分配"
                stats.setTotalAcceptCount(stats.getTotalAcceptCount() + 1);
            } else {
                // 由管理员XXX分配"
                stats.setManagerAcceptCount(stats.getManagerAcceptCount() + 1);
            }
        }
    }

    /**
     * 从累加器生成最终部门统计结果
     * 每一行数据代表一个部门或员工，包含所有指标维度
     */
    private List<DepartmentStatisticsData> generateDepartmentStatisticsResults(
            DepartmentStatisticsAccumulator accumulator, Date statDate) {
        List<DepartmentStatisticsData> results = new ArrayList<>();

        int sortNo = 0;
        // 为每个部门生成一条记录，包含所有指标
        for (Map.Entry<String, DepartmentStatisticsAccumulator.DepartmentStats> entry :
                accumulator.getDepartmentStatsMap().entrySet()) {
            String departmentPath = entry.getKey();
            DepartmentStatisticsAccumulator.DepartmentStats stats = entry.getValue();

            // 创建一个DepartmentStatisticsData对象，包含所有指标
            DepartmentStatisticsData vo = new DepartmentStatisticsData();
            vo.setStatDate(statDate);
            vo.setDepartmentPath(departmentPath);

            // 设置各项指标
            // 1. 总承接数（当日）
            vo.setDailyTotalAccepted(stats.getTotalAcceptCount());
            //设置管理员分配人数
            vo.setManagerAccepted(stats.getManagerAcceptCount());

            // 2. 总成单数（当日）
            vo.setDailyTotalOrders(stats.getTotalOrderCount());

            // 3. 转化率（当日）
            BigDecimal conversionRate = calculateRateBigDecimal(stats.getTotalOrderCount(), stats.getTotalAcceptCount());
            vo.setDailyConversionRate(conversionRate);

            // 4. 及时单占比（当日）
            BigDecimal timelyRate = calculateRateBigDecimal(stats.getTimelyOrderCount(), stats.getTotalOrderCount());
            vo.setDailyTimelyOrderRatio(timelyRate);

            // 5. 非及时单占比（当日）
            BigDecimal nonTimelyRate = calculateRateBigDecimal(stats.getNonTimelyOrderCount(), stats.getTotalOrderCount());
            vo.setDailyNonTimelyOrderRatio(nonTimelyRate);

            results.add(vo);
        }

        return results;
    }

    /**
     * 计算百分比（返回BigDecimal类型）
     */
    private BigDecimal calculateRateBigDecimal(int count, int total) {
        if (total == 0) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(count)
                .multiply(new BigDecimal(100))
                .divide(new BigDecimal(total), 2, RoundingMode.HALF_UP);
    }

}
