package com.sundot.airport.blocked.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.sundot.airport.blocked.dto.BlockedAreaBlockedDTO;
import com.sundot.airport.blocked.dto.BlockedAreaDistributionResultDTO;
import com.sundot.airport.blocked.dto.BlockedAreaLuggageDTO;
import com.sundot.airport.blocked.dto.BlockedBrigadeRateStatsDTO;
import com.sundot.airport.blocked.dto.BlockedBrigadeStatsDTO;
import com.sundot.airport.blocked.dto.BlockedCertificateDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedCertificateLevelDTO;
import com.sundot.airport.blocked.dto.BlockedCertificateLevelDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedDailyBrigadeLuggageStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyBrigadeRateStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyBrigadeStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyBrigadeTerminalLuggageStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyBrigadeTerminalRateStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyBrigadeTerminalStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyLuggageStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyRateStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDailyStatsDTO;
import com.sundot.airport.blocked.dto.BlockedDashboardQueryDTO;
import com.sundot.airport.blocked.dto.BlockedDashboardResultDTO;
import com.sundot.airport.blocked.dto.BlockedDifficultyDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedDiscriminationDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedGenderDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedItemDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedItemLocationDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedMissCheckReasonDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedOperatingYearsDistributionDTO;
import com.sundot.airport.blocked.dto.BlockedRankingDTO;
import com.sundot.airport.blocked.dto.BlockedRateResultDTO;
import com.sundot.airport.blocked.dto.BlockedTerminalStatsDTO;
import com.sundot.airport.blocked.dto.BlockedTimePeriodLuggageStatsDTO;
import com.sundot.airport.blocked.dto.BlockedTimePeriodStatsDTO;
import com.sundot.airport.blocked.mapper.BlockedDashboardMapper;
import com.sundot.airport.blocked.service.IBlockedDashboardService;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.system.mapper.SysDeptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 查堵大屏Service业务层处理
 * 
 * @author wangxx
 * @date 2026-04-15
 */
@Service
public class BlockedDashboardServiceImpl implements IBlockedDashboardService {

    @Autowired
    private BlockedDashboardMapper blockedDashboardMapper;
    
    @Autowired
    private SysDeptMapper sysDeptMapper;

    /**
     * 查询查堵总数
     * 
     * @param queryDTO 查询参数
     * @return 查堵统计结果
     */
    @Override
    public BlockedDashboardResultDTO getBlockedTotalCount(BlockedDashboardQueryDTO queryDTO) {
        BlockedDashboardResultDTO result = new BlockedDashboardResultDTO();
        
        // 判断是否选择了大队
        if (queryDTO.getBrigadeId() == null) {
            // 从各大队每日过检行李查堵数据收集表统计
            Integer totalCount = blockedDashboardMapper.selectTotalBlockedCountWithoutBrigade(queryDTO);
            result.setTotalBlockedCount(totalCount != null ? totalCount : 0);
        } else {
            // 从漏检统计表统计
            Integer totalCount = blockedDashboardMapper.selectTotalBlockedCountWithBrigade(queryDTO);
            result.setTotalBlockedCount(totalCount != null ? totalCount : 0);
        }
        
        return result;
    }

