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

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
import com.sundot.airport.common.core.domain.DailyTaskAccuracyRankingDto;
import com.sundot.airport.common.core.domain.DailyTaskAccuracyRankingItemDto;
import com.sundot.airport.common.core.domain.SysHomeReportDetailDto;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.dto.CategoryAccuracyItemDto;
import com.sundot.airport.common.dto.QuizAccuracyAnalysisResultDto;
import com.sundot.airport.common.enums.DeptTypeEnum;
import com.sundot.airport.common.enums.HomePageQueryEnum;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.common.enums.DeptType;
import com.sundot.airport.common.enums.MedalTypeEnum;
import com.sundot.airport.common.enums.RoleTypeEnum;
import com.sundot.airport.common.enums.TimeRangeEnum;
import com.sundot.airport.common.core.domain.entity.SysRole;
import com.sundot.airport.common.utils.DateUtils;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.exam.domain.DailyTask;
import com.sundot.airport.exam.domain.DailyTaskDetail;
import com.sundot.airport.exam.dto.AccuracyAggregateStatisticsDTO;
import com.sundot.airport.exam.dto.AccuracyStatisticsDTO;
import com.sundot.airport.exam.dto.AccuracyStatisticsQueryDTO;
import com.sundot.airport.exam.enums.DailyTaskStatusEnum;
import com.sundot.airport.exam.mapper.DailyTaskDetailMapper;
import com.sundot.airport.exam.mapper.DailyTaskMapper;
import com.sundot.airport.exam.service.IAccuracyStatisticsService;
import com.sundot.airport.system.service.ISysDeptService;
import com.sundot.airport.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Collections;
import java.util.stream.Collectors;

/**
 * <b>功能名：</b>AccuracyStatisticsServiceImpl<br>
 * <b>说明：</b> 抽问抽答正确率统计Service实现（匹配成都接口格式，适配美兰4级架构） <br>
 * <b>著作权：</b> Copyright (C) 2026 SUNDOT CORPORATION<br>
 *
 * @author Simon Lin
 */
@Service
public class AccuracyStatisticsServiceImpl implements IAccuracyStatisticsService {

    private static final Logger log = LoggerFactory.getLogger(AccuracyStatisticsServiceImpl.class);

    @Autowired
    private DailyTaskMapper dailyTaskMapper;

    @Autowired
    private DailyTaskDetailMapper dailyTaskDetailMapper;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private org.springframework.jdbc.core.JdbcTemplate jdbcTemplate;

    /**
     * 部门数据缓存（请求级别）
     */
    private static class DeptCache {
        List<SysDept> allDepts;
        Map<Long, SysDept> deptMap;
        Map<Long, DeptHierarchy> hierarchyMap;
        // 按部门类型分组的部门列表
        List<SysDept> teamDepts;
        List<SysDept> managerDepts;
        List<SysDept> brigadeDepts;
        // 班组正确率缓存
        Map<Long, BigDecimal> teamAccuracyMap;

        DeptCache(List<SysDept> allDepts) {
            this.allDepts = allDepts;
            this.deptMap = new HashMap<>();
            this.hierarchyMap = new HashMap<>();
            this.teamDepts = new ArrayList<>();
            this.managerDepts = new ArrayList<>();
            this.brigadeDepts = new ArrayList<>();
            this.teamAccuracyMap = new HashMap<>();

            // 初始化部门Map
            for (SysDept dept : allDepts) {
                if ("0".equals(dept.getDelFlag())) {
                    deptMap.put(dept.getDeptId(), dept);
                    // 按类型分组
                    if (StrUtil.equals(DeptType.TEAMS.getCode(), dept.getDeptType())) {
                        teamDepts.add(dept);
                    } else if (StrUtil.equals(DeptType.MANAGER.getCode(), dept.getDeptType())) {
                        managerDepts.add(dept);
                    } else if (StrUtil.equals(DeptType.BRIGADE.getCode(), dept.getDeptType())) {
                        brigadeDepts.add(dept);
                    }
                }
            }
        }

        /**
         * 获取部门层级（带缓存）
         */
        DeptHierarchy getHierarchy(Long deptId) {
            if (deptId == null) return new DeptHierarchy();
            return hierarchyMap.computeIfAbsent(deptId, this::computeHierarchy);
        }

        private DeptHierarchy computeHierarchy(Long deptId) {
            DeptHierarchy hierarchy = new DeptHierarchy();
            SysDept dept = deptMap.get(deptId);
            if (dept == null) return hierarchy;

            String ancestors = dept.getAncestors();
            String deptType = dept.getDeptType();

            if (ancestors == null || ancestors.trim().isEmpty()) {
                hierarchy.stationId = deptId;
                return hierarchy;
            }

            String[] ancestorIds = ancestors.split(",");
            if (ancestorIds.length >= 2) {
                try {
                    hierarchy.stationId = Long.parseLong(ancestorIds[1].trim());
                } catch (NumberFormatException ignored) {
                }
            }
            if (ancestorIds.length >= 3) {
                try {
                    hierarchy.brigadeId = Long.parseLong(ancestorIds[2].trim());
                } catch (NumberFormatException ignored) {
                }
            }
            if (ancestorIds.length >= 4) {
                try {
                    hierarchy.managerId = Long.parseLong(ancestorIds[3].trim());
                } catch (NumberFormatException ignored) {
                }
            }

            if (StrUtil.equals(DeptType.STATION.getCode(), deptType)) {
                hierarchy.stationId = deptId;
            } else if (StrUtil.equals(DeptType.BRIGADE.getCode(), deptType)) {
                hierarchy.brigadeId = deptId;
            } else if (StrUtil.equals(DeptType.MANAGER.getCode(), deptType)) {
                hierarchy.managerId = deptId;
            } else if (StrUtil.equals(DeptType.TEAMS.getCode(), deptType)) {
                hierarchy.teamId = deptId;
            }

            return hierarchy;
        }
    }

    /**
     * ThreadLocal缓存，用于在同一请求中共享部门数据
     */
    private static final ThreadLocal<DeptCache> DEPT_CACHE = new ThreadLocal<>();