    /**
     * 查询各大队查堵总数
     * 
     * @param queryDTO 查询参数
     * @return 各大队查堵统计列表
     */
    @Override
    public List<BlockedBrigadeStatsDTO> getBlockedCountByBrigade(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedBrigadeStatsDTO> resultList = blockedDashboardMapper.selectBlockedCountByBrigade(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询总查堵万分率(所有大队平均值)
     * 
     * @param queryDTO 查询参数
     * @return 查堵万分率统计结果
     */
    @Override
    public BlockedRateResultDTO getTotalBlockedRate(BlockedDashboardQueryDTO queryDTO) {
        BlockedRateResultDTO result = new BlockedRateResultDTO();
        BigDecimal totalRate = blockedDashboardMapper.selectTotalBlockedRate(queryDTO);
        // 保留两位小数
        if (totalRate != null) {
            totalRate = totalRate.setScale(2, java.math.RoundingMode.HALF_UP);
        } else {
            totalRate = BigDecimal.ZERO;
        }
        result.setTotalBlockedRate(totalRate);
        return result;
    }

    /**
     * 查询各大队平均查堵万分率(用于条形图)
     * 
     * @param queryDTO 查询参数
     * @return 各大队查堵万分率统计列表
     */
    @Override
    public List<BlockedBrigadeRateStatsDTO> getBlockedRateByBrigade(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedBrigadeRateStatsDTO> resultList = blockedDashboardMapper.selectBlockedRateByBrigade(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 保留两位小数
            for (BlockedBrigadeRateStatsDTO dto : resultList) {
                if (dto.getAvgBlockedRate() != null) {
                    dto.setAvgBlockedRate(dto.getAvgBlockedRate().setScale(2, java.math.RoundingMode.HALF_UP));
                } else {
                    dto.setAvgBlockedRate(BigDecimal.ZERO);
                }
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询每日查堵合计件数(用于趋势图)
     * 
     * @param queryDTO 查询参数
     * @return 每日查堵统计列表
     */
    @Override
    public List<BlockedDailyStatsDTO> getBlockedCountByDate(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyStatsDTO> resultList = blockedDashboardMapper.selectBlockedCountByDate(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询每日各大队查堵合计件数(用于大队对比表)
     * 
     * @param queryDTO 查询参数
     * @return 每日各大队查堵统计列表
     */
    @Override
    public List<BlockedDailyBrigadeStatsDTO> getBlockedCountByDateAndBrigade(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyBrigadeStatsDTO> resultList = blockedDashboardMapper.selectBlockedCountByDateAndBrigade(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询每日平均查堵万分率(用于趋势图)
     * 
     * @param queryDTO 查询参数
     * @return 每日查堵万分率统计列表
     */
    @Override
    public List<BlockedDailyRateStatsDTO> getBlockedRateByDate(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyRateStatsDTO> resultList = blockedDashboardMapper.selectBlockedRateByDate(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询每日各大队平均查堵万分率(用于大队对比表)
     * 
     * @param queryDTO 查询参数
     * @return 每日各大队查堵万分率统计列表
     */
    @Override
    public List<BlockedDailyBrigadeRateStatsDTO> getBlockedRateByDateAndBrigade(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyBrigadeRateStatsDTO> resultList = blockedDashboardMapper.selectBlockedRateByDateAndBrigade(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询每日过检行李合计(用于趋势图)
     * 
     * @param queryDTO 查询参数
     * @return 每日过检行李统计列表
     */
    @Override
    public List<BlockedDailyLuggageStatsDTO> getTotalLuggageCountByDate(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyLuggageStatsDTO> resultList = blockedDashboardMapper.selectTotalLuggageCountByDate(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询每日各大队过检行李合计(用于大队对比表)
     * 
     * @param queryDTO 查询参数
     * @return 每日各大队过检行李统计列表
     */
    @Override
    public List<BlockedDailyBrigadeLuggageStatsDTO> getTotalLuggageCountByDateAndBrigade(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyBrigadeLuggageStatsDTO> resultList = blockedDashboardMapper.selectTotalLuggageCountByDateAndBrigade(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵物品分布(用于扇形图)
     * 
     * @param queryDTO 查询参数
     * @return 查堵物品分布统计列表
     */
    @Override
    public List<BlockedItemDistributionDTO> getItemDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedItemDistributionDTO> resultList = blockedDashboardMapper.selectItemDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询区域查堵数据分布(双轴图表)
     * 
     * @param queryDTO 查询参数
     * @return 区域查堵数据分布统计结果
     */
    @Override
    public BlockedAreaDistributionResultDTO getAreaDistribution(BlockedDashboardQueryDTO queryDTO) {
        BlockedAreaDistributionResultDTO result = new BlockedAreaDistributionResultDTO();
        
        // 查询过检行李数(柱状图数据)
        List<BlockedAreaLuggageDTO> luggageList = blockedDashboardMapper.selectAreaLuggageDistribution(queryDTO);
        result.setLuggageDataList(luggageList != null ? luggageList : Collections.emptyList());
        
        // 查询查堵件数(折线图数据)
        List<BlockedAreaBlockedDTO> blockedList = blockedDashboardMapper.selectAreaBlockedDistribution(queryDTO);
        result.setBlockedDataList(blockedList != null ? blockedList : Collections.emptyList());
        
        // 提取大队名称列表
        if (luggageList != null && !luggageList.isEmpty()) {
            List<String> brigadeNames = luggageList.stream()
                    .map(BlockedAreaLuggageDTO::getBrigadeName)
                    .collect(Collectors.toList());
            result.setBrigadeNames(brigadeNames);
        } else if (blockedList != null && !blockedList.isEmpty()) {
            List<String> brigadeNames = blockedList.stream()
                    .map(BlockedAreaBlockedDTO::getBrigadeName)
                    .collect(Collectors.toList());
            result.setBrigadeNames(brigadeNames);
        } else {
            result.setBrigadeNames(Collections.emptyList());
        }
        
        return result;
    }

    /**
     * 查询查堵类型分布(用于分组柱状图)
     * 
     * @param queryDTO 查询参数
     * @return 查堵类型分布统计列表
     */
    @Override
    public List<BlockedDiscriminationDistributionDTO> getDiscriminationDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDiscriminationDistributionDTO> resultList = blockedDashboardMapper.selectDiscriminationDistribution(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵时间段过检行李数及万分率(用于双轴图表)
     * 
     * @param queryDTO 查询参数
     * @return 时间段统计列表
     */
    @Override
    public List<BlockedTimePeriodStatsDTO> getTimePeriodStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedTimePeriodStatsDTO> resultList = blockedDashboardMapper.selectTimePeriodStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询每日过检行李数及万分率(用于双轴图表)
     * 
     * @param queryDTO 查询参数
     * @return 每日统计列表
     */
    @Override
    public List<BlockedTimePeriodStatsDTO> getDailyLuggageAndRate(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedTimePeriodStatsDTO> resultList = blockedDashboardMapper.selectDailyLuggageAndRate(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-AI复查图像总数(用于双系列图表)
     * 
     * @param queryDTO 查询参数
     * @return AI图像统计列表
     */
    @Override
    public List<BlockedDailyStatsDTO> getAiImageStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyStatsDTO> resultList = blockedDashboardMapper.selectAiImageStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-AI漏判图像总数(用于单系列图表)
     * 
     * @param queryDTO 查询参数
     * @return AI漏判图像统计列表
     */
    @Override
    public List<BlockedDailyStatsDTO> getAiMissImageStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyStatsDTO> resultList = blockedDashboardMapper.selectAiMissImageStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-AI误判图像总数(用于单系列图表)
     * 
     * @param queryDTO 查询参数
     * @return AI误判图像统计列表
     */
    @Override
    public List<BlockedDailyStatsDTO> getAiErrorImageStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyStatsDTO> resultList = blockedDashboardMapper.selectAiErrorImageStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-主管排行榜
     * 
     * @param queryDTO 查询参数
     * @return 主管排行榜列表
     */
    @Override
    public List<BlockedRankingDTO> getSupervisorRanking(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedRankingDTO> resultList = blockedDashboardMapper.selectSupervisorRanking(queryDTO);
        if (CollectionUtil.isNotEmpty(resultList)) {
            // 计算并列排名并限制前30条
            return calculateDenseRankingWithLimit(resultList, 30);
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-班组排行榜
     * 
     * @param queryDTO 查询参数
     * @return 班组排行榜列表
     */
    @Override
    public List<BlockedRankingDTO> getTeamLeaderRanking(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedRankingDTO> resultList = blockedDashboardMapper.selectTeamLeaderRanking(queryDTO);
        if (CollectionUtil.isNotEmpty(resultList)) {
            // 计算并列排名并限制前30条
            return calculateDenseRankingWithLimit(resultList, 30);
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-人员排行榜
     * 
     * @param queryDTO 查询参数
     * @return 人员排行榜列表
     */
    @Override
    public List<BlockedRankingDTO> getReviewedUserRanking(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedRankingDTO> resultList = blockedDashboardMapper.selectReviewedUserRanking(queryDTO);
        if (CollectionUtil.isNotEmpty(resultList)) {
            // 计算并列排名并限制前30条
            return calculateDenseRankingWithLimit(resultList, 30);
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-物品位置分布(用于扇形图)
     * 
     * @param queryDTO 查询参数
     * @return 物品位置分布统计列表
     */
    @Override
    public List<BlockedItemLocationDistributionDTO> getItemLocationDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedItemLocationDistributionDTO> resultList = blockedDashboardMapper.selectItemLocationDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-原因分类分布(用于扇形图)
     * 
     * @param queryDTO 查询参数
     * @return 原因分类分布统计列表
     */
    @Override
    public List<BlockedMissCheckReasonDistributionDTO> getMissCheckReasonDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedMissCheckReasonDistributionDTO> resultList = blockedDashboardMapper.selectMissCheckReasonDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-图像难易程度分布(用于扇形图)
     * 
     * @param queryDTO 查询参数
     * @return 难易程度分布统计列表
     */
    @Override
    public List<BlockedDifficultyDistributionDTO> getDifficultyDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDifficultyDistributionDTO> resultList = blockedDashboardMapper.selectDifficultyDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-开机人员持证比例(用于扇形图)
     * 
     * @param queryDTO 查询参数
     * @return 证书级别分布统计列表
     */
    @Override
    public List<BlockedCertificateDistributionDTO> getCertificateDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedCertificateDistributionDTO> resultList = blockedDashboardMapper.selectCertificateDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                    // 转换证书级别为中文
                    if (item.getCertificateLevel() != null) {
                        item.setCertificateLevel(convertCertificateLevel(item.getCertificateLevel()));
                    }
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询大队开机人员证书分布(用于柱状图)
     * 通过ancestors字段找到每个用户所属的最上级大队，然后按大队分组统计
     * 
     * @param queryDTO 查询参数
     * @return 大队证书分布统计列表
     */
    @Override
    public List<BlockedCertificateLevelDTO> getBrigadeCertificateDistribution(BlockedDashboardQueryDTO queryDTO) {
        // 1. 从数据库获取原始数据
        List<Map<String, Object>> rawData = blockedDashboardMapper.selectBrigadeCertificateDistribution(queryDTO);
        
        if (rawData == null || rawData.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 2. 收集所有需要查询的部门ID（包括ancestors中的所有ID和当前dept_id）
        Set<Long> allDeptIds = new HashSet<>();
        for (Map<String, Object> row : rawData) {
            String ancestors = (String) row.get("ancestors");
            Long deptId = ((Number) row.get("dept_id")).longValue();
            
            if (ancestors != null && !ancestors.isEmpty()) {
                String[] ancestorIds = ancestors.split(",");
                for (String idStr : ancestorIds) {
                    try {
                        Long id = Long.parseLong(idStr.trim());
                        if (id > 0) {
                            allDeptIds.add(id);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略
                    }
                }
            }
            if (deptId != null) {
                allDeptIds.add(deptId);
            }
        }
        
        // 3. 批量查询所有部门信息，构建大队ID映射缓存
        Map<Long, Long> deptToBrigadeMap = buildDeptToBrigadeMap(allDeptIds);
        
        // 4. 按大队分组统计
        Map<Long, BlockedCertificateLevelDTO> brigadeMap = new LinkedHashMap<>();
        
        for (Map<String, Object> row : rawData) {
            String qualificationLevel = (String) row.get("qualification_level");
            Long deptId = ((Number) row.get("dept_id")).longValue();
            
            // 5. 从缓存中获取大队ID
            Long brigadeId = deptToBrigadeMap.get(deptId);
            
            if (brigadeId == null) {
                continue; // 跳过无法找到大队的用户
            }
            
            // 6. 获取或创建大队统计对象
            BlockedCertificateLevelDTO stats = brigadeMap.computeIfAbsent(brigadeId, id -> {
                BlockedCertificateLevelDTO dto = new BlockedCertificateLevelDTO();
                dto.setBrigadeId(id);
                dto.setSeniorCount(0);
                dto.setMiddleCount(0);
                dto.setJuniorCount(0);
                dto.setTotalCount(0);
                return dto;
            });
            
            // 7. 根据证书级别统计
            if ("LEVEL_ONE".equals(qualificationLevel) || 
                "LEVEL_TWO".equals(qualificationLevel) || 
                "LEVEL_THREE".equals(qualificationLevel)) {
                stats.setSeniorCount(stats.getSeniorCount() + 1);
            } else if ("LEVEL_FOUR".equals(qualificationLevel)) {
                stats.setMiddleCount(stats.getMiddleCount() + 1);
            } else if ("LEVEL_FIVE".equals(qualificationLevel)) {
                stats.setJuniorCount(stats.getJuniorCount() + 1);
            }
            
            stats.setTotalCount(stats.getTotalCount() + 1);
        }
        
        // 8. 转换为列表并填充大队名称
        List<BlockedCertificateLevelDTO> resultList = new ArrayList<>(brigadeMap.values());
        fillBrigadeNames(resultList);
        
        // 9. 按总人数降序排序
        resultList.sort((a, b) -> b.getTotalCount().compareTo(a.getTotalCount()));
        
        return resultList;
    }
    
    /**
     * 构建部门到大队的映射关系
     * 遍历所有部门的ancestors，找到每个部门所属的最上级大队
     * 
     * @param allDeptIds 所有需要查询的部门ID集合
     * @return 部门ID -> 大队ID 的映射
     */
    private Map<Long, Long> buildDeptToBrigadeMap(Set<Long> allDeptIds) {
        if (allDeptIds == null || allDeptIds.isEmpty()) {
            return Collections.emptyMap();
        }
        
        // 1. 批量查询所有部门信息
        List<SysDept> allDepts = sysDeptMapper.selectDeptByIdList(new ArrayList<>(allDeptIds));
        
        if (allDepts == null || allDepts.isEmpty()) {
            return Collections.emptyMap();
        }
        
        // 2. 构建部门ID到部门对象的映射
        Map<Long, SysDept> deptMap = new HashMap<>();
        for (SysDept dept : allDepts) {
            deptMap.put(dept.getDeptId(), dept);
        }
        
        // 3. 找出所有大队类型的部门ID
        Set<Long> brigadeIds = new HashSet<>();
        for (SysDept dept : allDepts) {
            if ("BRIGADE".equals(dept.getDeptType())) {
                brigadeIds.add(dept.getDeptId());
            }
        }
        
        // 4. 为每个部门找到其所属的最上级大队
        Map<Long, Long> deptToBrigadeMap = new HashMap<>();
        for (SysDept dept : allDepts) {
            Long brigadeId = findBrigadeIdFromAncestors(dept.getAncestors(), dept.getDeptId(), brigadeIds);
            if (brigadeId != null) {
                deptToBrigadeMap.put(dept.getDeptId(), brigadeId);
            }
        }
        
        return deptToBrigadeMap;
    }
    
    /**
     * 从ancestors中找到最上级大队ID
     * 
     * @param ancestors 祖级列表
     * @param currentDeptId 当前部门ID
     * @param brigadeIds 所有大队ID集合
     * @return 最上级大队ID，如果找不到则返回null
     */
    private Long findBrigadeIdFromAncestors(String ancestors, Long currentDeptId, Set<Long> brigadeIds) {
        if (ancestors == null || ancestors.isEmpty()) {
            return null;
        }
        
        // 将ancestors分割成ID列表
        String[] ancestorIds = ancestors.split(",");
        
        // 遍历祖先节点，找到第一个大队类型的部门
        for (String ancestorIdStr : ancestorIds) {
            try {
                Long ancestorId = Long.parseLong(ancestorIdStr.trim());
                if (ancestorId > 0 && brigadeIds.contains(ancestorId)) {
                    return ancestorId;
                }
            } catch (NumberFormatException e) {
                // 忽略解析错误
            }
        }
        
        // 如果祖先节点中没有找到大队，检查当前部门是否为大队
        if (currentDeptId != null && brigadeIds.contains(currentDeptId)) {
            return currentDeptId;
        }
        
        return null;
    }
    
    /**
     * 填充大队名称（批量查询）
     * 
     * @param resultList 统计结果列表
     */
    private void fillBrigadeNames(List<BlockedCertificateLevelDTO> resultList) {
        if (resultList == null || resultList.isEmpty()) {
            return;
        }
        
        // 收集所有大队ID
        List<Long> brigadeIds = resultList.stream()
                .map(BlockedCertificateLevelDTO::getBrigadeId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        
        if (brigadeIds.isEmpty()) {
            return;
        }
        
        // 批量查询大队信息
        List<SysDept> brigades = sysDeptMapper.selectDeptByIdList(brigadeIds);
        
        // 构建大队ID到名称的映射
        Map<Long, String> brigadeNameMap = new HashMap<>();
        for (SysDept dept : brigades) {
            brigadeNameMap.put(dept.getDeptId(), dept.getDeptName());
        }
        
        // 填充名称
        for (BlockedCertificateLevelDTO dto : resultList) {
            if (dto.getBrigadeId() != null) {
                dto.setBrigadeName(brigadeNameMap.get(dto.getBrigadeId()));
            }
        }
    }

    /**
     * 查询两楼每日查堵走势(按大队)
     * 数据来源：各大队每日过检行李查堵数据收集表
     * 先查出来是哪个安检大队的，然后按日期统计以下四个字段：
     * T1旅检查堵件数、T2旅检查堵件数、T1行检查堵件数、T2行检查堵件数
     * 
     * @param queryDTO 查询参数
     * @return 两楼每日查堵走势统计列表
     */
    @Override
    public List<BlockedDailyBrigadeTerminalStatsDTO> getDailyBrigadeTerminalStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyBrigadeTerminalStatsDTO> resultList = blockedDashboardMapper.selectDailyBrigadeTerminalStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询两楼每日过检图像数(按大队)
     * 数据来源：各大队每日过检行李查堵数据收集表
     * 先查出来是哪个安检大队的，然后按日期统计以下四个字段：
     * T2旅检过检行李数、T1旅检过检行李数、T1行检过检行李数、T2行检过检行李数
     * 
     * @param queryDTO 查询参数
     * @return 两楼每日过检图像数统计列表
     */
    @Override
    public List<BlockedDailyBrigadeTerminalLuggageStatsDTO> getDailyBrigadeTerminalLuggageStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyBrigadeTerminalLuggageStatsDTO> resultList = blockedDashboardMapper.selectDailyBrigadeTerminalLuggageStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询两楼查堵数（包含行检，按大队）
     * 数据来源：漏检统计表
     * 先查大队数量，再查T1、T2数量
     * 
     * @param queryDTO 查询参数
     * @return 两楼查堵数统计
     */
    @Override
    public BlockedTerminalStatsDTO getTerminalBlockedStats(BlockedDashboardQueryDTO queryDTO) {
        return blockedDashboardMapper.selectTerminalBlockedStats(queryDTO);
    }

    /**
     * 查询查堵时间段过检行李数(按大队)
     * 数据源：每日各时间段过检行李数
     * 维度(横轴)：时间段
     * 统计值(左坐标轴)：过检行李数平均值
     * 统计值(右坐标轴)：时段查堵件数平均值
     * 
     * @param queryDTO 查询参数
     * @return 时间段过检行李数统计列表
     */
    @Override
    public List<BlockedTimePeriodLuggageStatsDTO> getTimePeriodLuggageStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedTimePeriodLuggageStatsDTO> resultList = blockedDashboardMapper.selectTimePeriodLuggageStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询两楼每日查堵万分率(按大队)
     * 数据源：各大队每日过检行李查堵数据收集表
     * 按时间统计T2旅检万分率、T1旅检万分率、T1行检万分率、T2行检万分率
     * 
     * @param queryDTO 查询参数
     * @return 两楼每日查堵万分率统计列表
     */
    @Override
    public List<BlockedDailyBrigadeTerminalRateStatsDTO> getDailyBrigadeTerminalRateStats(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedDailyBrigadeTerminalRateStatsDTO> resultList = blockedDashboardMapper.selectDailyBrigadeTerminalRateStats(queryDTO);
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-主管排行榜(大队维度,前10名)
     * 数据源：漏检统计表
     * 数据筛选：分管主管不为空
     * 排行字段：分管主管
     * 排行依据：统计记录总数
     * 显示行数：显示前10行
     * 
     * @param queryDTO 查询参数
     * @return 主管排行榜列表（前10名）
     */
    @Override
    public List<BlockedRankingDTO> getBrigadeSupervisorRanking(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedRankingDTO> resultList = blockedDashboardMapper.selectBrigadeSupervisorRanking(queryDTO);
        if (CollectionUtil.isNotEmpty(resultList)) {
            // 计算并列排名并限制前10条
            return calculateDenseRankingWithLimit(resultList, 10);
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-班组排行榜(大队维度,前10名)
     * 数据源：漏检统计表
     * 数据筛选：分管班组长不为空
     * 排行字段：分管班组长
     * 排行依据：统计记录总数
     * 显示行数：显示前10条（并列排名）
     * 
     * @param queryDTO 查询参数
     * @return 班组排行榜列表（前10条）
     */
    @Override
    public List<BlockedRankingDTO> getBrigadeTeamLeaderRanking(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedRankingDTO> resultList = blockedDashboardMapper.selectBrigadeTeamLeaderRanking(queryDTO);
        if (CollectionUtil.isNotEmpty(resultList)) {
            // 计算并列排名并限制前10条
            return calculateDenseRankingWithLimit(resultList, 10);
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵-人员排行榜(大队维度,前10名)
     * 数据源：漏检统计表
     * 数据筛选：被回查人不为空
     * 排行字段：被回查人
     * 排行依据：统计记录总数
     * 显示行数：显示前10条（并列排名）
     * 
     * @param queryDTO 查询参数
     * @return 人员排行榜列表（前10条）
     */
    @Override
    public List<BlockedRankingDTO> getBrigadeReviewedUserRanking(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedRankingDTO> resultList = blockedDashboardMapper.selectBrigadeReviewedUserRanking(queryDTO);
        if (CollectionUtil.isNotEmpty(resultList)) {
            // 计算并列排名并限制前10条
            return calculateDenseRankingWithLimit(resultList, 10);
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵男女比例(按大队)
     * 数据源：漏检统计表
     * 统计性别分布
     * 
     * @param queryDTO 查询参数
     * @return 男女比例统计列表
     */
    @Override
    public List<BlockedGenderDistributionDTO> getGenderDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedGenderDistributionDTO> resultList = blockedDashboardMapper.selectGenderDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵人员证书级别分布(按大队)
     * 数据源：漏检统计表
     * 统计证书级别分布
     * 
     * @param queryDTO 查询参数
     * @return 证书级别分布统计列表
     */
    @Override
    public List<BlockedCertificateLevelDistributionDTO> getCertificateLevelDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedCertificateLevelDistributionDTO> resultList = blockedDashboardMapper.selectCertificateLevelDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询证书级别人员基数(分大队统计)
     * 数据源：用户表(sys_user) + 部门表(sys_dept)
     * 统计指定大队及其下属所有部门的人员证书级别构成
     *
     * @param queryDTO 查询参数（大队ID必填）
     * @return 证书级别人员基数统计列表
     */
    @Override
    public List<BlockedCertificateLevelDistributionDTO> getBrigadePersonnelCertificateBase(BlockedDashboardQueryDTO queryDTO) {
        // 1. 从数据库获取原始数据
        List<Map<String, Object>> rawData = blockedDashboardMapper.selectBrigadePersonnelCertificateBase(queryDTO);
        
        if (rawData == null || rawData.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 2. 按证书级别分组统计
        Map<String, Long> levelCountMap = new HashMap<>();
        long totalCount = 0;
        
        for (Map<String, Object> row : rawData) {
            String qualificationLevel = (String) row.get("qualification_level");
            if (qualificationLevel != null && !qualificationLevel.isEmpty()) {
                levelCountMap.merge(qualificationLevel, 1L, Long::sum);
                totalCount++;
            }
        }
        
        // 3. 构建结果列表
        List<BlockedCertificateLevelDistributionDTO> resultList = new ArrayList<>();
        for (Map.Entry<String, Long> entry : levelCountMap.entrySet()) {
            BlockedCertificateLevelDistributionDTO dto = new BlockedCertificateLevelDistributionDTO();
            dto.setCertificateLevel(convertCertificateLevel(entry.getKey()));
            dto.setCount(entry.getValue().intValue());
            
            // 计算百分比
            if (totalCount > 0) {
                double percentage = Math.round(entry.getValue() * 10000.0 / totalCount) / 100.0;
                dto.setPercentage(java.math.BigDecimal.valueOf(percentage));
            }
            
            resultList.add(dto);
        }
        
        // 4. 按数量降序排序
        resultList.sort((a, b) -> Long.compare(
            b.getCount() != null ? b.getCount() : 0,
            a.getCount() != null ? a.getCount() : 0
        ));
        
        return resultList;
    }

    /**
     * 查询查堵-主管分管次数分布(用于饼图)
     * 数据源：漏检统计表
     * 统计字段：分管主管
     * 
     * @param queryDTO 查询参数
     * @return 主管分管次数分布统计列表
     */
    @Override
    public List<BlockedRankingDTO> getSupervisorDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedRankingDTO> resultList = blockedDashboardMapper.selectSupervisorDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getTotalCount() != null ? item.getTotalCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getTotalCount() != null ? item.getTotalCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 查询查堵人员开机年限分布(用于饼图)
     * 数据源：漏检统计表
     * 统计字段：开机年限
     * 
     * @param queryDTO 查询参数
     * @return 开机年限分布统计列表
     */
    @Override
    public List<BlockedOperatingYearsDistributionDTO> getOperatingYearsDistribution(BlockedDashboardQueryDTO queryDTO) {
        List<BlockedOperatingYearsDistributionDTO> resultList = blockedDashboardMapper.selectOperatingYearsDistribution(queryDTO);
        if (resultList != null && !resultList.isEmpty()) {
            // 计算总数
            long totalCount = resultList.stream().mapToLong(item -> item.getCount() != null ? item.getCount() : 0).sum();
            // 计算百分比
            if (totalCount > 0) {
                resultList.forEach(item -> {
                    long count = item.getCount() != null ? item.getCount() : 0;
                    double percentage = Math.round(count * 10000.0 / totalCount) / 100.0;
                    item.setPercentage(java.math.BigDecimal.valueOf(percentage));
                });
            }
        }
        return resultList != null ? resultList : Collections.emptyList();
    }

    /**
     * 转换证书级别代码为中文
     * LEVEL_FIVE -> 初级
     * LEVEL_FOUR -> 中级
     * LEVEL_ONE/LEVEL_TWO/LEVEL_THREE -> 高级
     * 
     * @param levelCode 级别代码
     * @return 中文级别名称
     */
    private String convertCertificateLevel(String levelCode) {
        if (levelCode == null) {
            return "";
        }
        switch (levelCode) {
            case "LEVEL_FIVE":
                return "初级";
            case "LEVEL_FOUR":
                return "中级";
            case "LEVEL_ONE":
            case "LEVEL_TWO":
            case "LEVEL_THREE":
                return "高级";
            default:
                return levelCode;
        }
    }

    /**
     * 计算并列排名并限制前N条
     * 并列排名规则：相同totalCount的记录排名相同，下一个不同值的排名紧接其后
     * 限制规则：只返回排名序号 <= maxRank 的记录
     *
     * @param resultList 排行榜数据列表（已按totalCount降序排序）
     * @param maxRank 最大排名序号（站级30，大队10）
     * @return 过滤后的排行榜列表
     */
    private List<BlockedRankingDTO> calculateDenseRankingWithLimit(List<BlockedRankingDTO> resultList, int maxRank) {
        if (resultList == null || resultList.isEmpty()) {
            return resultList;
        }

        List<BlockedRankingDTO> result = new ArrayList<>();
        int currentRank = 1;  // 当前排名
        Integer previousCount = null;  // 上一个记录的totalCount

        for (BlockedRankingDTO item : resultList) {
            Integer currentCount = item.getTotalCount();
            
            // 如果totalCount与上一个不同，更新排名
            if (previousCount == null || !currentCount.equals(previousCount)) {
                // 如果当前排名已经超过限制，停止添加
                if (currentRank > maxRank) {
                    break;
                }
                previousCount = currentCount;
            }
            
            // 设置排名并添加到结果列表
            item.setRank(currentRank);
            result.add(item);
        }

        return result;
    }

    /**
     * 查询旅检万分查堵率平均值
     * 
     * @param queryDTO 查询参数
     * @return 旅检万分查堵率平均值
     */
    @Override
    public BigDecimal getTravelInspectionBlockRate(BlockedDashboardQueryDTO queryDTO) {
        BigDecimal travelRate = blockedDashboardMapper.selectTravelInspectionBlockRate(queryDTO);
        // 保留两位小数
        if (travelRate != null) {
            return travelRate.setScale(2, java.math.RoundingMode.HALF_UP);
        }
        return BigDecimal.ZERO;
    }

    /**
     * 查询行检万分查堵率平均值
     * 
     * @param queryDTO 查询参数
     * @return 行检万分查堵率平均值
     */
    @Override
    public BigDecimal getWalkInspectionBlockRate(BlockedDashboardQueryDTO queryDTO) {
        BigDecimal walkRate = blockedDashboardMapper.selectWalkInspectionBlockRate(queryDTO);
        // 保留两位小数
        if (walkRate != null) {
            return walkRate.setScale(2, java.math.RoundingMode.HALF_UP);
        }
        return BigDecimal.ZERO;
    }
}