    /**
     * 初始化部门缓存
     */
    @Override
    public void initDeptCache() {
        DeptCache cache = DEPT_CACHE.get();
        if (cache == null) {
            long start = System.currentTimeMillis();
            List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());
            cache = new DeptCache(allDepts);
            DEPT_CACHE.set(cache);
            log.info("initDeptCache: loaded {} depts in {}ms", allDepts.size(), System.currentTimeMillis() - start);
        }
    }

    /**
     * 清理缓存
     */
    @Override
    public void clearDeptCache() {
        DEPT_CACHE.remove();
    }

    /**
     * 获取当前缓存（如果存在）
     */
    private DeptCache getDeptCache() {
        return DEPT_CACHE.get();
    }

    @Override
    public AccuracyStatisticsDTO getAccuracyStatistics(AccuracyStatisticsQueryDTO query) {
        long methodStart = System.currentTimeMillis();
        try {
            // 初始化部门缓存（整个请求中复用）
            initDeptCache();

            // 获取当前用户信息（从登录信息中获取，确保包含角色信息）
            Long currentUserId = SecurityUtils.getUserId();
            Long currentDeptId = SecurityUtils.getDeptId();
            SysUser currentUser = SecurityUtils.getLoginUser().getUser();

            // 调试日志
            log.info("getAccuracyStatistics - currentUserId: {}, currentDeptId: {}", currentUserId, currentDeptId);
            log.info("getAccuracyStatistics - currentUser: {}", currentUser != null ? currentUser.getUserName() : "null");
            log.info("getAccuracyStatistics - currentUser.getRoles(): {}", currentUser != null ? currentUser.getRoles() : "null");

            AccuracyStatisticsDTO result = new AccuracyStatisticsDTO();

            // 获取用户角色
            String roleKey = getUserRoleKey(currentUser);
            log.info("getAccuracyStatistics - roleKey: {}", roleKey);
            if (currentUser != null && currentUser.getRoles() != null && !currentUser.getRoles().isEmpty()) {
                result.setUserRole(currentUser.getRoles().get(0).getRoleName());
            }

            // 解析时间范围
            Date[] dateRange = parseDateRange(query);
            Date startDate = dateRange[0];
            Date endDate = dateRange[1];

            // 设置时间范围描述
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            if (startDate != null && endDate != null) {
                result.setTimePeriod(sdf.format(startDate) + " ~ " + sdf.format(endDate));
            }

            // 获取部门层级信息（使用缓存）
            DeptHierarchy hierarchy = getDeptHierarchyCached(currentDeptId);

            // 检查是否有待完成任务
            checkPendingTask(result, currentUserId);

            // 根据角色返回不同的数据
            if (RoleTypeEnum.SecurityCheck.getCode().equals(roleKey)) {
                // 安检员
                calculateSecurityCheckData(result, currentUserId, hierarchy, startDate, endDate);
            } else if (RoleTypeEnum.banzuzhang.getCode().equals(roleKey)) {
                // 班组长（支持dataSource参数）
                calculateTeamLeaderData(result, currentUserId, hierarchy, startDate, endDate, query);
            } else if (RoleTypeEnum.kezhang.getCode().equals(roleKey)) {
                // 主管
                calculateManagerData(result, currentUserId, hierarchy, startDate, endDate);
            } else if (RoleTypeEnum.jingli.getCode().equals(roleKey) || RoleTypeEnum.xingzheng.getCode().equals(roleKey)) {
                // 大队长（经理/行政）
                calculateBrigadeLeaderData(result, hierarchy, startDate, endDate);
            } else if (RoleTypeEnum.test.getCode().equals(roleKey)) {
                // 站长
                calculateStationLeaderData(result, hierarchy, startDate, endDate);
            } else if (RoleTypeEnum.admin.getCode().equals(roleKey) || RoleTypeEnum.zhijianke.getCode().equals(roleKey)) {
                // 超级管理员、质检科：与站长相同视角，查看全站数据
                calculateStationLeaderData(result, hierarchy, startDate, endDate);
            } else {
                // 其他角色：返回基本数据
                calculatePersonalAccuracy(result, currentUserId, startDate, endDate);
                calculateLevelAvgAccuracy(result, hierarchy, startDate, endDate);
            }

            log.info("getAccuracyStatistics completed in {}ms", System.currentTimeMillis() - methodStart);
            return result;
        } finally {
            // 清理缓存，避免内存泄漏
            clearDeptCache();
        }
    }

    /**
     * 获取部门层级（使用缓存）
     */
    private DeptHierarchy getDeptHierarchyCached(Long deptId) {
        DeptCache cache = getDeptCache();
        if (cache != null) {
            return cache.getHierarchy(deptId);
        }
        return getDeptHierarchy(deptId);
    }

    /**
     * 获取用户的角色Key
     */
    private String getUserRoleKey(SysUser user) {
        if (user == null || user.getRoles() == null || user.getRoles().isEmpty()) {
            return null;
        }
        // 按优先级返回角色：站长 > 大队长 > 主管 > 班组长 > 安检员
        List<String> roleKeys = user.getRoles().stream().map(SysRole::getRoleKey).collect(Collectors.toList());
        if (roleKeys.contains(RoleTypeEnum.test.getCode())) {
            return RoleTypeEnum.test.getCode();
        }
        if (roleKeys.contains(RoleTypeEnum.jingli.getCode())) {
            return RoleTypeEnum.jingli.getCode();
        }
        if (roleKeys.contains(RoleTypeEnum.xingzheng.getCode())) {
            return RoleTypeEnum.xingzheng.getCode();
        }
        if (roleKeys.contains(RoleTypeEnum.kezhang.getCode())) {
            return RoleTypeEnum.kezhang.getCode();
        }
        if (roleKeys.contains(RoleTypeEnum.banzuzhang.getCode())) {
            return RoleTypeEnum.banzuzhang.getCode();
        }
        if (roleKeys.contains(RoleTypeEnum.SecurityCheck.getCode())) {
            return RoleTypeEnum.SecurityCheck.getCode();
        }
        return user.getRoles().get(0).getRoleKey();
    }

    /**
     * 安检员数据计算
     * 正确率：本人、班平均、主管平均、大队平均、站平均
     * 排名：班组排名、主管排名、大队排名、全站排名（个人排名）
     */
    private void calculateSecurityCheckData(AccuracyStatisticsDTO result, Long userId, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 个人正确率
        calculatePersonalAccuracy(result, userId, startDate, endDate);

        // 班平均、主管平均、大队平均、站平均
        if (hierarchy.teamId != null) {
            result.setTeamAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.teamId, startDate, endDate));
        }
        if (hierarchy.managerId != null) {
            result.setDeptAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.managerId, startDate, endDate));
        }
        if (hierarchy.brigadeId != null) {
            result.setBrigadeAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.brigadeId, startDate, endDate));
        }
        if (hierarchy.stationId != null) {
            result.setSiteAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.stationId, startDate, endDate));
        }

        // 个人在各层级的排名
        calculatePersonalRankings(result, userId, hierarchy, startDate, endDate);
    }

    /**
     * 班组长数据计算
     * 支持dataSource参数：
     * - individual：返回班组长个人数据（个人正确率、个人在各层级的排名）
     * - team或空：返回班组数据（班组正确率、班组在各层级的排名）
     */
    private void calculateTeamLeaderData(AccuracyStatisticsDTO result, Long userId, DeptHierarchy hierarchy, Date startDate, Date endDate, AccuracyStatisticsQueryDTO query) {
        // 根据dataSource参数决定返回个人数据还是班组数据
        if (query != null && "individual".equalsIgnoreCase(query.getDataSource())) {
            // 返回班组长个人数据（类似安检员的数据）
            log.info("班组长 {} 查询个人数据（dataSource=individual）", userId);
            calculateSecurityCheckData(result, userId, hierarchy, startDate, endDate);
            return;
        }

        // 默认返回班组数据（dataSource为"team"或未指定）
        log.info("班组长 {} 查询班组数据（dataSource={}）", userId, query != null ? query.getDataSource() : "null");

        // 班平均、主管平均、大队平均、站平均
        if (hierarchy.teamId != null) {
            result.setTeamAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.teamId, startDate, endDate));
        }
        if (hierarchy.managerId != null) {
            result.setDeptAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.managerId, startDate, endDate));
        }
        if (hierarchy.brigadeId != null) {
            result.setBrigadeAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.brigadeId, startDate, endDate));
        }
        if (hierarchy.stationId != null) {
            result.setSiteAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.stationId, startDate, endDate));
        }

        // 班组在主管中的排名
        if (hierarchy.teamId != null && hierarchy.managerId != null) {
            List<TeamAccuracyInfo> teamsInManager = calculateTeamAccuraciesUnderDept(hierarchy.managerId, startDate, endDate);
            if (!teamsInManager.isEmpty()) {
                result.setTeamInDeptRanking(findTeamRanking(hierarchy.teamId, teamsInManager));
            }
        }

        // 班组在大队中的排名
        if (hierarchy.teamId != null && hierarchy.brigadeId != null) {
            List<TeamAccuracyInfo> teamsInBrigade = calculateTeamAccuraciesUnderDept(hierarchy.brigadeId, startDate, endDate);
            if (!teamsInBrigade.isEmpty()) {
                result.setTeamInBrigadeRanking(findTeamRanking(hierarchy.teamId, teamsInBrigade));
            }
        }

        // 班组在全站中的排名
        if (hierarchy.teamId != null && hierarchy.stationId != null) {
            List<TeamAccuracyInfo> teamsInStation = calculateTeamAccuraciesUnderDept(hierarchy.stationId, startDate, endDate);
            if (!teamsInStation.isEmpty()) {
                result.setTeamInSiteRanking(findTeamRanking(hierarchy.teamId, teamsInStation));
            }
        }
    }

    /**
     * 主管数据计算
     * 正确率：主管平均、大队平均、站平均
     * 排名：大队排名、全站排名（主管排名）
     */
    private void calculateManagerData(AccuracyStatisticsDTO result, Long userId, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 主管平均、大队平均、站平均
        if (hierarchy.managerId != null) {
            result.setDeptAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.managerId, startDate, endDate));
        }
        if (hierarchy.brigadeId != null) {
            result.setBrigadeAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.brigadeId, startDate, endDate));
        }
        if (hierarchy.stationId != null) {
            result.setSiteAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.stationId, startDate, endDate));
        }

        // 主管在大队中的排名
        if (hierarchy.managerId != null && hierarchy.brigadeId != null) {
            List<TeamAccuracyInfo> managersInBrigade = calculateManagerAccuraciesUnderBrigade(hierarchy.brigadeId, startDate, endDate);
            if (!managersInBrigade.isEmpty()) {
                result.setDeptInBrigadeRanking(findTeamRanking(hierarchy.managerId, managersInBrigade));
            }
        }

        // 主管在全站中的排名
        if (hierarchy.managerId != null && hierarchy.stationId != null) {
            List<TeamAccuracyInfo> managersInStation = calculateManagerAccuraciesUnderStation(hierarchy.stationId, startDate, endDate);
            if (!managersInStation.isEmpty()) {
                result.setDeptInSiteRanking(findTeamRanking(hierarchy.managerId, managersInStation));
            }
        }
    }

    /**
     * 大队长数据计算
     * 正确率：大队平均、站平均
     * 本大队正确率前三的主管
     * 全站排名：大队排名/全站大队数总和
     */
    private void calculateBrigadeLeaderData(AccuracyStatisticsDTO result, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 大队平均、站平均
        if (hierarchy.brigadeId != null) {
            result.setBrigadeAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.brigadeId, startDate, endDate));
        }
        if (hierarchy.stationId != null) {
            result.setSiteAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.stationId, startDate, endDate));
        }

        // 本大队正确率前三的主管
        if (hierarchy.brigadeId != null) {
            List<TeamAccuracyInfo> managersInBrigade = calculateManagerAccuraciesUnderBrigade(hierarchy.brigadeId, startDate, endDate);
            if (!managersInBrigade.isEmpty()) {
                List<AccuracyStatisticsDTO.RankingItem> topManagers = convertToRankingItems(managersInBrigade, 3, true);
                result.setTopKezhangInBrigade(topManagers);
            }
        }

        // 大队在全站中的排名
        if (hierarchy.brigadeId != null && hierarchy.stationId != null) {
            List<TeamAccuracyInfo> brigadesInStation = calculateBrigadeAccuraciesUnderStation(hierarchy.stationId, startDate, endDate);
            if (!brigadesInStation.isEmpty()) {
                result.setBrigadeInSiteRanking(findTeamRanking(hierarchy.brigadeId, brigadesInStation));
            }
        }
    }

    /**
     * 站长数据计算
     * 全站抽问抽答正确率
     * 一二三大队排名（大队正确率排名）
     * 主管正确率排名：正序前三名和倒序后三名
     * 班组正确率排名：正序前三名和倒序后三名
     */
    private void calculateStationLeaderData(AccuracyStatisticsDTO result, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 全站平均正确率
        if (hierarchy.stationId != null) {
            result.setSiteAvgAccuracy(calculateDeptAvgAccuracy(hierarchy.stationId, startDate, endDate));
        }

        // 大队正确率排名列表
        if (hierarchy.stationId != null) {
            List<TeamAccuracyInfo> brigadesInStation = calculateBrigadeAccuraciesUnderStation(hierarchy.stationId, startDate, endDate);
            if (!brigadesInStation.isEmpty()) {
                List<AccuracyStatisticsDTO.RankingItem> brigadeRankingList = new ArrayList<>();
                for (int i = 0; i < brigadesInStation.size(); i++) {
                    TeamAccuracyInfo info = brigadesInStation.get(i);
                    AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                    item.setId(info.deptId);
                    item.setName(info.deptName);
                    item.setAccuracy(info.accuracy);
                    item.setRank(i + 1);
                    brigadeRankingList.add(item);
                }
                result.setBrigadeRankingList(brigadeRankingList);
            }

            // 主管正确率排名：正序前三名和倒序后三名
            List<TeamAccuracyInfo> managersInStation = calculateManagerAccuraciesUnderStation(hierarchy.stationId, startDate, endDate);
            if (!managersInStation.isEmpty()) {
                result.setTopDepts(convertToManagerRankingItems(managersInStation, 3, true));
                result.setBottomDepts(convertToManagerRankingItems(managersInStation, 3, false));
            }

            // 班组正确率排名：正序前三名和倒序后三名
            List<TeamAccuracyInfo> teamsInStation = calculateTeamAccuraciesUnderDept(hierarchy.stationId, startDate, endDate);
            if (!teamsInStation.isEmpty()) {
                result.setTopTeamsInSite(convertToTeamRankingItemsWithBrigade(teamsInStation, 3, true));
                result.setBottomTeamsInSite(convertToTeamRankingItemsWithBrigade(teamsInStation, 3, false));
            }
        }
    }

    /**
     * 计算大队下所有主管的正确率（使用缓存和批量计算优化）
     */
    private List<TeamAccuracyInfo> calculateManagerAccuraciesUnderBrigade(Long brigadeId, Date startDate, Date endDate) {
        List<TeamAccuracyInfo> result = new ArrayList<>();
        DeptCache cache = getDeptCache();

        // 使用缓存的主管列表
        List<SysDept> managerDepts = cache != null ? cache.managerDepts : getManagerDeptsFromDb();

        // 收集大队下所有主管及其下属班组
        List<SysDept> managersInBrigade = new ArrayList<>();
        Map<Long, List<Long>> managerTeamIdsMap = new HashMap<>();
        List<Long> allTeamIds = new ArrayList<>();

        for (SysDept dept : managerDepts) {
            // 检查是否属于该大队
            if (brigadeId.equals(dept.getParentId())) {
                managersInBrigade.add(dept);
                DeptHierarchy h = cache != null ? cache.getHierarchy(dept.getDeptId()) : getDeptHierarchy(dept.getDeptId());
                List<Long> teamIds = getTeamIdsUnderDept(dept.getDeptId(), h);
                managerTeamIdsMap.put(dept.getDeptId(), teamIds);
                allTeamIds.addAll(teamIds);
            }
        }

        // 批量计算所有班组的正确率
        Map<Long, long[]> teamCountsMap = allTeamIds.isEmpty() ? new HashMap<>() : batchCalculateAccuracyCountsForTeams(allTeamIds, startDate, endDate);

        // 为每个主管汇总正确率
        for (SysDept dept : managersInBrigade) {
            TeamAccuracyInfo info = new TeamAccuracyInfo();
            info.deptId = dept.getDeptId();
            info.deptName = dept.getDeptName();

            List<Long> teamIds = managerTeamIdsMap.get(dept.getDeptId());
            long totalCorrect = 0;
            long totalCount = 0;

            if (teamIds != null && !teamIds.isEmpty()) {
                for (Long teamId : teamIds) {
                    long[] counts = teamCountsMap.getOrDefault(teamId, new long[]{0, 0});
                    totalCorrect += counts[0];
                    totalCount += counts[1];
                }
            }

            if (totalCount > 0) {
                info.accuracy = BigDecimal.valueOf(totalCorrect)
                        .multiply(BigDecimal.valueOf(100))
                        .divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP);
            } else {
                info.accuracy = BigDecimal.ZERO;
            }
            result.add(info);
        }

        // 按正确率降序排序
        result.sort((a, b) -> b.accuracy.compareTo(a.accuracy));

        return result;
    }

    /**
     * 从数据库获取主管部门列表（无缓存时使用）
     */
    private List<SysDept> getManagerDeptsFromDb() {
        List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());
        return allDepts.stream()
                .filter(d -> "0".equals(d.getDelFlag()) && StrUtil.equals(DeptType.MANAGER.getCode(), d.getDeptType()))
                .collect(Collectors.toList());
    }

    /**
     * 计算站级下所有大队的正确率（使用缓存和批量计算优化）
     */
    private List<TeamAccuracyInfo> calculateBrigadeAccuraciesUnderStation(Long stationId, Date startDate, Date endDate) {
        List<TeamAccuracyInfo> result = new ArrayList<>();

        // 使用缓存的大队列表
        DeptCache cache = getDeptCache();
        List<SysDept> brigadeDepts = cache != null ? cache.brigadeDepts : getBrigadeDeptsFromDb();

        // 收集站级下所有大队及其下属班组
        List<SysDept> brigadesInStation = new ArrayList<>();
        Map<Long, List<Long>> brigadeTeamIdsMap = new HashMap<>();
        List<Long> allTeamIds = new ArrayList<>();

        for (SysDept dept : brigadeDepts) {
            // 检查是否属于该站级
            if (stationId.equals(dept.getParentId())) {
                brigadesInStation.add(dept);
                DeptHierarchy h = cache != null ? cache.getHierarchy(dept.getDeptId()) : getDeptHierarchy(dept.getDeptId());
                List<Long> teamIds = getTeamIdsUnderDept(dept.getDeptId(), h);
                brigadeTeamIdsMap.put(dept.getDeptId(), teamIds);
                allTeamIds.addAll(teamIds);
            }
        }

        // 批量计算所有班组的正确率
        Map<Long, long[]> teamCountsMap = allTeamIds.isEmpty() ? new HashMap<>() : batchCalculateAccuracyCountsForTeams(allTeamIds, startDate, endDate);

        // 为每个大队汇总正确率
        for (SysDept dept : brigadesInStation) {
            TeamAccuracyInfo info = new TeamAccuracyInfo();
            info.deptId = dept.getDeptId();
            info.deptName = dept.getDeptName();

            List<Long> teamIds = brigadeTeamIdsMap.get(dept.getDeptId());
            long totalCorrect = 0;
            long totalCount = 0;

            if (teamIds != null && !teamIds.isEmpty()) {
                for (Long teamId : teamIds) {
                    long[] counts = teamCountsMap.getOrDefault(teamId, new long[]{0, 0});
                    totalCorrect += counts[0];
                    totalCount += counts[1];
                }
            }

            if (totalCount > 0) {
                info.accuracy = BigDecimal.valueOf(totalCorrect)
                        .multiply(BigDecimal.valueOf(100))
                        .divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP);
            } else {
                info.accuracy = BigDecimal.ZERO;
            }
            result.add(info);
        }

        // 按正确率降序排序
        result.sort((a, b) -> b.accuracy.compareTo(a.accuracy));

        return result;
    }

    /**
     * 从数据库获取大队部门列表（无缓存时使用）
     */
    private List<SysDept> getBrigadeDeptsFromDb() {
        List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());
        return allDepts.stream()
                .filter(d -> "0".equals(d.getDelFlag()) && StrUtil.equals(DeptType.BRIGADE.getCode(), d.getDeptType()))
                .collect(Collectors.toList());
    }

    /**
     * 将班组排名转换为带大队名称的格式
     */
    private List<AccuracyStatisticsDTO.RankingItem> convertToTeamRankingItems(List<TeamAccuracyInfo> rankings, int limit, boolean fromTop, Long brigadeId) {
        List<AccuracyStatisticsDTO.RankingItem> result = new ArrayList<>();

        if (rankings.isEmpty()) {
            return result;
        }

        int size = rankings.size();
        int actualLimit = Math.min(limit, size);

        if (fromTop) {
            for (int i = 0; i < actualLimit; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(info.deptName);
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        } else {
            for (int i = size - actualLimit; i < size; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(info.deptName);
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        }

        return result;
    }

    /**
     * 将班组排名转换为带大队名称的格式（站长视角）
     * 格式如"一大队张三班组"
     */
    private List<AccuracyStatisticsDTO.RankingItem> convertToTeamRankingItemsWithBrigade(List<TeamAccuracyInfo> rankings, int limit, boolean fromTop) {
        List<AccuracyStatisticsDTO.RankingItem> result = new ArrayList<>();

        if (rankings.isEmpty()) {
            return result;
        }

        int size = rankings.size();
        int actualLimit = Math.min(limit, size);

        if (fromTop) {
            for (int i = 0; i < actualLimit; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(getTeamDisplayNameWithBrigade(info.deptId, info.deptName));
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        } else {
            for (int i = size - actualLimit; i < size; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(getTeamDisplayNameWithBrigade(info.deptId, info.deptName));
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        }

        return result;
    }

    /**
     * 获取班组显示名称，格式为"大队名+班组名"，如"一大队张三班组"（使用缓存优化）
     */
    private String getTeamDisplayNameWithBrigade(Long teamId, String teamName) {
        DeptCache cache = getDeptCache();
        SysDept teamDept = cache != null ? cache.deptMap.get(teamId) : deptService.selectDeptById(teamId);
        if (teamDept == null) {
            return teamName;
        }
        // 获取班组所属的主管
        Long managerId = teamDept.getParentId();
        if (managerId != null) {
            SysDept managerDept = cache != null ? cache.deptMap.get(managerId) : deptService.selectDeptById(managerId);
            if (managerDept != null) {
                // 获取主管所属的大队
                Long brigadeId = managerDept.getParentId();
                if (brigadeId != null) {
                    SysDept brigadeDept = cache != null ? cache.deptMap.get(brigadeId) : deptService.selectDeptById(brigadeId);
                    if (brigadeDept != null && StrUtil.equals(DeptType.BRIGADE.getCode(), brigadeDept.getDeptType())) {
                        return brigadeDept.getDeptName() + teamName;
                    }
                }
            }
        }
        return teamName;
    }

    @Override
    public AccuracyStatisticsDTO getUserAccuracyStatistics(Long userId, AccuracyStatisticsQueryDTO query) {
        SysUser user = userService.selectUserById(userId);
        if (user == null) {
            return new AccuracyStatisticsDTO();
        }

        AccuracyStatisticsDTO result = new AccuracyStatisticsDTO();

        // 获取用户角色
        String roleKey = getUserRoleKey(user);
        if (user.getRoles() != null && !user.getRoles().isEmpty()) {
            result.setUserRole(user.getRoles().get(0).getRoleName());
        }

        // 解析时间范围
        Date[] dateRange = parseDateRange(query);
        Date startDate = dateRange[0];
        Date endDate = dateRange[1];

        // 设置时间范围描述
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (startDate != null && endDate != null) {
            result.setTimePeriod(sdf.format(startDate) + " ~ " + sdf.format(endDate));
        }

        // 获取部门层级信息
        DeptHierarchy hierarchy = getDeptHierarchy(user.getDeptId());

        // 检查是否有待完成任务
        checkPendingTask(result, userId);

        // 根据角色返回不同的数据
        if (RoleTypeEnum.SecurityCheck.getCode().equals(roleKey)) {
            // 安检员
            calculateSecurityCheckData(result, userId, hierarchy, startDate, endDate);
        } else if (RoleTypeEnum.banzuzhang.getCode().equals(roleKey)) {
            // 班组长（支持dataSource参数）
            calculateTeamLeaderData(result, userId, hierarchy, startDate, endDate, query);
        } else if (RoleTypeEnum.kezhang.getCode().equals(roleKey)) {
            // 主管
            calculateManagerData(result, userId, hierarchy, startDate, endDate);
        } else if (RoleTypeEnum.jingli.getCode().equals(roleKey) || RoleTypeEnum.xingzheng.getCode().equals(roleKey)) {
            // 大队长（经理/行政）
            calculateBrigadeLeaderData(result, hierarchy, startDate, endDate);
        } else if (RoleTypeEnum.test.getCode().equals(roleKey)) {
            // 站长
            calculateStationLeaderData(result, hierarchy, startDate, endDate);
        } else {
            // 其他角色：返回基本数据
            calculatePersonalAccuracy(result, userId, startDate, endDate);
            calculateLevelAvgAccuracy(result, hierarchy, startDate, endDate);
        }

        return result;
    }

    @Override
    public AccuracyAggregateStatisticsDTO getAggregateStatistics(AccuracyStatisticsQueryDTO query) {
        Date[] dateRange = parseDateRange(query);
        Date startDate = dateRange[0];
        Date endDate = dateRange[1];

        AccuracyAggregateStatisticsDTO result = new AccuracyAggregateStatisticsDTO();

        // 查询时间范围内所有已完成的任务
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        if (startDate != null) {
            taskWrapper.ge(DailyTask::getDtBusinessDate, startDate);
        }
        if (endDate != null) {
            taskWrapper.le(DailyTask::getDtBusinessDate, endDate);
        }
        taskWrapper.eq(DailyTask::getDtStatus, DailyTaskStatusEnum.COMPLETED.getCode());
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> allTasks = dailyTaskMapper.selectList(taskWrapper);

        // 统计总答题人数
        Set<Long> uniqueUsers = allTasks.stream()
                .map(DailyTask::getDtUserId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        result.setTotalUsers(uniqueUsers.size());

        // 获取所有任务的答题明细
        List<String> taskIds = allTasks.stream()
                .map(DailyTask::getDtId)
                .collect(Collectors.toList());

        if (!taskIds.isEmpty()) {
            LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
            detailWrapper.in(DailyTaskDetail::getDtdTaskId, taskIds);
            detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
            detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
            List<DailyTaskDetail> allDetails = dailyTaskDetailMapper.selectList(detailWrapper);

            result.setTotalAnswers((long) allDetails.size());
            long correctCount = allDetails.stream()
                    .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                    .count();
            result.setTotalCorrect(correctCount);

            if (!allDetails.isEmpty()) {
                result.setOverallAccuracyRate(
                        BigDecimal.valueOf(correctCount)
                                .multiply(BigDecimal.valueOf(100))
                                .divide(BigDecimal.valueOf(allDetails.size()), 2, RoundingMode.HALF_UP)
                );
            } else {
                result.setOverallAccuracyRate(BigDecimal.ZERO);
            }
        } else {
            result.setTotalAnswers(0L);
            result.setTotalCorrect(0L);
            result.setOverallAccuracyRate(BigDecimal.ZERO);
        }

        return result;
    }

    @Override
    public DailyTaskAccuracyRankingDto getAccuracyRanking(BaseLargeScreenQueryParamDto dto) {
        try {
            // 初始化部门缓存（整个请求中复用）
            initDeptCache();

            DailyTaskAccuracyRankingDto result = new DailyTaskAccuracyRankingDto();
            result.setTotal(0);
            result.setRank(0);

            // 解析日期范围
            Date startDate = dto.getStartDate();
            Date endDate = dto.getEndDate();
            if (endDate != null) {
                endDate = DateUtils.addSeconds(DateUtils.truncate(endDate, Calendar.DAY_OF_MONTH), 86399);
            }

            // 处理用户排名（userId不为空时）
            if (dto.getUserId() != null) {
                return getUserAccuracyRanking(dto.getUserId(), startDate, endDate);
            }

            // 处理部门排名（deptId不为空时，支持dataSource参数）
            if (dto.getDeptId() != null) {
                return getDeptAccuracyRanking(dto.getDeptId(), dto.getDataSource(), startDate, endDate);
            }

            // 默认：获取当前用户的排名
            Long currentUserId = SecurityUtils.getUserId();
            return getUserAccuracyRanking(currentUserId, startDate, endDate);

        } finally {
            // 清理缓存，避免内存泄漏
            clearDeptCache();
        }
    }

    /**
     * 获取用户的正确率排名
     */
    private DailyTaskAccuracyRankingDto getUserAccuracyRanking(Long userId, Date startDate, Date endDate) {
        DailyTaskAccuracyRankingDto result = new DailyTaskAccuracyRankingDto();

        SysUser user = userService.selectUserById(userId);
        if (user == null) {
            result.setTotal(0);
            result.setRank(0);
            return result;
        }

        // 获取用户的部门层级
        DeptHierarchy hierarchy = getDeptHierarchyCached(user.getDeptId());

        // 获取同级别的所有用户正确率排名
        List<UserAccuracyInfo> userRankings = calculateUserRankingsInScope(hierarchy, startDate, endDate);

        // 设置排名列表
        List<DailyTaskAccuracyRankingItemDto> rankingList = new ArrayList<>();
        int rank = 1;
        for (UserAccuracyInfo info : userRankings) {
            DailyTaskAccuracyRankingItemDto item = new DailyTaskAccuracyRankingItemDto();
            item.setId(info.userId);
            item.setName(info.userName);
            item.setAccuracyRate(info.accuracy);
            item.setRank(rank);
            rankingList.add(item);
            rank++;
        }
        result.setRankingList(rankingList);

        // 找到当前用户的排名
        int currentUserRank = 0;
        BigDecimal currentUserAccuracy = BigDecimal.ZERO;
        for (int i = 0; i < userRankings.size(); i++) {
            if (userId.equals(userRankings.get(i).userId)) {
                currentUserRank = i + 1;
                currentUserAccuracy = userRankings.get(i).accuracy;
                break;
            }
        }

        result.setId(userId);
        result.setName(user.getNickName());

        // 如果找不到当前用户，说明该用户没有答题记录，排在最后（正确率为0）
        if (currentUserRank == 0) {
            currentUserRank = userRankings.size() + 1;
            result.setRank(currentUserRank);
            result.setTotal(userRankings.size() + 1);
        } else {
            result.setRank(currentUserRank);
            result.setTotal(userRankings.size());
        }
        result.setAccuracyRate(currentUserAccuracy);

        // 设置奖牌类型
        if (userRankings.size() > 0 && currentUserRank > 0) {
            MedalTypeEnum medalType = calculateMedalType(currentUserRank, userRankings.size());
            result.setMedalType(medalType.getCode());
            result.setMedalTypeDesc(medalType.getDesc());
        }

        return result;
    }

    /**
     * 获取部门的正确率排名（支持dataSource参数，适配美兰4级组织结构）
     * dataSource=individual时：
     * - 班组(TEAMS)：返回班组长的个人排名
     * - 主管(MANAGER)：返回主管在大队中的排名
     * - 大队(BRIGADE)：返回大队在站级中的排名
     * - 站级(STATION)：返回站级数据
     * dataSource=team或空时：返回部门排名（默认）
     */
    private DailyTaskAccuracyRankingDto getDeptAccuracyRanking(Long deptId, String dataSource, Date startDate, Date endDate) {
        DailyTaskAccuracyRankingDto result = new DailyTaskAccuracyRankingDto();
        result.setTotal(0);
        result.setRank(0);

        DeptCache cache = getDeptCache();
        SysDept sysDept = cache != null ? cache.deptMap.get(deptId) : deptService.selectDeptById(deptId);
        if (sysDept == null) {
            log.warn("部门{}不存在，返回空结果", deptId);
            return result;
        }

        String deptType = sysDept.getDeptType();
        DeptHierarchy hierarchy = getDeptHierarchyCached(deptId);

        // 处理dataSource=individual的情况
        if ("individual".equalsIgnoreCase(dataSource)) {
            if (StrUtil.equals(DeptType.TEAMS.getCode(), deptType)) {
                // 班组：获取班组长的个人排名
                Long teamLeaderId = getTeamLeaderId(deptId);
                if (teamLeaderId != null) {
                    log.info("班组{}，dataSource=individual，返回班组长{}的个人排名", deptId, teamLeaderId);
                    return getUserAccuracyRanking(teamLeaderId, startDate, endDate);
                } else {
                    log.warn("未找到班组{}的班组长，返回空结果", deptId);
                    return result;
                }
            } else if (StrUtil.equals(DeptType.MANAGER.getCode(), deptType)) {
                // 主管：返回主管在大队中的排名
                log.info("主管{}，dataSource=individual，返回主管在大队中的排名", deptId);
                return getManagerInBrigadeRanking(sysDept, hierarchy, startDate, endDate);
            } else if (StrUtil.equals(DeptType.BRIGADE.getCode(), deptType)) {
                // 大队：返回大队在站级中的排名
                log.info("大队{}，dataSource=individual，返回大队在站级中的排名", deptId);
                return getBrigadeInStationRanking(sysDept, hierarchy, startDate, endDate);
            } else if (StrUtil.equals(DeptType.STATION.getCode(), deptType)) {
                // 站级：返回站级数据
                log.info("站级{}，dataSource=individual，返回站级数据", deptId);
                result.setId(sysDept.getDeptId());
                result.setName(sysDept.getDeptName());
                BigDecimal accuracy = calculateDeptAvgAccuracy(deptId, startDate, endDate);
                result.setAccuracyRate(accuracy);
                result.setRank(1);
                result.setTotal(1);
                return result;
            }
        }

        // 默认：返回部门排名（dataSource=team或未指定）
        log.info("dataSource={}，返回部门排名", dataSource);
        return getDeptDefaultRanking(sysDept, hierarchy, startDate, endDate);
    }

    /**
     * 获取班组的班组长userId
     */
    private Long getTeamLeaderId(Long teamDeptId) {
        List<SysUser> users = userService.selectUserListByRoleKeyAndDeptId(
                Collections.singletonList(RoleTypeEnum.banzuzhang.getCode()), teamDeptId);
        if (users != null && !users.isEmpty()) {
            return users.get(0).getUserId();
        }
        return null;
    }

    /**
     * 获取主管在大队中的排名
     */
    private DailyTaskAccuracyRankingDto getManagerInBrigadeRanking(SysDept managerDept, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        DailyTaskAccuracyRankingDto result = new DailyTaskAccuracyRankingDto();
        result.setId(managerDept.getDeptId());
        result.setName(managerDept.getDeptName());

        if (hierarchy.brigadeId == null) {
            result.setRank(1);
            result.setTotal(1);
            result.setAccuracyRate(calculateDeptAvgAccuracy(managerDept.getDeptId(), startDate, endDate));
            return result;
        }

        // 获取大队下所有主管的排名
        List<TeamAccuracyInfo> managersInBrigade = calculateManagerAccuraciesUnderBrigade(hierarchy.brigadeId, startDate, endDate);

        // 设置排名列表
        List<DailyTaskAccuracyRankingItemDto> rankingList = new ArrayList<>();
        for (int i = 0; i < managersInBrigade.size(); i++) {
            TeamAccuracyInfo info = managersInBrigade.get(i);
            DailyTaskAccuracyRankingItemDto item = new DailyTaskAccuracyRankingItemDto();
            item.setId(info.deptId);
            item.setName(info.deptName);
            item.setAccuracyRate(info.accuracy);
            item.setRank(i + 1);
            rankingList.add(item);
        }
        result.setRankingList(rankingList);

        // 查找当前主管的排名
        AccuracyStatisticsDTO.RankingInfo rankingInfo = findTeamRanking(managerDept.getDeptId(), managersInBrigade);
        result.setRank(rankingInfo.getRank());
        result.setTotal(rankingInfo.getTotal());

        // 设置正确率
        BigDecimal accuracy = calculateDeptAvgAccuracy(managerDept.getDeptId(), startDate, endDate);
        result.setAccuracyRate(accuracy);

        // 设置奖牌类型
        if (rankingInfo.getTotal() > 0 && rankingInfo.getRank() > 0) {
            MedalTypeEnum medalType = calculateMedalType(rankingInfo.getRank(), rankingInfo.getTotal());
            result.setMedalType(medalType.getCode());
            result.setMedalTypeDesc(medalType.getDesc());
        }

        return result;
    }

    /**
     * 获取大队在站级中的排名
     */
    private DailyTaskAccuracyRankingDto getBrigadeInStationRanking(SysDept brigadeDept, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        DailyTaskAccuracyRankingDto result = new DailyTaskAccuracyRankingDto();
        result.setId(brigadeDept.getDeptId());
        result.setName(brigadeDept.getDeptName());

        if (hierarchy.stationId == null) {
            result.setRank(1);
            result.setTotal(1);
            result.setAccuracyRate(calculateDeptAvgAccuracy(brigadeDept.getDeptId(), startDate, endDate));
            return result;
        }

        // 获取站级下所有大队的排名
        List<TeamAccuracyInfo> brigadesInStation = calculateBrigadeAccuraciesUnderStation(hierarchy.stationId, startDate, endDate);

        // 设置排名列表
        List<DailyTaskAccuracyRankingItemDto> rankingList = new ArrayList<>();
        for (int i = 0; i < brigadesInStation.size(); i++) {
            TeamAccuracyInfo info = brigadesInStation.get(i);
            DailyTaskAccuracyRankingItemDto item = new DailyTaskAccuracyRankingItemDto();
            item.setId(info.deptId);
            item.setName(info.deptName);
            item.setAccuracyRate(info.accuracy);
            item.setRank(i + 1);
            rankingList.add(item);
        }
        result.setRankingList(rankingList);

        // 查找当前大队的排名
        AccuracyStatisticsDTO.RankingInfo rankingInfo = findTeamRanking(brigadeDept.getDeptId(), brigadesInStation);
        result.setRank(rankingInfo.getRank());
        result.setTotal(rankingInfo.getTotal());

        // 设置正确率
        BigDecimal accuracy = calculateDeptAvgAccuracy(brigadeDept.getDeptId(), startDate, endDate);
        result.setAccuracyRate(accuracy);

        // 设置奖牌类型
        if (rankingInfo.getTotal() > 0 && rankingInfo.getRank() > 0) {
            MedalTypeEnum medalType = calculateMedalType(rankingInfo.getRank(), rankingInfo.getTotal());
            result.setMedalType(medalType.getCode());
            result.setMedalTypeDesc(medalType.getDesc());
        }

        return result;
    }

    /**
     * 获取部门的默认排名（班组在主管中的排名）
     */
    private DailyTaskAccuracyRankingDto getDeptDefaultRanking(SysDept dept, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        DailyTaskAccuracyRankingDto result = new DailyTaskAccuracyRankingDto();
        result.setId(dept.getDeptId());
        result.setName(dept.getDeptName());

        String deptType = dept.getDeptType();

        if (StrUtil.equals(DeptType.TEAMS.getCode(), deptType)) {
            // 班组：返回班组在主管中的排名
            if (hierarchy.managerId != null) {
                List<TeamAccuracyInfo> teamsInManager = calculateTeamAccuraciesUnderDept(hierarchy.managerId, startDate, endDate);

                // 设置排名列表
                List<DailyTaskAccuracyRankingItemDto> rankingList = new ArrayList<>();
                for (int i = 0; i < teamsInManager.size(); i++) {
                    TeamAccuracyInfo info = teamsInManager.get(i);
                    DailyTaskAccuracyRankingItemDto item = new DailyTaskAccuracyRankingItemDto();
                    item.setId(info.deptId);
                    item.setName(info.deptName);
                    item.setAccuracyRate(info.accuracy);
                    item.setRank(i + 1);
                    rankingList.add(item);
                }
                result.setRankingList(rankingList);

                AccuracyStatisticsDTO.RankingInfo rankingInfo = findTeamRanking(dept.getDeptId(), teamsInManager);
                result.setRank(rankingInfo.getRank());
                result.setTotal(rankingInfo.getTotal());
            } else {
                result.setRank(1);
                result.setTotal(1);
            }
        } else if (StrUtil.equals(DeptType.MANAGER.getCode(), deptType)) {
            // 主管：返回主管在大队中的排名
            return getManagerInBrigadeRanking(dept, hierarchy, startDate, endDate);
        } else if (StrUtil.equals(DeptType.BRIGADE.getCode(), deptType)) {
            // 大队：返回大队在站级中的排名
            return getBrigadeInStationRanking(dept, hierarchy, startDate, endDate);
        } else {
            // 站级
            result.setRank(1);
            result.setTotal(1);
        }

        // 设置正确率
        BigDecimal accuracy = calculateDeptAvgAccuracy(dept.getDeptId(), startDate, endDate);
        result.setAccuracyRate(accuracy);

        // 设置奖牌类型
        if (result.getTotal() > 0 && result.getRank() > 0) {
            MedalTypeEnum medalType = calculateMedalType(result.getRank(), result.getTotal());
            result.setMedalType(medalType.getCode());
            result.setMedalTypeDesc(medalType.getDesc());
        }

        return result;
    }

    @Override
    public BigDecimal getAccuracyRate(Long userId, Long deptId, Date startDate, Date endDate) {
        if (userId != null) {
            // 用户维度
            long[] counts = calculateAccuracyCounts(userId, null, startDate, endDate);
            if (counts[1] > 0) {
                return BigDecimal.valueOf(counts[0])
                        .divide(BigDecimal.valueOf(counts[1]), 4, RoundingMode.HALF_UP);
            }
        } else if (deptId != null) {
            // 部门维度
            DeptHierarchy hierarchy = getDeptHierarchyCached(deptId);
            List<Long> teamIds = getTeamIdsUnderDept(deptId, hierarchy);
            long[] counts = calculateAccuracyCountsForTeams(teamIds, startDate, endDate);
            if (counts[1] > 0) {
                return BigDecimal.valueOf(counts[0])
                        .divide(BigDecimal.valueOf(counts[1]), 4, RoundingMode.HALF_UP);
            }
        }
        return BigDecimal.ZERO;
    }

    @Override
    public SysHomeReportDetailDto answerData(BaseLargeScreenQueryParamDto dto) {
        if (ObjectUtil.isNull(dto.getUserId()) && ObjectUtil.isNull(dto.getDeptId())) {
            throw new ServiceException("用户ID和部门ID不能同时为空");
        }
        // 默认筛选条件：最近一年
        if (ObjectUtil.isNull(dto.getStartDate()) && ObjectUtil.isNull(dto.getEndDate()) && ObjectUtil.isNull(dto.getSpecifiedDate())) {
            Calendar cal = Calendar.getInstance();
            dto.setEndDate(cal.getTime());
            cal.add(Calendar.YEAR, -1);
            dto.setStartDate(cal.getTime());
        }

        SysHomeReportDetailDto result = new SysHomeReportDetailDto();

        // 设置基本信息
        if (ObjectUtil.isNotNull(dto.getUserId())) {
            SysUser sysUser = userService.selectUserById(dto.getUserId());
            if (ObjectUtil.isNull(sysUser)) {
                throw new ServiceException("【" + dto.getUserId() + "】用户不存在");
            }
            result.setId(sysUser.getUserId());
            result.setName(sysUser.getNickName());
            result.setType(HomePageQueryEnum.USER.getCode());
        } else {
            DeptCache cache = getDeptCache();
            SysDept sysDept = cache != null ? cache.deptMap.get(dto.getDeptId()) : deptService.selectDeptById(dto.getDeptId());
            if (ObjectUtil.isNull(sysDept)) {
                throw new ServiceException("【" + dto.getDeptId() + "】部门不存在");
            }
            result.setId(sysDept.getDeptId());
            result.setName(sysDept.getDeptName());
            result.setType(HomePageQueryEnum.DEPT.getCode());
        }

        // 获取正确率列表
        List<BigDecimal> accuracyRates = getAccuracyRatesForReport(dto);

        if (accuracyRates.isEmpty()) {
            result.setMaxNumber(BigDecimal.ZERO);
            result.setMinNumber(BigDecimal.ZERO);
            result.setAverageNumber(BigDecimal.ZERO);
            result.setMedianNumber(BigDecimal.ZERO);
            return result;
        }

        // 排序
        accuracyRates.sort(BigDecimal::compareTo);

        // 最大值（转换为百分比）
        result.setMaxNumber(accuracyRates.get(accuracyRates.size() - 1).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        // 最小值（转换为百分比）
        result.setMinNumber(accuracyRates.get(0).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));
        // 平均值
        BigDecimal sum = accuracyRates.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        result.setAverageNumber(sum.multiply(BigDecimal.valueOf(100)).divide(BigDecimal.valueOf(accuracyRates.size()), 2, RoundingMode.HALF_UP));
        // 中位数
        int size = accuracyRates.size();
        int middle = size / 2;
        BigDecimal median;
        if (size % 2 == 1) {
            median = accuracyRates.get(middle);
        } else {
            median = accuracyRates.get(middle - 1).add(accuracyRates.get(middle)).divide(BigDecimal.valueOf(2), 4, RoundingMode.HALF_UP);
        }
        result.setMedianNumber(median.multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP));

        return result;
    }

    /**
     * 获取用于报表统计的正确率列表
     */
    private List<BigDecimal> getAccuracyRatesForReport(BaseLargeScreenQueryParamDto dto) {
        List<BigDecimal> result = new ArrayList<>();

        if (ObjectUtil.isNotNull(dto.getUserId())) {
            // 用户维度：获取用户在时间范围内每次答题的正确率
            LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
            taskWrapper.eq(DailyTask::getDtUserId, dto.getUserId());
            taskWrapper.eq(DailyTask::getDtStatus, DailyTaskStatusEnum.COMPLETED.getCode());
            taskWrapper.eq(DailyTask::getDelStatus, 0);
            if (dto.getStartDate() != null) {
                taskWrapper.ge(DailyTask::getDtBusinessDate, dto.getStartDate());
            }
            if (dto.getEndDate() != null) {
                taskWrapper.le(DailyTask::getDtBusinessDate, dto.getEndDate());
            }
            List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

            for (DailyTask task : tasks) {
                LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
                detailWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
                detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
                List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(detailWrapper);

                if (!details.isEmpty()) {
                    long correctCount = details.stream().filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect())).count();
                    BigDecimal accuracy = BigDecimal.valueOf(correctCount).divide(BigDecimal.valueOf(details.size()), 4, RoundingMode.HALF_UP);
                    result.add(accuracy);
                }
            }
        } else if (ObjectUtil.isNotNull(dto.getDeptId())) {
            // 部门维度：获取部门下所有用户的正确率
            DeptCache cache = getDeptCache();
            SysDept sysDept = cache != null ? cache.deptMap.get(dto.getDeptId()) : deptService.selectDeptById(dto.getDeptId());
            if (sysDept == null) {
                return result;
            }

            DeptHierarchy hierarchy = getDeptHierarchyCached(dto.getDeptId());
            List<Long> teamIds = getTeamIdsUnderDept(dto.getDeptId(), hierarchy);

            if (teamIds.isEmpty()) {
                return result;
            }

            // 获取这些班组下所有用户的正确率
            List<UserAccuracyInfo> userAccuracies = calculateUserAccuraciesInTeams(teamIds, dto.getStartDate(), dto.getEndDate());

            for (UserAccuracyInfo info : userAccuracies) {
                // userAccuracies 中的 accuracy 已经是百分比形式，需要转回小数
                result.add(info.accuracy.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
            }
        }

        return result;
    }

    /**
     * 检查是否有待完成任务
     */
    private void checkPendingTask(AccuracyStatisticsDTO result, Long userId) {
        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DailyTask::getDtUserId, userId);
        wrapper.in(DailyTask::getDtStatus, DailyTaskStatusEnum.PENDING.getCode(), DailyTaskStatusEnum.IN_PROGRESS.getCode());
        wrapper.eq(DailyTask::getDelStatus, 0);
        wrapper.orderByDesc(DailyTask::getCreateTime);
        wrapper.last("LIMIT 1");
        DailyTask pendingTask = dailyTaskMapper.selectOne(wrapper);

        if (pendingTask != null) {
            result.setHasPendingTask(true);
            result.setPendingTaskId(pendingTask.getDtId());
        } else {
            result.setHasPendingTask(false);
        }
    }

    /**
     * 计算个人正确率
     */
    private void calculatePersonalAccuracy(AccuracyStatisticsDTO result, Long userId, Date startDate, Date endDate) {
        long[] counts = calculateAccuracyCounts(userId, null, startDate, endDate);
        result.setPersonalCorrectCount(counts[0]);
        result.setPersonalTotalCount(counts[1]);

        if (counts[1] > 0) {
            result.setPersonalAccuracy(
                    BigDecimal.valueOf(counts[0])
                            .multiply(BigDecimal.valueOf(100))
                            .divide(BigDecimal.valueOf(counts[1]), 2, RoundingMode.HALF_UP)
            );
        } else {
            result.setPersonalAccuracy(BigDecimal.ZERO);
        }
    }

    /**
     * 计算各层级平均正确率
     */
    private void calculateLevelAvgAccuracy(AccuracyStatisticsDTO result, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 班组平均正确率
        if (hierarchy.teamId != null) {
            BigDecimal teamAvg = calculateDeptAvgAccuracy(hierarchy.teamId, startDate, endDate);
            result.setTeamAvgAccuracy(teamAvg);
        }

        // 主管平均正确率
        if (hierarchy.managerId != null) {
            BigDecimal managerAvg = calculateDeptAvgAccuracy(hierarchy.managerId, startDate, endDate);
            result.setDeptAvgAccuracy(managerAvg);
        }

        // 大队平均正确率（美兰特有）
        if (hierarchy.brigadeId != null) {
            BigDecimal brigadeAvg = calculateDeptAvgAccuracy(hierarchy.brigadeId, startDate, endDate);
            result.setBrigadeAvgAccuracy(brigadeAvg);
        }

        // 站级平均正确率
        if (hierarchy.stationId != null) {
            BigDecimal stationAvg = calculateDeptAvgAccuracy(hierarchy.stationId, startDate, endDate);
            result.setSiteAvgAccuracy(stationAvg);
        }
    }

    /**
     * 计算部门平均正确率（使用缓存优化）
     */
    private BigDecimal calculateDeptAvgAccuracy(Long deptId, Date startDate, Date endDate) {
        DeptHierarchy hierarchy = getDeptHierarchyCached(deptId);
        List<Long> teamIds = getTeamIdsUnderDept(deptId, hierarchy);

        if (teamIds.isEmpty()) {
            return BigDecimal.ZERO;
        }

        long[] counts = calculateAccuracyCountsForTeams(teamIds, startDate, endDate);
        if (counts[1] > 0) {
            return BigDecimal.valueOf(counts[0])
                    .multiply(BigDecimal.valueOf(100))
                    .divide(BigDecimal.valueOf(counts[1]), 2, RoundingMode.HALF_UP);
        }
        return BigDecimal.ZERO;
    }

    /**
     * 计算个人在各层级的排名
     */
    private void calculatePersonalRankings(AccuracyStatisticsDTO result, Long userId, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 班组内排名
        if (hierarchy.teamId != null) {
            AccuracyStatisticsDTO.RankingInfo teamRanking = calculateUserRankingInDept(userId, hierarchy.teamId, startDate, endDate);
            result.setTeamRanking(teamRanking);
        }

        // 主管内排名
        if (hierarchy.managerId != null) {
            AccuracyStatisticsDTO.RankingInfo deptRanking = calculateUserRankingInDept(userId, hierarchy.managerId, startDate, endDate);
            result.setDeptRanking(deptRanking);
        }

        // 大队内排名
        if (hierarchy.brigadeId != null) {
            AccuracyStatisticsDTO.RankingInfo brigadeRanking = calculateUserRankingInDept(userId, hierarchy.brigadeId, startDate, endDate);
            result.setBrigadeRanking(brigadeRanking);
        }

        // 站级内排名
        if (hierarchy.stationId != null) {
            AccuracyStatisticsDTO.RankingInfo siteRanking = calculateUserRankingInDept(userId, hierarchy.stationId, startDate, endDate);
            result.setSiteRanking(siteRanking);
        }
    }

    /**
     * 计算用户在指定部门范围内的排名（使用缓存优化）
     * 如果用户没有答题记录，将其视为正确率0排在最后
     */
    private AccuracyStatisticsDTO.RankingInfo calculateUserRankingInDept(Long userId, Long deptId, Date startDate, Date endDate) {
        DeptHierarchy hierarchy = getDeptHierarchyCached(deptId);
        List<Long> teamIds = getTeamIdsUnderDept(deptId, hierarchy);

        AccuracyStatisticsDTO.RankingInfo rankingInfo = new AccuracyStatisticsDTO.RankingInfo();

        if (teamIds.isEmpty()) {
            rankingInfo.setRank(1);
            rankingInfo.setTotal(1);
            return rankingInfo;
        }

        // 获取这些班组下所有用户的正确率
        List<UserAccuracyInfo> userAccuracies = calculateUserAccuraciesInTeams(teamIds, startDate, endDate);

        if (userAccuracies.isEmpty()) {
            // 没有任何人答题，当前用户排第1
            rankingInfo.setRank(1);
            rankingInfo.setTotal(1);
            return rankingInfo;
        }

        // 按正确率降序排序
        userAccuracies.sort((a, b) -> b.accuracy.compareTo(a.accuracy));

        // 找到当前用户的排名
        int rank = 0;
        for (int i = 0; i < userAccuracies.size(); i++) {
            if (userId.equals(userAccuracies.get(i).userId)) {
                rank = i + 1;
                break;
            }
        }

        // 如果找不到当前用户，说明该用户没有答题记录，排在最后（正确率为0）
        if (rank == 0) {
            rank = userAccuracies.size() + 1;
            rankingInfo.setRank(rank);
            rankingInfo.setTotal(userAccuracies.size() + 1);
        } else {
            rankingInfo.setRank(rank);
            rankingInfo.setTotal(userAccuracies.size());
        }
        return rankingInfo;
    }

    /**
     * 计算指定班组下所有用户的正确率
     */
    private List<UserAccuracyInfo> calculateUserAccuraciesInTeams(List<Long> teamIds, Date startDate, Date endDate) {
        List<UserAccuracyInfo> result = new ArrayList<>();

        // 查询这些班组在时间范围内的已完成任务
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.in(DailyTask::getDtDeptId, teamIds);
        taskWrapper.eq(DailyTask::getDtStatus, DailyTaskStatusEnum.COMPLETED.getCode());
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        if (startDate != null) {
            taskWrapper.ge(DailyTask::getDtBusinessDate, startDate);
        }
        if (endDate != null) {
            taskWrapper.le(DailyTask::getDtBusinessDate, endDate);
        }
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

        if (tasks.isEmpty()) {
            return result;
        }

        // 按用户分组
        Map<Long, List<DailyTask>> userTasksMap = tasks.stream()
                .filter(t -> t.getDtUserId() != null)
                .collect(Collectors.groupingBy(DailyTask::getDtUserId));

        // 获取所有任务ID
        List<String> allTaskIds = tasks.stream()
                .map(DailyTask::getDtId)
                .collect(Collectors.toList());

        // 批量查询所有任务明细
        LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.in(DailyTaskDetail::getDtdTaskId, allTaskIds);
        detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
        detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
        List<DailyTaskDetail> allDetails = dailyTaskDetailMapper.selectList(detailWrapper);

        // 按任务ID分组明细
        Map<String, List<DailyTaskDetail>> taskDetailsMap = allDetails.stream()
                .collect(Collectors.groupingBy(DailyTaskDetail::getDtdTaskId));

        // 计算每个用户的正确率
        for (Map.Entry<Long, List<DailyTask>> entry : userTasksMap.entrySet()) {
            Long userId = entry.getKey();
            List<DailyTask> userTasks = entry.getValue();

            // 获取用户的所有答题明细
            long totalAnswers = 0;
            long correctAnswers = 0;
            for (DailyTask task : userTasks) {
                List<DailyTaskDetail> taskDetails = taskDetailsMap.get(task.getDtId());
                if (taskDetails != null) {
                    totalAnswers += taskDetails.size();
                    correctAnswers += taskDetails.stream()
                            .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                            .count();
                }
            }

            if (totalAnswers > 0) {
                UserAccuracyInfo info = new UserAccuracyInfo();
                info.userId = userId;
                info.userName = userTasks.get(0).getDtUserName();
                info.accuracy = BigDecimal.valueOf(correctAnswers)
                        .multiply(BigDecimal.valueOf(100))
                        .divide(BigDecimal.valueOf(totalAnswers), 2, RoundingMode.HALF_UP);
                result.add(info);
            }
        }

        return result;
    }

    /**
     * 计算正确率数量 [正确数, 总数]
     */
    private long[] calculateAccuracyCounts(Long userId, Long deptId, Date startDate, Date endDate) {
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        if (userId != null) {
            taskWrapper.eq(DailyTask::getDtUserId, userId);
        }
        if (deptId != null) {
            taskWrapper.eq(DailyTask::getDtDeptId, deptId);
        }
        taskWrapper.eq(DailyTask::getDtStatus, DailyTaskStatusEnum.COMPLETED.getCode());
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        if (startDate != null) {
            taskWrapper.ge(DailyTask::getDtBusinessDate, startDate);
        }
        if (endDate != null) {
            taskWrapper.le(DailyTask::getDtBusinessDate, endDate);
        }
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

        if (tasks.isEmpty()) {
            return new long[]{0, 0};
        }

        List<String> taskIds = tasks.stream()
                .map(DailyTask::getDtId)
                .collect(Collectors.toList());

        LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.in(DailyTaskDetail::getDtdTaskId, taskIds);
        detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
        detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
        List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(detailWrapper);

        long totalAnswers = details.size();
        long correctAnswers = details.stream()
                .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                .count();

        return new long[]{correctAnswers, totalAnswers};
    }

    /**
     * 计算多个班组的正确率数量
     */
    private long[] calculateAccuracyCountsForTeams(List<Long> teamIds, Date startDate, Date endDate) {
        if (teamIds.isEmpty()) {
            return new long[]{0, 0};
        }

        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.in(DailyTask::getDtDeptId, teamIds);
        taskWrapper.eq(DailyTask::getDtStatus, DailyTaskStatusEnum.COMPLETED.getCode());
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        if (startDate != null) {
            taskWrapper.ge(DailyTask::getDtBusinessDate, startDate);
        }
        if (endDate != null) {
            taskWrapper.le(DailyTask::getDtBusinessDate, endDate);
        }
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

        if (tasks.isEmpty()) {
            return new long[]{0, 0};
        }

        List<String> taskIds = tasks.stream()
                .map(DailyTask::getDtId)
                .collect(Collectors.toList());

        LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.in(DailyTaskDetail::getDtdTaskId, taskIds);
        detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
        detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
        List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(detailWrapper);

        long totalAnswers = details.size();
        long correctAnswers = details.stream()
                .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                .count();

        return new long[]{correctAnswers, totalAnswers};
    }

    /**
     * 获取部门下所有班组ID（使用缓存优化）
     */
    private List<Long> getTeamIdsUnderDept(Long deptId, DeptHierarchy hierarchy) {
        List<Long> teamIds = new ArrayList<>();
        DeptCache cache = getDeptCache();

        // 优先使用缓存
        SysDept dept = cache != null ? cache.deptMap.get(deptId) : deptService.selectDeptById(deptId);
        if (dept == null) {
            log.warn("getTeamIdsUnderDept: dept not found for deptId={}", deptId);
            return teamIds;
        }

        String deptType = dept.getDeptType();

        if (StrUtil.equals(DeptType.TEAMS.getCode(), deptType)) {
            // 已经是班组，直接返回
            teamIds.add(deptId);
        } else if (cache != null) {
            // 使用缓存的班组列表（性能优化核心）
            for (SysDept d : cache.teamDepts) {
                DeptHierarchy h = cache.getHierarchy(d.getDeptId());
                boolean match = false;

                if (StrUtil.equals(DeptType.STATION.getCode(), deptType)) {
                    match = deptId.equals(h.stationId);
                } else if (StrUtil.equals(DeptType.BRIGADE.getCode(), deptType)) {
                    match = deptId.equals(h.brigadeId);
                } else if (StrUtil.equals(DeptType.MANAGER.getCode(), deptType)) {
                    match = deptId.equals(h.managerId);
                }

                if (match) {
                    teamIds.add(d.getDeptId());
                }
            }
        } else {
            // 无缓存时的原始逻辑
            List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());
            for (SysDept d : allDepts) {
                if (!"0".equals(d.getDelFlag())) continue;
                if (!StrUtil.equals(DeptType.TEAMS.getCode(), d.getDeptType())) continue;

                DeptHierarchy h = getDeptHierarchy(d.getDeptId());
                boolean match = false;

                if (StrUtil.equals(DeptType.STATION.getCode(), deptType)) {
                    match = deptId.equals(h.stationId);
                } else if (StrUtil.equals(DeptType.BRIGADE.getCode(), deptType)) {
                    match = deptId.equals(h.brigadeId);
                } else if (StrUtil.equals(DeptType.MANAGER.getCode(), deptType)) {
                    match = deptId.equals(h.managerId);
                }

                if (match) {
                    teamIds.add(d.getDeptId());
                }
            }
        }

        return teamIds;
    }

    /**
     * 计算指定范围内所有用户的正确率排名（用于首页排名，使用缓存优化）
     */
    private List<UserAccuracyInfo> calculateUserRankingsInScope(DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 获取该层级下所有班组ID
        List<Long> teamIds = new ArrayList<>();
        DeptCache cache = getDeptCache();

        if (hierarchy.stationId != null) {
            // 优先使用缓存
            if (cache != null) {
                for (SysDept dept : cache.teamDepts) {
                    DeptHierarchy deptHierarchy = cache.getHierarchy(dept.getDeptId());
                    if (hierarchy.stationId.equals(deptHierarchy.stationId)) {
                        teamIds.add(dept.getDeptId());
                    }
                }
            } else {
                // 无缓存时查询数据库
                List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());
                for (SysDept dept : allDepts) {
                    if (!"0".equals(dept.getDelFlag())) {
                        continue;
                    }
                    if (!StrUtil.equals(DeptType.TEAMS.getCode(), dept.getDeptType())) {
                        continue;
                    }

                    DeptHierarchy deptHierarchy = getDeptHierarchy(dept.getDeptId());
                    if (hierarchy.stationId.equals(deptHierarchy.stationId)) {
                        teamIds.add(dept.getDeptId());
                    }
                }
            }
        }

        if (teamIds.isEmpty()) {
            return new ArrayList<>();
        }

        List<UserAccuracyInfo> userAccuracies = calculateUserAccuraciesInTeams(teamIds, startDate, endDate);
        // 按正确率降序排序
        userAccuracies.sort((a, b) -> b.accuracy.compareTo(a.accuracy));

        return userAccuracies;
    }

    /**
     * 解析部门层级 - 适配美兰4级架构
     * ancestors结构：0,站级ID,大队ID,主管ID
     */
    private DeptHierarchy getDeptHierarchy(Long deptId) {
        DeptHierarchy hierarchy = new DeptHierarchy();

        if (deptId == null) {
            log.warn("getDeptHierarchy: deptId is null");
            return hierarchy;
        }

        SysDept dept = deptService.selectDeptById(deptId);
        if (dept == null) {
            log.warn("getDeptHierarchy: dept not found for deptId={}", deptId);
            return hierarchy;
        }

        String ancestors = dept.getAncestors();
        String deptType = dept.getDeptType();

        log.debug("getDeptHierarchy: deptId={}, deptName={}, ancestors={}, deptType={}",
                deptId, dept.getDeptName(), ancestors, deptType);

        if (ancestors == null || ancestors.trim().isEmpty()) {
            hierarchy.stationId = deptId;
            return hierarchy;
        }

        String[] ancestorIds = ancestors.split(",");
        log.debug("getDeptHierarchy: ancestorIds length={}, values={}", ancestorIds.length, Arrays.toString(ancestorIds));

        // 解析ancestors
        if (ancestorIds.length >= 2) {
            try {
                hierarchy.stationId = Long.parseLong(ancestorIds[1].trim());
            } catch (NumberFormatException ignored) {
            }
        }

        if (ancestorIds.length >= 3) {
            try {
                hierarchy.brigadeId = Long.parseLong(ancestorIds[2].trim());
            } catch (NumberFormatException ignored) {
            }
        }

        if (ancestorIds.length >= 4) {
            try {
                hierarchy.managerId = Long.parseLong(ancestorIds[3].trim());
            } catch (NumberFormatException ignored) {
            }
        }

        // 根据部门类型设置当前层级ID
        if (StrUtil.equals(DeptType.STATION.getCode(), deptType)) {
            hierarchy.stationId = deptId;
        } else if (StrUtil.equals(DeptType.BRIGADE.getCode(), deptType)) {
            hierarchy.brigadeId = deptId;
        } else if (StrUtil.equals(DeptType.MANAGER.getCode(), deptType)) {
            hierarchy.managerId = deptId;
        } else if (StrUtil.equals(DeptType.TEAMS.getCode(), deptType)) {
            hierarchy.teamId = deptId;
        }

        log.debug("getDeptHierarchy result: stationId={}, brigadeId={}, managerId={}, teamId={}",
                hierarchy.stationId, hierarchy.brigadeId, hierarchy.managerId, hierarchy.teamId);

        return hierarchy;
    }

    /**
     * 解析时间范围
     */
    private Date[] parseDateRange(AccuracyStatisticsQueryDTO query) {
        Date startDate = query != null ? query.getStartDate() : null;
        Date endDate = query != null ? query.getEndDate() : null;

        if (query != null && StrUtil.isNotBlank(query.getTimeRange())) {
            TimeRangeEnum timeRange = TimeRangeEnum.getByCode(query.getTimeRange());
            if (timeRange != null) {
                Date now = new Date();
                Calendar cal = Calendar.getInstance();
                cal.setTime(now);

                switch (timeRange) {
                    case TODAY:
                        startDate = DateUtils.truncate(now, Calendar.DAY_OF_MONTH);
                        endDate = now;
                        break;
                    case WEEK:
                        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
                        startDate = DateUtils.truncate(cal.getTime(), Calendar.DAY_OF_MONTH);
                        endDate = now;
                        break;
                    case MONTH:
                        cal.set(Calendar.DAY_OF_MONTH, 1);
                        startDate = DateUtils.truncate(cal.getTime(), Calendar.DAY_OF_MONTH);
                        endDate = now;
                        break;
                    case YEAR:
                        cal.set(Calendar.DAY_OF_YEAR, 1);
                        startDate = DateUtils.truncate(cal.getTime(), Calendar.DAY_OF_MONTH);
                        endDate = now;
                        break;
                }
            }
        }

        // 如果没有指定时间范围，默认最近一年
        if (startDate == null && endDate == null) {
            Calendar cal = Calendar.getInstance();
            endDate = cal.getTime();
            cal.add(Calendar.YEAR, -1);
            startDate = cal.getTime();
        }

        return new Date[]{startDate, endDate};
    }

    /**
     * 计算奖牌类型
     */
    private MedalTypeEnum calculateMedalType(int rank, int total) {
        if (total == 0 || rank == 0) {
            return MedalTypeEnum.CRY_YELLOW;
        }

        double percentage = (double) rank / total;

        if (rank == 1) {
            return MedalTypeEnum.GOLD;
        } else if (rank == 2) {
            return MedalTypeEnum.SILVER;
        } else if (rank == 3) {
            return MedalTypeEnum.BRONZE;
        } else if (percentage > 0.8) {
            return MedalTypeEnum.CRY_RED;
        } else if (percentage > 0.6) {
            return MedalTypeEnum.CRY_ORANGE;
        } else {
            return MedalTypeEnum.CRY_YELLOW;
        }
    }

    /**
     * 计算班组和部门级别排名
     * 支持班组用户和主管用户
     */
    private void calculateTeamAndDeptRankings(AccuracyStatisticsDTO result, DeptHierarchy hierarchy, Date startDate, Date endDate) {
        // 班组用户：计算班组在主管中的排名
        if (hierarchy.teamId != null && hierarchy.managerId != null) {
            List<TeamAccuracyInfo> teamsInManager = calculateTeamAccuraciesUnderDept(hierarchy.managerId, startDate, endDate);
            if (!teamsInManager.isEmpty()) {
                // 班组在主管中的排名
                AccuracyStatisticsDTO.RankingInfo teamInDeptRanking = findTeamRanking(hierarchy.teamId, teamsInManager);
                result.setTeamInDeptRanking(teamInDeptRanking);

                // 主管内Top班组（取前3）
                List<AccuracyStatisticsDTO.RankingItem> topTeamsInDept = convertToRankingItems(teamsInManager, 3, true);
                result.setTopTeamsInDept(topTeamsInDept);
            }
        }

        // 计算站级内班组排名（班组用户和主管用户都需要）
        if (hierarchy.stationId != null) {
            List<TeamAccuracyInfo> teamsInStation = calculateTeamAccuraciesUnderDept(hierarchy.stationId, startDate, endDate);
            if (!teamsInStation.isEmpty()) {
                // 班组用户：计算班组在站级中的排名
                if (hierarchy.teamId != null) {
                    AccuracyStatisticsDTO.RankingInfo teamInSiteRanking = findTeamRanking(hierarchy.teamId, teamsInStation);
                    result.setTeamInSiteRanking(teamInSiteRanking);
                }

                // 站级内Top班组（取前3）
                List<AccuracyStatisticsDTO.RankingItem> topTeamsInSite = convertToRankingItems(teamsInStation, 3, true);
                result.setTopTeamsInSite(topTeamsInSite);

                // 站级内Bottom班组（取后3）
                List<AccuracyStatisticsDTO.RankingItem> bottomTeamsInSite = convertToRankingItems(teamsInStation, 3, false);
                result.setBottomTeamsInSite(bottomTeamsInSite);
            }
        }

        // 计算主管在站级中的排名（班组用户和主管用户都需要）
        if (hierarchy.managerId != null && hierarchy.stationId != null) {
            List<TeamAccuracyInfo> managersInStation = calculateManagerAccuraciesUnderStation(hierarchy.stationId, startDate, endDate);
            if (!managersInStation.isEmpty()) {
                // 主管在站级中的排名
                AccuracyStatisticsDTO.RankingInfo deptInSiteRanking = findTeamRanking(hierarchy.managerId, managersInStation);
                result.setDeptInSiteRanking(deptInSiteRanking);

                // Top主管（取前3）
                List<AccuracyStatisticsDTO.RankingItem> topDepts = convertToRankingItems(managersInStation, 3, true);
                result.setTopDepts(topDepts);
            }
        }

        // 站长用户特殊处理：返回主管正确率排名前三和后三
        if (hierarchy.stationId != null && hierarchy.managerId == null && hierarchy.teamId == null) {
            // 当前用户是站长，计算所有主管的排名
            List<TeamAccuracyInfo> managersInStation = calculateManagerAccuraciesUnderStation(hierarchy.stationId, startDate, endDate);
            if (!managersInStation.isEmpty()) {
                // Top主管（取前3）- 格式如"一大队方圆主管"
                List<AccuracyStatisticsDTO.RankingItem> topDepts = convertToManagerRankingItems(managersInStation, 3, true);
                result.setTopDepts(topDepts);

                // Bottom主管（取后3）- 格式如"一大队方圆主管"
                List<AccuracyStatisticsDTO.RankingItem> bottomDepts = convertToManagerRankingItems(managersInStation, 3, false);
                result.setBottomDepts(bottomDepts);
            }
        }

        // 主管用户特殊处理：主管内Top班组
        if (hierarchy.teamId == null && hierarchy.managerId != null) {
            // 当前用户是主管，计算该主管下的班组排名
            Long currentManagerId = hierarchy.managerId;
            // 如果managerId来自ancestors，需要获取当前部门ID
            Long currentDeptId = SecurityUtils.getDeptId();
            SysDept currentDept = deptService.selectDeptById(currentDeptId);
            if (currentDept != null && StrUtil.equals(DeptType.MANAGER.getCode(), currentDept.getDeptType())) {
                currentManagerId = currentDeptId;
            }

            List<TeamAccuracyInfo> teamsUnderManager = calculateTeamAccuraciesUnderDept(currentManagerId, startDate, endDate);
            if (!teamsUnderManager.isEmpty()) {
                List<AccuracyStatisticsDTO.RankingItem> topTeamsInDept = convertToRankingItems(teamsUnderManager, 3, true);
                result.setTopTeamsInDept(topTeamsInDept);
            }
        }
    }

    /**
     * 计算指定部门下所有班组的正确率（批量优化版本）
     */
    private List<TeamAccuracyInfo> calculateTeamAccuraciesUnderDept(Long deptId, Date startDate, Date endDate) {
        List<TeamAccuracyInfo> result = new ArrayList<>();
        DeptCache cache = getDeptCache();

        DeptHierarchy hierarchy = cache != null ? cache.getHierarchy(deptId) : getDeptHierarchy(deptId);
        List<Long> teamIds = getTeamIdsUnderDept(deptId, hierarchy);

        if (teamIds.isEmpty()) {
            return result;
        }

        // 批量计算所有班组的正确率（核心优化：一次查询代替多次查询）
        Map<Long, long[]> teamCountsMap = batchCalculateAccuracyCountsForTeams(teamIds, startDate, endDate);

        // 为每个班组设置正确率
        for (Long teamId : teamIds) {
            SysDept teamDept = cache != null ? cache.deptMap.get(teamId) : deptService.selectDeptById(teamId);
            if (teamDept == null) {
                continue;
            }

            TeamAccuracyInfo info = new TeamAccuracyInfo();
            info.deptId = teamId;
            info.deptName = teamDept.getDeptName();

            long[] counts = teamCountsMap.getOrDefault(teamId, new long[]{0, 0});
            if (counts[1] > 0) {
                info.accuracy = BigDecimal.valueOf(counts[0])
                        .multiply(BigDecimal.valueOf(100))
                        .divide(BigDecimal.valueOf(counts[1]), 2, RoundingMode.HALF_UP);
            } else {
                info.accuracy = BigDecimal.ZERO;
            }
            result.add(info);
        }

        // 按正确率降序排序
        result.sort((a, b) -> b.accuracy.compareTo(a.accuracy));

        return result;
    }

    /**
     * 批量计算多个班组的正确率数量（性能优化核心方法）
     * 一次查询所有班组的数据，然后在内存中分组统计
     *
     * @return Map<班组ID, long [ ] { 正确数, 总数 }>
     */
    private Map<Long, long[]> batchCalculateAccuracyCountsForTeams(List<Long> teamIds, Date startDate, Date endDate) {
        Map<Long, long[]> result = new HashMap<>();
        if (teamIds.isEmpty()) {
            return result;
        }

        // 一次性查询所有班组的任务
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.in(DailyTask::getDtDeptId, teamIds);
        taskWrapper.eq(DailyTask::getDtStatus, DailyTaskStatusEnum.COMPLETED.getCode());
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        if (startDate != null) {
            taskWrapper.ge(DailyTask::getDtBusinessDate, startDate);
        }
        if (endDate != null) {
            taskWrapper.le(DailyTask::getDtBusinessDate, endDate);
        }
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

        if (tasks.isEmpty()) {
            return result;
        }

        // 按班组分组任务
        Map<Long, List<DailyTask>> tasksByDept = tasks.stream()
                .filter(t -> t.getDtDeptId() != null)
                .collect(Collectors.groupingBy(DailyTask::getDtDeptId));

        // 一次性查询所有任务明细
        List<String> allTaskIds = tasks.stream()
                .map(DailyTask::getDtId)
                .collect(Collectors.toList());

        LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.in(DailyTaskDetail::getDtdTaskId, allTaskIds);
        detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
        detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
        List<DailyTaskDetail> allDetails = dailyTaskDetailMapper.selectList(detailWrapper);

        // 按任务ID分组明细
        Map<String, List<DailyTaskDetail>> detailsByTaskId = allDetails.stream()
                .collect(Collectors.groupingBy(DailyTaskDetail::getDtdTaskId));

        // 计算每个班组的统计数据
        for (Map.Entry<Long, List<DailyTask>> entry : tasksByDept.entrySet()) {
            Long deptId = entry.getKey();
            List<DailyTask> deptTasks = entry.getValue();

            long totalCount = 0;
            long correctCount = 0;

            for (DailyTask task : deptTasks) {
                List<DailyTaskDetail> taskDetails = detailsByTaskId.get(task.getDtId());
                if (taskDetails != null) {
                    totalCount += taskDetails.size();
                    correctCount += taskDetails.stream()
                            .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                            .count();
                }
            }

            result.put(deptId, new long[]{correctCount, totalCount});
        }

        return result;
    }

    /**
     * 计算站级下所有主管的正确率（使用缓存和批量计算优化）
     */
    private List<TeamAccuracyInfo> calculateManagerAccuraciesUnderStation(Long stationId, Date startDate, Date endDate) {
        List<TeamAccuracyInfo> result = new ArrayList<>();
        DeptCache cache = getDeptCache();

        // 使用缓存的主管列表
        List<SysDept> managerDepts = cache != null ? cache.managerDepts : getManagerDeptsFromDb();

        // 收集站级下所有主管及其下属班组
        List<SysDept> managersInStation = new ArrayList<>();
        Map<Long, List<Long>> managerTeamIdsMap = new HashMap<>();
        List<Long> allTeamIds = new ArrayList<>();

        for (SysDept dept : managerDepts) {
            DeptHierarchy h = cache != null ? cache.getHierarchy(dept.getDeptId()) : getDeptHierarchy(dept.getDeptId());
            if (stationId.equals(h.stationId)) {
                managersInStation.add(dept);
                List<Long> teamIds = getTeamIdsUnderDept(dept.getDeptId(), h);
                managerTeamIdsMap.put(dept.getDeptId(), teamIds);
                allTeamIds.addAll(teamIds);
            }
        }

        // 批量计算所有班组的正确率
        Map<Long, long[]> teamCountsMap = allTeamIds.isEmpty() ? new HashMap<>() : batchCalculateAccuracyCountsForTeams(allTeamIds, startDate, endDate);

        // 为每个主管汇总正确率
        for (SysDept dept : managersInStation) {
            TeamAccuracyInfo info = new TeamAccuracyInfo();
            info.deptId = dept.getDeptId();
            info.deptName = dept.getDeptName();

            List<Long> teamIds = managerTeamIdsMap.get(dept.getDeptId());
            long totalCorrect = 0;
            long totalCount = 0;

            if (teamIds != null && !teamIds.isEmpty()) {
                for (Long teamId : teamIds) {
                    long[] counts = teamCountsMap.getOrDefault(teamId, new long[]{0, 0});
                    totalCorrect += counts[0];
                    totalCount += counts[1];
                }
            }

            if (totalCount > 0) {
                info.accuracy = BigDecimal.valueOf(totalCorrect)
                        .multiply(BigDecimal.valueOf(100))
                        .divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP);
            } else {
                info.accuracy = BigDecimal.ZERO;
            }
            result.add(info);
        }

        // 按正确率降序排序
        result.sort((a, b) -> b.accuracy.compareTo(a.accuracy));

        return result;
    }

    /**
     * 在排名列表中查找指定部门的排名
     * 如果部门不在列表中（无答题记录），将其视为正确率0排在最后
     */
    private AccuracyStatisticsDTO.RankingInfo findTeamRanking(Long deptId, List<TeamAccuracyInfo> rankings) {
        AccuracyStatisticsDTO.RankingInfo rankingInfo = new AccuracyStatisticsDTO.RankingInfo();

        if (rankings.isEmpty()) {
            rankingInfo.setRank(1);
            rankingInfo.setTotal(1);
            return rankingInfo;
        }

        int rank = 0;
        for (int i = 0; i < rankings.size(); i++) {
            if (deptId.equals(rankings.get(i).deptId)) {
                rank = i + 1;
                break;
            }
        }

        // 如果找不到，说明该部门没有答题记录，排在最后（正确率为0）
        if (rank == 0) {
            rank = rankings.size() + 1;
            rankingInfo.setRank(rank);
            rankingInfo.setTotal(rankings.size() + 1);
        } else {
            rankingInfo.setRank(rank);
            rankingInfo.setTotal(rankings.size());
        }
        return rankingInfo;
    }

    /**
     * 将TeamAccuracyInfo列表转换为RankingItem列表
     *
     * @param rankings 排名列表（已按正确率降序排序）
     * @param limit    取多少个
     * @param fromTop  true=从头取（Top），false=从尾取（Bottom）
     */
    private List<AccuracyStatisticsDTO.RankingItem> convertToRankingItems(List<TeamAccuracyInfo> rankings, int limit, boolean fromTop) {
        List<AccuracyStatisticsDTO.RankingItem> result = new ArrayList<>();

        if (rankings.isEmpty()) {
            return result;
        }

        int size = rankings.size();
        int actualLimit = Math.min(limit, size);

        if (fromTop) {
            // 取前N个
            for (int i = 0; i < actualLimit; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(info.deptName);
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        } else {
            // 取后N个（倒序）
            for (int i = size - actualLimit; i < size; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(info.deptName);
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        }

        return result;
    }

    /**
     * 将主管排名列表转换为RankingItem列表，名称格式为"大队名+主管名"
     *
     * @param rankings 排名列表（已按正确率降序排序）
     * @param limit    取多少个
     * @param fromTop  true=从头取（Top），false=从尾取（Bottom）
     */
    private List<AccuracyStatisticsDTO.RankingItem> convertToManagerRankingItems(List<TeamAccuracyInfo> rankings, int limit, boolean fromTop) {
        List<AccuracyStatisticsDTO.RankingItem> result = new ArrayList<>();

        if (rankings.isEmpty()) {
            return result;
        }

        int size = rankings.size();
        int actualLimit = Math.min(limit, size);

        if (fromTop) {
            // 取前N个
            for (int i = 0; i < actualLimit; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(getManagerDisplayName(info.deptId, info.deptName));
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        } else {
            // 取后N个（倒序）
            for (int i = size - actualLimit; i < size; i++) {
                TeamAccuracyInfo info = rankings.get(i);
                AccuracyStatisticsDTO.RankingItem item = new AccuracyStatisticsDTO.RankingItem();
                item.setId(info.deptId);
                item.setName(getManagerDisplayName(info.deptId, info.deptName));
                item.setAccuracy(info.accuracy);
                item.setRank(i + 1);
                result.add(item);
            }
        }

        return result;
    }

    /**
     * 获取主管显示名称，格式为"大队名+主管名"，如"一大队方圆主管"（使用缓存优化）
     */
    private String getManagerDisplayName(Long managerId, String managerName) {
        DeptCache cache = getDeptCache();
        SysDept managerDept = cache != null ? cache.deptMap.get(managerId) : deptService.selectDeptById(managerId);
        if (managerDept == null) {
            return managerName;
        }
        // 获取主管所属大队
        Long brigadeId = managerDept.getParentId();
        if (brigadeId != null) {
            SysDept brigadeDept = cache != null ? cache.deptMap.get(brigadeId) : deptService.selectDeptById(brigadeId);
            if (brigadeDept != null && StrUtil.equals(DeptType.BRIGADE.getCode(), brigadeDept.getDeptType())) {
                return brigadeDept.getDeptName() + managerName;
            }
        }
        return managerName;
    }

    /**
     * 班组/部门正确率信息
     */
    private static class TeamAccuracyInfo {
        Long deptId;
        String deptName;
        BigDecimal accuracy;
    }

    /**
     * 部门层级内部类 - 美兰4级架构
     */
    private static class DeptHierarchy {
        Long stationId;   // 站级ID
        Long brigadeId;   // 大队ID
        Long managerId;   // 主管ID
        Long teamId;      // 班组ID
    }

    /**
     * 用户正确率信息
     */
    private static class UserAccuracyInfo {
        Long userId;
        String userName;
        BigDecimal accuracy;
    }

    @Override
    public Map<Long, BigDecimal> getUsersAccuracyMap(List<Long> userIds, String startDate, String endDate) {
        DateRange dateRange = new DateRange();
        dateRange.startDate = startDate;
        dateRange.endDate = endDate;
        return calculateUsersAccuracyMap(userIds, dateRange);
    }

    @Override
    public Map<Long, BigDecimal> getTeamsAccuracyMap(List<Long> teamIds, String startDate, String endDate) {
        DateRange dateRange = new DateRange();
        dateRange.startDate = startDate;
        dateRange.endDate = endDate;
        return calculateTeamsAccuracyMap(teamIds, dateRange);
    }

    @Override
    public Map<Long, BigDecimal> getDeptsAccuracyMap(List<Long> deptIds, String startDate, String endDate) {
        DateRange dateRange = new DateRange();
        dateRange.startDate = startDate;
        dateRange.endDate = endDate;
        return calculateDeptsAccuracyMap(deptIds, dateRange);
    }

    @Override
    public QuizAccuracyAnalysisResultDto getQuizAccuracyAnalysis(String startDate, String endDate) {
        QuizAccuracyAnalysisResultDto result = new QuizAccuracyAnalysisResultDto();

        // 查询各分类正确率
        List<CategoryAccuracyItemDto> categoryList = dailyTaskDetailMapper.selectCorrectRateByCategory(startDate, endDate);
        if (categoryList == null || categoryList.isEmpty()) {
            result.setAvgCorrectRate(BigDecimal.ZERO);
            result.setCategoryList(Collections.emptyList());
            result.setNote("");
            return result;
        }

        // 计算全站平均正确率（所有分类合并计算）
        int totalCorrect = categoryList.stream().mapToInt(c -> c.getCorrectCount() == null ? 0 : c.getCorrectCount()).sum();
        int totalCount = categoryList.stream().mapToInt(c -> c.getTotalCount() == null ? 0 : c.getTotalCount()).sum();
        BigDecimal avgRate = totalCount > 0
                ? BigDecimal.valueOf(totalCorrect * 100.0 / totalCount).setScale(2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;
        result.setAvgCorrectRate(avgRate);

        // 找出正确率最高和最低的分类
        CategoryAccuracyItemDto best = categoryList.stream()
                .max(Comparator.comparing(c -> c.getCorrectRate() == null ? BigDecimal.ZERO : c.getCorrectRate()))
                .orElse(null);
        CategoryAccuracyItemDto weak = categoryList.stream()
                .min(Comparator.comparing(c -> c.getCorrectRate() == null ? BigDecimal.ZERO : c.getCorrectRate()))
                .orElse(null);

        // 标注标签和颜色（best和weak相同时均标最高）
        for (CategoryAccuracyItemDto item : categoryList) {
            if (best != null && item.getCategoryName() != null && item.getCategoryName().equals(best.getCategoryName())) {
                item.setLabel("最高");
                item.setColor("green");
            } else if (weak != null && item.getCategoryName() != null && item.getCategoryName().equals(weak.getCategoryName())) {
                item.setLabel("薄弱");
                item.setColor("red");
            } else {
                item.setLabel("一般");
                item.setColor("normal");
            }
        }

        result.setCategoryList(categoryList);
        result.setBestCategoryName(best != null ? best.getCategoryName() : null);
        result.setWeakCategoryName(weak != null ? weak.getCategoryName() : null);

        // 生成备注说明
        String bestName = best != null ? best.getCategoryName() : null;
        String weakName = weak != null ? weak.getCategoryName() : null;
        if (bestName != null && weakName != null && !bestName.equals(weakName)) {
            result.setNote(String.format("[%s]掌握程度最好，[%s]知识点薄弱", bestName, weakName));
        } else if (bestName != null) {
            result.setNote(String.format("[%s]掌握程度最好", bestName));
        }

        return result;
    }

    /**
     * 计算多个用户的正确率Map
     */
    private Map<Long, BigDecimal> calculateUsersAccuracyMap(List<Long> userIds, DateRange dateRange) {
        Map<Long, BigDecimal> result = new HashMap<>();
        // 查询用户在时间范围内已完成的任务
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.in(DailyTask::getDtUserId, userIds);
        taskWrapper.ge(DailyTask::getDtBusinessDate, java.sql.Date.valueOf(dateRange.startDate));
        taskWrapper.le(DailyTask::getDtBusinessDate, java.sql.Date.valueOf(dateRange.endDate));
        taskWrapper.eq(DailyTask::getDtStatus, "COMPLETED");
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

        if (tasks.isEmpty()) {
            for (Long userId : userIds) {
                result.put(userId, BigDecimal.ZERO);
            }
        }

        // 查询所有题目明细
        List<String> taskIds = tasks.stream().map(DailyTask::getDtId).collect(Collectors.toList());
        LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.in(DailyTaskDetail::getDtdTaskId, taskIds);
        detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
        detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
        List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(detailWrapper);

        for (Long userId : userIds) {
            List<DailyTask> targetTaskList = tasks.stream().filter(t -> t.getDtUserId().equals(userId)).collect(Collectors.toList());
            List<String> targetDailyTaskIdList = targetTaskList.stream().map(DailyTask::getDtId).collect(Collectors.toList());
            List<DailyTaskDetail> targetDetailList = details.stream().filter(d -> targetDailyTaskIdList.contains(d.getDtdTaskId())).collect(Collectors.toList());
            int totalCount = targetDetailList.size();
            int correctCount = (int) targetDetailList.stream()
                    .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                    .count();
            BigDecimal accuracy = totalCount > 0
                    ? new BigDecimal(correctCount).multiply(new BigDecimal(100)).divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP)
                    : BigDecimal.ZERO;
            result.put(userId, accuracy);
        }
        return result;
    }

    /**
     * 计算多个班组的正确率Map
     */
    private Map<Long, BigDecimal> calculateTeamsAccuracyMap(List<Long> teamIds, DateRange dateRange) {
        Map<Long, BigDecimal> result = new HashMap<>();
        for (Long teamId : teamIds) {
            List<Long> teamUserIds = getTeamUserIds(teamId);
            AccuracyData data = calculateGroupAccuracy(teamUserIds, dateRange);
            result.put(teamId, data.accuracy);
        }
        return result;
    }

    /**
     * 计算多个科级的正确率Map
     */
    private Map<Long, BigDecimal> calculateDeptsAccuracyMap(List<Long> deptIds, DateRange dateRange) {
        Map<Long, BigDecimal> result = new HashMap<>();
        for (Long deptId : deptIds) {
            List<Long> deptUserIds = getDeptInspectorsAndLeaders(deptId);
            AccuracyData data = calculateGroupAccuracy(deptUserIds, dateRange);
            result.put(deptId, data.accuracy);
        }
        return result;
    }

    /**
     * 计算个人正确率
     */
    private AccuracyData calculateUserAccuracy(Long userId, DateRange dateRange) {
        // 查询用户在时间范围内已完成的任务
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.eq(DailyTask::getDtUserId, userId);
        taskWrapper.ge(DailyTask::getDtBusinessDate, java.sql.Date.valueOf(dateRange.startDate));
        taskWrapper.le(DailyTask::getDtBusinessDate, java.sql.Date.valueOf(dateRange.endDate));
        taskWrapper.eq(DailyTask::getDtStatus, "COMPLETED");
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

        if (tasks.isEmpty()) {
            return new AccuracyData(BigDecimal.ZERO, 0, 0);
        }

        // 查询所有题目明细
        List<String> taskIds = tasks.stream().map(DailyTask::getDtId).collect(Collectors.toList());
        LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.in(DailyTaskDetail::getDtdTaskId, taskIds);
        detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
        detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
        List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(detailWrapper);

        int totalCount = details.size();
        int correctCount = (int) details.stream()
                .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                .count();

        BigDecimal accuracy = totalCount > 0
                ? new BigDecimal(correctCount).multiply(new BigDecimal(100))
                .divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;

        return new AccuracyData(accuracy, correctCount, totalCount);
    }

    /**
     * 计算群组正确率
     */
    private AccuracyData calculateGroupAccuracy(List<Long> userIds, DateRange dateRange) {
        if (userIds.isEmpty()) {
            return new AccuracyData(BigDecimal.ZERO, 0, 0);
        }

        // 查询所有用户在时间范围内已完成的任务
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.in(DailyTask::getDtUserId, userIds);
        taskWrapper.ge(DailyTask::getDtBusinessDate, java.sql.Date.valueOf(dateRange.startDate));
        taskWrapper.le(DailyTask::getDtBusinessDate, java.sql.Date.valueOf(dateRange.endDate));
        taskWrapper.eq(DailyTask::getDtStatus, "COMPLETED");
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

        if (tasks.isEmpty()) {
            return new AccuracyData(BigDecimal.ZERO, 0, 0);
        }

        // 查询所有题目明细
        List<String> taskIds = tasks.stream().map(DailyTask::getDtId).collect(Collectors.toList());
        LambdaQueryWrapper<DailyTaskDetail> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.in(DailyTaskDetail::getDtdTaskId, taskIds);
        detailWrapper.eq(DailyTaskDetail::getDelStatus, 0);
        detailWrapper.isNotNull(DailyTaskDetail::getDtdIsCorrect);
        List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(detailWrapper);

        int totalCount = details.size();
        int correctCount = (int) details.stream()
                .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                .count();

        BigDecimal accuracy = totalCount > 0
                ? new BigDecimal(correctCount).multiply(new BigDecimal(100))
                .divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;

        return new AccuracyData(accuracy, correctCount, totalCount);
    }

    /**
     * 获取班组所有成员ID列表
     * 注意：使用直接SQL查询，绕过@DataScope数据权限过滤，以获取全部用户数据用于统计
     */
    private List<Long> getTeamUserIds(Long teamId) {
        String sql = "SELECT user_id FROM sys_user WHERE dept_id = ? AND del_flag = '0'";
        return jdbcTemplate.queryForList(sql, Long.class, teamId);
    }


    /**
     * 获取科级下所有安检员和班组长ID列表
     * 使用 selectUserListByRoleKeyAndDeptId 方法一次性查询，避免循环读库
     */
    private List<Long> getDeptInspectorsAndLeaders(Long deptId) {
        // 使用角色标识查询，一次性获取该部门（包含子部门）下所有安检员和班组长
        List<SysUser> users = userService.selectUserListByRoleKeyAndDeptId(
                Arrays.asList(RoleTypeEnum.banzuzhang.getCode(), RoleTypeEnum.SecurityCheck.getCode()),
                deptId
        );
        return users.stream()
                .map(SysUser::getUserId)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 时间范围
     */
    private static class DateRange {
        String startDate;
        String endDate;
    }

    /**
     * 正确率数据
     */
    private static class AccuracyData {
        BigDecimal accuracy;     // 正确率
        Integer correctCount;    // 正确题数
        Integer totalCount;      // 总题数

        AccuracyData(BigDecimal accuracy, Integer correctCount, Integer totalCount) {
            this.accuracy = accuracy;
            this.correctCount = correctCount;
            this.totalCount = totalCount;
        }
    }

}
