package com.sundot.airport.web.controller.item;

import cn.hutool.core.util.StrUtil;
import com.sundot.airport.check.domain.CheckEfficiencyDto;
import com.sundot.airport.check.domain.CheckEfficiencyRankDto;
import com.sundot.airport.check.service.ICheckEfficiencyService;
import com.sundot.airport.common.core.domain.AjaxResult;
import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.dto.*;
import com.sundot.airport.common.enums.DeptType;
import com.sundot.airport.common.enums.DeptTypeEnum;
import com.sundot.airport.common.enums.RoleTypeEnum;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.common.utils.*;
import com.sundot.airport.exam.service.IAccuracyStatisticsService;
import com.sundot.airport.item.domain.SeizureEfficiencyDto;
import com.sundot.airport.item.domain.SeizureEfficiencyRankDto;
import com.sundot.airport.item.service.SeizureEfficiencyService;
import com.sundot.airport.system.domain.SysLargeScreenLearningGrowthQueryParamDto;
import com.sundot.airport.system.mapper.SysUserMapper;
import com.sundot.airport.system.service.ISysDeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import static com.sundot.airport.common.utils.SecurityUtils.getDeptId;

@Api(tags = "绩效维度统计")
@Slf4j
@RestController
@RequestMapping("/performance/dimension")
public class PerformanceDimensionController {


    @Autowired
    private SeizureEfficiencyService seizureEfficiencyService;

    @Autowired
    private ICheckEfficiencyService checkEfficiencyService;

    @Autowired
    private IAccuracyStatisticsService accuracyStatisticsService;


    @Autowired
    private ISysDeptService sysDeptService;


    @Autowired
    private SysUserMapper userMapper;

    /**
     * 基于时间维度的绩效统计查询
     * 返回时间维度组织的数据结构：时间 -> [对象名称, 数值] 列表
     */
    @Cacheable(
            value = "statistics_data",
            keyGenerator = "statisticsKeyGenerator",
            unless = "!T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isSuccess(#result) ||T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isEmptyData(#result)"
    )
    @ApiOperation("基于时间维度的绩效统计查询趋势图")
    @PostMapping("/calculate-by-time")
    public AjaxResult calculatePerformanceByTime(@RequestBody PerformanceDimensionParamDto param) {
        try {
            // 参数验证
            validateParameters(param);

            // 计算基于时间维度的绩效统计结果
            TimeBasedPerformanceResult result = calculatePerformanceByTimeDimension(param);

            if (param.getDimension() != 4) {
                if (param.getDimensionType() == 1) {
                    sortAndLimitDataItemsByProgress(result.getTimeDataList(), param);
                } else {
                    sortAndLimitDataItemsByAverage(result.getTimeDataList(), param);
                }
            }

            // 填充科室和班级信息
            enrichDeptAndClassInfo(result, param);

            return AjaxResult.success(result);
        } catch (Exception e) {
            log.error("计算时间维度绩效统计失败", e);
            return AjaxResult.error("计算时间维度绩效统计失败：" + e.getMessage());
        }
    }

    @Cacheable(
            value = "statistics_data",
            keyGenerator = "statisticsKeyGenerator",
            unless = "!T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isSuccess(#result) ||T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isEmptyData(#result)"
    )
    @ApiOperation("基于时间维度的绩效统计查询列表")
    @PostMapping("/calculate-by-time-list")
    public AjaxResult calculatePerformanceByTimeList(@RequestBody PerformanceDimensionParamDto param) {
        try {
            // 参数验证
            validateParameters(param);

            // 计算基于时间维度的绩效统计结果
            TimeBasedPerformanceResult result = calculatePerformanceByTimeDimension(param);

            // 计算上一个月的数据
            PerformanceDimensionParamDto param1 = createLastMonthParam(param);

            TimeBasedPerformanceResult lastResult = calculatePerformanceByTimeDimension(param1);

            // 根据维度类型处理数据
            processDataForListView(result, lastResult, param);

            // 填充科室和班级信息
            enrichDeptAndClassInfo(result, param);

            return AjaxResult.success(result);
        } catch (Exception e) {
            log.error("计算时间维度绩效统计列表失败", e);
            return AjaxResult.error("计算时间维度绩效统计列表失败：" + e.getMessage());
        }
    }

    /**
     * 创建上一个月的查询参数
     *
     * @param param 原始参数
     * @return 上个月参数的查询参数
     */
    private PerformanceDimensionParamDto createLastMonthParam(PerformanceDimensionParamDto param) {
        PerformanceDimensionParamDto lastMonthParam = new PerformanceDimensionParamDto();

        // 获取开始时间对应的 LocalDate
        LocalDate startLocalDate = param.getStartTime().toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();

        // 计算上个月的第一天和最后一天
        LocalDate lastMonthStart = startLocalDate.minusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastMonthEnd = startLocalDate.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());

        lastMonthParam.setStartTime(DateUtils.toDate(lastMonthStart));
        lastMonthParam.setEndTime(DateUtils.toDate(lastMonthEnd));
        lastMonthParam.setDimension(param.getDimension());
        lastMonthParam.setResultField(param.getResultField());
        lastMonthParam.setDimensionType(param.getDimensionType());
        lastMonthParam.setSortOrder(param.getSortOrder());

        return lastMonthParam;
    }

    /**
     * 处理列表视图数据
     * 根据维度类型决定是否限制数量，并计算环比
     */
    private void processDataForListView(TimeBasedPerformanceResult result, TimeBasedPerformanceResult lastResult, PerformanceDimensionParamDto param) {
        List<TimeBasedPerformanceResult.TimeData> timeDataList = result.getTimeDataList();
        if (timeDataList == null || timeDataList.isEmpty()) {
            return;
        }
        List<TimeBasedPerformanceResult.TimeData> lastTimeDataList = lastResult.getTimeDataList();

        // 开始时间上个月数据
        Map<Long, BigDecimal> lastMonthValues = new HashMap<>();

        // 对当前月份数据进行排序和限制
        if (param.getDimensionType() == 1) {
            sortAndLimitDataItemsByProgress(timeDataList, param);
        } else {
            sortAndLimitDataItemsByAverage(timeDataList, param);
        }

        // 对上个月数据进行排序和限制
        if (lastTimeDataList != null && !lastTimeDataList.isEmpty()) {
            if (param.getDimension() != null && param.getDimension() != 4) {
                if (param.getDimensionType() == 1) {
                    sortDataItemsByProgressOnly(lastTimeDataList, param);
                } else {
                    sortDataItemsByAverageOnly(lastTimeDataList, param);
                }
            }
            for (TimeBasedPerformanceResult.TimeData timeData : lastTimeDataList) {
                for (TimeBasedPerformanceResult.DataItem item : timeData.getDataItems()) {
                    Long id = item.getId();
                    lastMonthValues.putIfAbsent(id, item.getValue() != null ? item.getValue() : BigDecimal.ZERO);
                }
            }
        }

        // 计算环比并更新 displayValue
        calculateAndFormatRatioWithIdKey(timeDataList, lastMonthValues);
    }


    /**
     * 计算环比显示值
     */
    private String calculateRatioDisplay(BigDecimal currentValue, BigDecimal previousValue) {
        if (previousValue == null) {
            return "--%";
        }

        // 如果前值为 0，无法计算环比
        if (previousValue.compareTo(BigDecimal.ZERO) == 0) {
            // 如果当前值也为 0，显示无变化
            if (currentValue.compareTo(BigDecimal.ZERO) == 0) {
                return "0%";
            }
            // 否则显示无穷大或特殊标识
            return "--%";
        }

        // 计算环比变化 = (当前值 - 前值) / |前值| * 100%
        // 使用前值的绝对值作为分母，确保增长率的正负号正确反映变化方向
        BigDecimal difference = currentValue.subtract(previousValue);
        BigDecimal ratio = difference.divide(previousValue.abs(), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal("100"));

        // 格式化为带符号的百分比
        String sign = ratio.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "";
        String ratioStr = ratio.setScale(0, RoundingMode.HALF_UP).toString();

        return sign + ratioStr + "%";
    }

    /**
     * 计算环比并更新
     */
    private void calculateAndFormatRatioWithIdKey(List<TimeBasedPerformanceResult.TimeData> timeDataList, Map<Long, BigDecimal> lastMonthValues) {

        Map<Long, BigDecimal> previousValues = new HashMap<>();

        for (int i = 0; i < timeDataList.size(); i++) {
            TimeBasedPerformanceResult.TimeData timeData = timeDataList.get(i);
            List<TimeBasedPerformanceResult.DataItem> dataItems = timeData.getDataItems();

            for (TimeBasedPerformanceResult.DataItem item : dataItems) {
                Long id = item.getId();
                BigDecimal currentValue = item.getValue() != null ? item.getValue() : BigDecimal.ZERO;
                BigDecimal previousValue = null;

                // 第一个月：使用上个月的数据作为对比
                if (i == 0) {
                    previousValue = lastMonthValues.get(id);
                } else {
                    // 后续月份：使用前一个月的数据作为对比
                    previousValue = previousValues.get(id);
                }

                // 计算环比
                String ratioDisplay = calculateRatioDisplay(currentValue, previousValue);

                //currentValue保留两位小数
                currentValue = currentValue.setScale(2, RoundingMode.HALF_UP);
                item.setDisplayValue(currentValue + " (" + ratioDisplay + ")");

                // 保存当前值作为下一个时间点的前值
                previousValues.put(id, currentValue);
            }
        }
    }

    /**
     * 按进步值对时间数据进行排序（不限制数量，用于上个月数据）
     */
    private void sortDataItemsByProgressOnly(List<TimeBasedPerformanceResult.TimeData> timeDataList, PerformanceDimensionParamDto param) {
        if (timeDataList == null || timeDataList.size() < 2) {
            return;
        }

        // 获取第一个和最后一个时间点的数据
        List<TimeBasedPerformanceResult.DataItem> firstTimeData = timeDataList.get(0).getDataItems();
        List<TimeBasedPerformanceResult.DataItem> lastTimeData = timeDataList.get(timeDataList.size() - 1).getDataItems();

        Map<Long, BigDecimal> progressMap = new HashMap<>();

        for (TimeBasedPerformanceResult.DataItem firstItem : firstTimeData) {
            for (TimeBasedPerformanceResult.DataItem lastItem : lastTimeData) {
                if (firstItem.getId().equals(lastItem.getId())) {
                    BigDecimal firstValue = firstItem.getValue() != null ? firstItem.getValue() : BigDecimal.ZERO;
                    BigDecimal lastValue = lastItem.getValue() != null ? lastItem.getValue() : BigDecimal.ZERO;
                    BigDecimal progress = lastValue.subtract(firstValue);
                    progressMap.put(firstItem.getId(), progress);
                    break;
                }
            }
        }

        // 对第一个时间点的数据按进步值排序
        firstTimeData.sort((item1, item2) -> {
            BigDecimal progress1 = progressMap.getOrDefault(item1.getId(), BigDecimal.ZERO);
            BigDecimal progress2 = progressMap.getOrDefault(item2.getId(), BigDecimal.ZERO);
            int compareResult = progress2.compareTo(progress1);
            if (compareResult == 0) {
                return item1.getName().compareTo(item2.getName());
            }
            return compareResult;
        });

        // 更新所有时间点的数据顺序，但不限制数量
        Set<Long> selectedIds = firstTimeData.stream()
                .map(TimeBasedPerformanceResult.DataItem::getId)
                .collect(Collectors.toSet());

        for (TimeBasedPerformanceResult.TimeData timeData : timeDataList) {
            timeData.setDataItems(
                    timeData.getDataItems().stream()
                            .filter(item -> selectedIds.contains(item.getId()))
                            .collect(Collectors.toList())
            );
        }
    }

    /**
     * 按平均值对时间数据进行排序（不限制数量，用于上个月数据）
     */
    private void sortDataItemsByAverageOnly(List<TimeBasedPerformanceResult.TimeData> timeDataList, PerformanceDimensionParamDto param) {
        if (timeDataList == null || timeDataList.isEmpty()) {
            return;
        }

        // 计算每个人的平均值
        Map<Long, BigDecimal> averageMap = new HashMap<>();

        // 统计每个人在所有时间点的值
        Map<Long, List<BigDecimal>> idToValuesMap = new HashMap<>();

        for (TimeBasedPerformanceResult.TimeData timeData : timeDataList) {
            for (TimeBasedPerformanceResult.DataItem item : timeData.getDataItems()) {
                idToValuesMap.computeIfAbsent(item.getId(), k -> new ArrayList<>())
                        .add(item.getValue() != null ? item.getValue() : BigDecimal.ZERO);
            }
        }

        // 计算平均值
        idToValuesMap.forEach((id, values) -> {
            BigDecimal sum = values.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal average = sum.divide(BigDecimal.valueOf(values.size()), 2, RoundingMode.HALF_UP);
            averageMap.put(id, average);
        });

        List<TimeBasedPerformanceResult.DataItem> firstTimeData = timeDataList.get(0).getDataItems();

        // 按平均值排序
        firstTimeData.sort((item1, item2) -> {
            BigDecimal avg1 = averageMap.getOrDefault(item1.getId(), BigDecimal.ZERO);
            BigDecimal avg2 = averageMap.getOrDefault(item2.getId(), BigDecimal.ZERO);
            int compareResult = avg2.compareTo(avg1); // 降序排列
            if (compareResult == 0) {
                compareResult = item1.getName().compareTo(item2.getName());
            }
            return compareResult;
        });

        // 更新所有时间点的数据顺序，但不限制数量
        Set<Long> selectedIds = firstTimeData.stream()
                .map(TimeBasedPerformanceResult.DataItem::getId)
                .collect(Collectors.toSet());

        for (TimeBasedPerformanceResult.TimeData timeData : timeDataList) {
            timeData.setDataItems(
                    timeData.getDataItems().stream()
                            .filter(item -> selectedIds.contains(item.getId()))
                            .collect(Collectors.toList())
            );
        }
    }

    /**
     * 参数验证
     */
    private void validateParameters(PerformanceDimensionParamDto param) {
        if (param.getStartTime() == null) {
            throw new IllegalArgumentException("开始时间不能为空");
        }
        if (param.getEndTime() == null) {
            throw new IllegalArgumentException("结束时间不能为空");
        }
        if (param.getStartTime().after(param.getEndTime())) {
            throw new IllegalArgumentException("开始时间不能晚于结束时间");
        }
        if (param.getDimension() != null && (param.getDimension() < 1 || param.getDimension() > 4)) {
            throw new IllegalArgumentException("维度参数必须在1-4之间");
        }
    }


    /**
     * 计算基于时间维度的绩效统计结果
     *
     * @param param 查询参数
     * @return 基于时间维度的绩效统计结果
     */
    public TimeBasedPerformanceResult calculatePerformanceByTimeDimension(PerformanceDimensionParamDto param) {
        // 参数校验和默认值设置
        validateAndSetDefaults(param);

        TimeBasedPerformanceResult result = new TimeBasedPerformanceResult();
        result.setResultField(param.getResultField());
        result.setIsProgress(param.getDimensionType() == 1);

        // 获取所有人员/班组ID
        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
        if (topSiteId == null) {
            throw new ServiceException("无法找到有效的站点信息");
        }
        // 个人维度
        if (param.getDimension() == 1) {
            result = calculatePersonalTimeBasedResult(param, topSiteId);
        } else if (param.getDimension() == 2) {
            // 班组维度
            result = calculateTeamTimeBasedResult(param, topSiteId);
        } else if (param.getDimension() == 3) {
            // 科室维度
            result = calculateDepartmentTimeBasedResult(param, topSiteId);
        } else if (param.getDimension() == 4) {
            // 大队维度
            result = calculateBrigadeTimeBasedResult(param, topSiteId);
        }

        return result;
    }

    /**
     * 班组维度
     *
     * @param param
     * @param topSiteId 站点ID
     * @return 时间维度结果
     */
    private TimeBasedPerformanceResult calculateTeamTimeBasedResult(PerformanceDimensionParamDto param, Long topSiteId) {
        // 获取站点下所有班组
        List<SysDept> allDepts = sysDeptService.selectChildrenDeptById(topSiteId);
        List<SysDept> teamDeptList = allDepts.stream()
                .filter(item -> StrUtil.equals(DeptType.TEAMS.getCode(), item.getDeptType()))
                .collect(Collectors.toList());
        Set<Long> ids = teamDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toSet());
        return calculatePersonalOrTeamTimeBasedResult(param, ids);
    }

    /**
     * 个人维度
     *
     * @param param     查询参数
     * @param topSiteId 站点ID
     * @return 时间维度结果
     */
    private TimeBasedPerformanceResult calculatePersonalTimeBasedResult(PerformanceDimensionParamDto param, Long topSiteId) {
        List<SysUser> sysUserTempList = userMapper.selectUserByDeptId(topSiteId);
        List<SysUser> users = sysUserTempList.stream().filter(item -> item.getRoles().stream().anyMatch(sysRole -> RoleTypeEnum.banzuzhang.getCode().equals(sysRole.getRoleKey()) || RoleTypeEnum.SecurityCheck.getCode().equals(sysRole.getRoleKey()))).collect(Collectors.toList());
        Set<Long> ids = users.stream().map(SysUser::getUserId).collect(Collectors.toSet());
        return calculatePersonalOrTeamTimeBasedResult(param, ids);
    }

    /**
     * 计算大队维度的时间维度结果
     */
    private TimeBasedPerformanceResult calculateBrigadeTimeBasedResult(PerformanceDimensionParamDto param, Long topSiteId) {
        TimeBasedPerformanceResult result = new TimeBasedPerformanceResult();

        List<SysDept> allDepts = sysDeptService.selectChildrenDeptById(topSiteId);
        // 获取站点下所有大队
        List<SysDept> brigadeList = allDepts.stream().filter(item -> StrUtil.equals(DeptType.BRIGADE.getCode(), item.getDeptType())).collect(Collectors.toList());


        // 计算时间分段
        List<LargeScreenDateUtils.DateRange> timeRanges = new ArrayList<>();
        List<String> timeAxis = new ArrayList<>();

        LocalDate startLocalDate = dateToLocalDate(param.getStartTime());
        LocalDate endLocalDate = dateToLocalDate(param.getEndTime());
        if (startLocalDate == null || endLocalDate == null) {
            return result;
        }
        long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(startLocalDate, endLocalDate);

        // 根据时间跨度选择分段粒度
        createTimeSegments(startLocalDate, endLocalDate, daysBetween, timeRanges, timeAxis);

        result.setTimeAxis(timeAxis);

        // 预加载所有时间段的数据
        Map<String, List<PerformanceDimensionResult>> map = new HashMap<>();

        preloadTimeSegmentData(timeRanges, param.getDimension(), map);

        // 获取所有科室ID
        Set<Long> deptIds = new HashSet<>();
        for (SysDept dept : brigadeList) {
            deptIds.add(dept.getDeptId());
        }

        // 构建时间维度数据
        List<TimeBasedPerformanceResult.TimeData> timeDataList = new ArrayList<>();

        for (int i = 0; i < timeRanges.size(); i++) {
            LargeScreenDateUtils.DateRange range = timeRanges.get(i);
            String timeLabel = timeAxis.get(i);
            String timeKey = getTimeRangeKey(range);

            TimeBasedPerformanceResult.TimeData timeData = new TimeBasedPerformanceResult.TimeData();
            timeData.setTimeLabel(timeLabel);

            List<TimeBasedPerformanceResult.DataItem> dataItems = new ArrayList<>();

            // 为每个科室计算该时间段的数据
            Map<Long, String> nameMap = getDeptNameMap(new ArrayList<>(deptIds));
            for (Long deptId : deptIds) {
                String deptName = nameMap.get(deptId);
                if (deptName == null) continue;

                BigDecimal value = getDimensionValueFromPreloadedData(
                        deptId,
                        map.get(timeKey),
                        param.getResultField()
                );

                TimeBasedPerformanceResult.DataItem dataItem = new TimeBasedPerformanceResult.DataItem();
                dataItem.setId(deptId);
                dataItem.setName(deptName);
                dataItem.setValue(value);
                dataItem.setDisplayValue(formatScoreOnly(value));
                dataItems.add(dataItem);
            }

            // 按数值排序
            sortDataItems(dataItems, param);
            timeData.setDataItems(dataItems);
            timeDataList.add(timeData);
        }

        result.setTimeDataList(timeDataList);
        return result;
    }

    /**
     * 计算科室维度的时间维度结果
     */
    private TimeBasedPerformanceResult calculateDepartmentTimeBasedResult(PerformanceDimensionParamDto param, Long topSiteId) {
        TimeBasedPerformanceResult result = new TimeBasedPerformanceResult();

        List<SysDept> allDepts = sysDeptService.selectChildrenDeptById(topSiteId);
        // 获取站点下所有科室
        List<SysDept> departmentList = allDepts.stream().filter(item -> StrUtil.equals(DeptType.MANAGER.getCode(), item.getDeptType())).collect(Collectors.toList());


        // 计算时间分段
        List<LargeScreenDateUtils.DateRange> timeRanges = new ArrayList<>();
        List<String> timeAxis = new ArrayList<>();

        LocalDate startLocalDate = dateToLocalDate(param.getStartTime());
        LocalDate endLocalDate = dateToLocalDate(param.getEndTime());
        if (startLocalDate == null || endLocalDate == null) {
            return result;
        }
        long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(startLocalDate, endLocalDate);

        // 根据时间跨度选择分段粒度
        createTimeSegments(startLocalDate, endLocalDate, daysBetween, timeRanges, timeAxis);

        result.setTimeAxis(timeAxis);

        // 预加载所有时间段的数据
        Map<String, List<PerformanceDimensionResult>> map = new HashMap<>();

        preloadTimeSegmentData(timeRanges, param.getDimension(), map);

        // 获取所有科室ID
        Set<Long> deptIds = new HashSet<>();
        for (SysDept dept : departmentList) {
            deptIds.add(dept.getDeptId());
        }

        // 构建时间维度数据
        List<TimeBasedPerformanceResult.TimeData> timeDataList = new ArrayList<>();

        for (int i = 0; i < timeRanges.size(); i++) {
            LargeScreenDateUtils.DateRange range = timeRanges.get(i);
            String timeLabel = timeAxis.get(i);
            String timeKey = getTimeRangeKey(range);

            TimeBasedPerformanceResult.TimeData timeData = new TimeBasedPerformanceResult.TimeData();
            timeData.setTimeLabel(timeLabel);

            List<TimeBasedPerformanceResult.DataItem> dataItems = new ArrayList<>();

            // 为每个科室计算该时间段的数据
            Map<Long, String> nameMap = getDeptNameMap(new ArrayList<>(deptIds));
            for (Long deptId : deptIds) {
                String deptName = nameMap.get(deptId);
                if (deptName == null) continue;

                BigDecimal value = getDimensionValueFromPreloadedData(
                        deptId,
                        map.get(timeKey),
                        param.getResultField()
                );

                TimeBasedPerformanceResult.DataItem dataItem = new TimeBasedPerformanceResult.DataItem();
                dataItem.setId(deptId);
                dataItem.setName(deptName);
                dataItem.setValue(value);
                dataItem.setDisplayValue(formatScoreOnly(value));
                dataItems.add(dataItem);
            }

            // 按数值排序
            sortDataItems(dataItems, param);
            timeData.setDataItems(dataItems);
            timeDataList.add(timeData);
        }

        result.setTimeDataList(timeDataList);
        return result;
    }

    /**
     * 计算个人或班组维度的时间维度结果
     */
    private TimeBasedPerformanceResult calculatePersonalOrTeamTimeBasedResult(PerformanceDimensionParamDto param, Set<Long> ids) {
        TimeBasedPerformanceResult result = new TimeBasedPerformanceResult();

        // 计算时间分段
        List<LargeScreenDateUtils.DateRange> timeRanges = new ArrayList<>();
        List<String> timeAxis = new ArrayList<>();

        LocalDate startLocalDate = dateToLocalDate(param.getStartTime());
        LocalDate endLocalDate = dateToLocalDate(param.getEndTime());
        if (startLocalDate == null || endLocalDate == null) {
            return result;
        }
        long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(startLocalDate, endLocalDate);

        // 根据时间跨度选择分段粒度
        createTimeSegments(startLocalDate, endLocalDate, daysBetween, timeRanges, timeAxis);

        result.setTimeAxis(timeAxis);

        // 预加载所有时间段的数据
        Map<String, List<PerformanceDimensionResult>> map = new HashMap<>();

        preloadTimeSegmentData(timeRanges, param.getDimension(), map);

        // 构建时间维度数据
        List<TimeBasedPerformanceResult.TimeData> timeDataList = new LinkedList<>();

        for (int i = 0; i < timeRanges.size(); i++) {
            LargeScreenDateUtils.DateRange range = timeRanges.get(i);
            String timeLabel = timeAxis.get(i);
            String timeKey = getTimeRangeKey(range);

            TimeBasedPerformanceResult.TimeData timeData = new TimeBasedPerformanceResult.TimeData();
            timeData.setTimeLabel(timeLabel);

            List<TimeBasedPerformanceResult.DataItem> dataItems = new ArrayList<>();


            // 为每个人员/班组计算该时间段的数据
            Map<Long, String> nameMap;
            if (param.getDimension() == 1) {
                nameMap = getUserNickNameMap(new ArrayList<>(ids));
            } else {
                nameMap = getDeptNameMap(new ArrayList<>(ids));
            }
            for (Long id : ids) {
                String name = nameMap.get(id);
                if (name == null) continue;

                BigDecimal value = getDimensionValueFromPreloadedData(id, map.get(timeKey), param.getResultField());

                TimeBasedPerformanceResult.DataItem dataItem = new TimeBasedPerformanceResult.DataItem();
                dataItem.setId(id);
                dataItem.setName(name);
                dataItem.setValue(value);
                dataItem.setDisplayValue(formatScoreOnly(value));
                dataItems.add(dataItem);
            }

            timeData.setDataItems(dataItems);
            timeDataList.add(timeData);
        }

        result.setTimeDataList(timeDataList);
        return result;
    }

    /**
     * 填充科室和班级信息
     */
    private void enrichDeptAndClassInfo(TimeBasedPerformanceResult result, PerformanceDimensionParamDto param) {
        // 只处理人员维度和班组维度
        if (param.getDimension() == null || param.getDimension() == 4) {
            return;
        }

        List<TimeBasedPerformanceResult.TimeData> timeDataList = result.getTimeDataList();
        if (timeDataList == null || timeDataList.isEmpty()) {
            return;
        }

        // 获取第一个时间点的所有 ID
        List<TimeBasedPerformanceResult.DataItem> firstTimeData = timeDataList.get(0).getDataItems();
        if (firstTimeData == null || firstTimeData.isEmpty()) {
            return;
        }

        // 收集所有需要查询的 ID
        Set<Long> ids = firstTimeData.stream()
                .map(TimeBasedPerformanceResult.DataItem::getId)
                .collect(Collectors.toSet());

        // 预加载这些 ID 的信息
        Map<Long, SysUser> userMap = new HashMap<>();
        Map<Long, SysDept> deptMap = new HashMap<>();

        if (param.getDimension() == 1) {
            // 人员维度：加载用户和部门信息
            for (Long id : ids) {
                SysUser user = userMapper.selectUserById(id);
                if (user != null) {
                    userMap.put(id, user);
                }
            }
            // 加载所有部门信息用于查找班组
            List<SysDept> allDepts = sysDeptService.selectChildrenDeptById(DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId())));
            for (SysDept dept : allDepts) {
                deptMap.put(dept.getDeptId(), dept);
            }
        } else if (param.getDimension() == 2 || param.getDimension() == 3) {
            // 班组维度：加载部门信息
            List<SysDept> allDepts = sysDeptService.selectChildrenDeptById(DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId())));
            for (SysDept dept : allDepts) {
                deptMap.put(dept.getDeptId(), dept);
            }
        }

        // 为所有时间点的数据填充科室和班级信息
        for (TimeBasedPerformanceResult.TimeData timeData : timeDataList) {
            for (TimeBasedPerformanceResult.DataItem item : timeData.getDataItems()) {
                if (param.getDimension() == 1) {
                    // 人员维度
                    SysUser user = userMap.get(item.getId());
                    if (user != null) {
                        Long deptId = user.getDeptId();
                        if (deptId != null) {
                            SysDept dept = deptMap.get(deptId);
                            if (dept != null) {
                                item.setClassName(dept.getDeptName());
                                if (dept.getParentId() != null) {
                                    SysDept parentDept = deptMap.get(dept.getParentId());
                                    if (parentDept != null) {
                                        item.setDeptName(parentDept.getDeptName());
                                        if (parentDept.getParentId() != null) {
                                            SysDept brigadeDept = deptMap.get(parentDept.getParentId());
                                            if (brigadeDept != null) {
                                                item.setBrigadeName(brigadeDept.getDeptName());
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else if (param.getDimension() == 2) {
                    // 班组维度
                    SysDept dept = deptMap.get(item.getId());
                    if (dept != null) {
                        if (dept.getParentId() != null) {
                            SysDept parentDept = deptMap.get(dept.getParentId());
                            if (parentDept != null) {
                                item.setDeptName(parentDept.getDeptName());
                                if (parentDept.getParentId() != null) {
                                    SysDept brigadeDept = deptMap.get(parentDept.getParentId());
                                    if (brigadeDept != null) {
                                        item.setBrigadeName(brigadeDept.getDeptName());
                                    }
                                }
                            }
                        }
                    }
                } else if (param.getDimension() == 3) {
                    // 科室维度
                    SysDept dept = deptMap.get(item.getId());
                    if (dept != null) {
                        if (dept.getParentId() != null) {
                            SysDept parentDept = deptMap.get(dept.getParentId());
                            if (parentDept != null) {
                                item.setBrigadeName(parentDept.getDeptName());
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 创建时间分段
     */
    private void createTimeSegments(LocalDate startLocalDate, LocalDate endLocalDate, long daysBetween,
                                    List<LargeScreenDateUtils.DateRange> timeRanges, List<String> timeAxis) {
        //按月分段
        LocalDate current = startLocalDate.withDayOfMonth(1);
        while (!current.isAfter(endLocalDate)) {
            LocalDate monthEnd = current.plusMonths(1).minusDays(1);
            if (monthEnd.isAfter(endLocalDate)) {
                monthEnd = endLocalDate;
            }
            LargeScreenDateUtils.DateRange range = new LargeScreenDateUtils.DateRange(
                    Date.from(current.atStartOfDay(ZoneId.systemDefault()).toInstant()),
                    Date.from(monthEnd.atStartOfDay(ZoneId.systemDefault()).toInstant())
            );
            timeRanges.add(range);
            timeAxis.add(DateUtils.parseDateToStr("yyyy-MM", range.getStartDate()));
            current = current.plusMonths(1);
        }
    }

    /**
     * 预加载时间分段数据
     */
    private void preloadTimeSegmentData(List<LargeScreenDateUtils.DateRange> timeRanges, int dimension,
                                        Map<String, List<PerformanceDimensionResult>> map) {
        for (LargeScreenDateUtils.DateRange range : timeRanges) {
            PerformanceMetricsParamDto param = new PerformanceMetricsParamDto();
            param.setStartTime(range.getStartDate());
            param.setEndTime(DateUtils.addDays(range.getEndDate(), 1));
            param.setDimension(dimension);
            List<PerformanceDimensionResult> performanceDimensionResults = calculateCurrentPeriodResults(param);
            String timeKey = getTimeRangeKey(range);
            map.put(timeKey, performanceDimensionResults);

        }
    }

    /**
     * 对数据项进行排序
     */
    private void sortDataItems(List<TimeBasedPerformanceResult.DataItem> dataItems, PerformanceDimensionParamDto param) {
        Comparator<TimeBasedPerformanceResult.DataItem> comparator =
                Comparator.comparing(TimeBasedPerformanceResult.DataItem::getValue,
                        Comparator.nullsFirst(BigDecimal::compareTo));

        if (Integer.valueOf(2).equals(param.getSortOrder())) {
            comparator = comparator.reversed(); // 降序
        }

        dataItems.sort(comparator);
    }

    /**
     * 按进步值对时间数据进行排序和限制（进步维度）
     * 进步值 = 最后一个时间点的值 - 第一个时间点的值
     */
    private void sortAndLimitDataItemsByProgress(List<TimeBasedPerformanceResult.TimeData> timeDataList, PerformanceDimensionParamDto param) {
        if (timeDataList == null || timeDataList.size() < 2) {
            return;
        }

        // 获取第一个和最后一个时间点的数据
        List<TimeBasedPerformanceResult.DataItem> firstTimeData = timeDataList.get(0).getDataItems();
        List<TimeBasedPerformanceResult.DataItem> lastTimeData = timeDataList.get(timeDataList.size() - 1).getDataItems();

        Map<Long, TimeBasedPerformanceResult.DataItem> progressMap = new HashMap<>();

        for (TimeBasedPerformanceResult.DataItem firstItem : firstTimeData) {
            for (TimeBasedPerformanceResult.DataItem lastItem : lastTimeData) {
                if (firstItem.getId().equals(lastItem.getId())) {
                    BigDecimal firstValue = firstItem.getValue() != null ? firstItem.getValue() : BigDecimal.ZERO;
                    BigDecimal lastValue = lastItem.getValue() != null ? lastItem.getValue() : BigDecimal.ZERO;
                    BigDecimal progress = lastValue.subtract(firstValue);
                    TimeBasedPerformanceResult.DataItem dataItem = new TimeBasedPerformanceResult.DataItem();
                    dataItem.setId(firstItem.getId());
                    dataItem.setName(firstItem.getName());
                    dataItem.setValue(progress);
                    progressMap.put(firstItem.getId(), dataItem);
                    break;
                }
            }
        }

        // 对第一个时间点的数据按进步值排序
        firstTimeData.sort((item1, item2) -> {
            TimeBasedPerformanceResult.DataItem dataItem = progressMap.get(item1.getId());
            BigDecimal progress1 = dataItem != null ? dataItem.getValue() : BigDecimal.ZERO;
            TimeBasedPerformanceResult.DataItem dataItem1 = progressMap.get(item2.getId());
            BigDecimal progress2 = dataItem1 != null ? dataItem1.getValue() : BigDecimal.ZERO;
            int compareResult = progress2.compareTo(progress1);
            if (compareResult == 0) {
                return item1.getName().compareTo(item2.getName());
            }
            return compareResult;
        });

        // 限制数量
        int limit = 5;
        if (firstTimeData.size() > limit) {
            if (Integer.valueOf(1).equals(param.getSortOrder())) {
                // 升序：取进步最慢的后五名
                firstTimeData.subList(0, firstTimeData.size() - limit).clear();
            } else {
                // 降序：取进步最快的前五名
                firstTimeData.subList(limit, firstTimeData.size()).clear();
            }
        }

        Set<Long> selectedIds = firstTimeData.stream()
                .map(TimeBasedPerformanceResult.DataItem::getId)
                .collect(Collectors.toSet());

        for (TimeBasedPerformanceResult.TimeData timeData : timeDataList) {
            timeData.setDataItems(
                    timeData.getDataItems().stream()
                            .filter(item -> selectedIds.contains(item.getId()))
                            .collect(Collectors.toList())
            );
        }
    }

    /**
     * 按平均值对时间数据进行排序和限制（总分维度）
     * 平均值 = 所有时间点值的平均
     */
    private void sortAndLimitDataItemsByAverage(List<TimeBasedPerformanceResult.TimeData> timeDataList, PerformanceDimensionParamDto param) {
        if (timeDataList == null || timeDataList.isEmpty()) {
            return;
        }

        // 计算每个人的平均值
        Map<Long, BigDecimal> averageMap = new HashMap<>();

        // 统计每个人在所有时间点的值
        Map<Long, List<BigDecimal>> idToValuesMap = new HashMap<>();

        for (TimeBasedPerformanceResult.TimeData timeData : timeDataList) {
            for (TimeBasedPerformanceResult.DataItem item : timeData.getDataItems()) {
                idToValuesMap.computeIfAbsent(item.getId(), k -> new ArrayList<>())
                        .add(item.getValue() != null ? item.getValue() : BigDecimal.ZERO);
            }
        }

        // 计算平均值
        idToValuesMap.forEach((id, values) -> {
            BigDecimal sum = values.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal average = sum.divide(BigDecimal.valueOf(values.size()), 2, RoundingMode.HALF_UP);
            averageMap.put(id, average);
        });

        List<TimeBasedPerformanceResult.DataItem> firstTimeData = timeDataList.get(0).getDataItems();

        // 按平均值排序
        firstTimeData.sort((item1, item2) -> {
            BigDecimal avg1 = averageMap.getOrDefault(item1.getId(), BigDecimal.ZERO);
            BigDecimal avg2 = averageMap.getOrDefault(item2.getId(), BigDecimal.ZERO);
            int compareResult = avg2.compareTo(avg1); // 降序排列
            if (compareResult == 0) {
                compareResult = item1.getName().compareTo(item2.getName());
            }
            return compareResult;
        });

        // 限制数量
        int limit = 5;
        if (firstTimeData.size() > limit) {
            if (Integer.valueOf(1).equals(param.getSortOrder())) {
                // 升序：取平均分最低的后五名
                firstTimeData.subList(0, firstTimeData.size() - limit).clear();
            } else {
                // 降序：取平均分最高的前五名
                firstTimeData.subList(limit, firstTimeData.size()).clear();
            }
        }

        // 更新所有时间点的数据，只保留选中的项目
        Set<Long> selectedIds = firstTimeData.stream()
                .map(TimeBasedPerformanceResult.DataItem::getId)
                .collect(Collectors.toSet());

        for (TimeBasedPerformanceResult.TimeData timeData : timeDataList) {
            timeData.setDataItems(
                    timeData.getDataItems().stream()
                            .filter(item -> selectedIds.contains(item.getId()))
                            .collect(Collectors.toList())
            );
        }
    }


    /**
     * 参数校验和设置默认值
     */
    private void validateAndSetDefaults(PerformanceDimensionParamDto param) {
        if (param.getDimension() == null) {
            param.setDimension(1); // 默认个人维度
        }
        if (param.getSortOrder() == null) {
            param.setSortOrder(2); // 默认降序
        }
        if (param.getResultField() == null) {
            param.setResultField("totalScore"); // 默认总分排序
        }
        if (param.getDimensionType() == null) {
            param.setDimensionType(1); // 默认总分
        }
    }

    /**
     * 计算当前时间段的维度结果
     */
    private List<PerformanceDimensionResult> calculateCurrentPeriodResults(PerformanceMetricsParamDto param) {
        List<PerformanceDimensionResult> results = new ArrayList<>();

        BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
        dto.setStartDate(param.getStartTime());
        dto.setEndDate(param.getEndTime());

        // 根据维度获取对应的数据
        switch (param.getDimension()) {
            case 1: // 个人维度
                results.addAll(calculateIndividualResults(dto, param));
                break;
            case 2: // 班组维度
                results.addAll(calculateTeamResults(dto, param));
                break;
            case 3: // 科室维度
                results.addAll(calculateDepartmentResults(dto, param));
                break;
            case 4: // 大队维度
                results.addAll(calculateBrigadeResults(dto, param));
                break;
            default:
                throw new IllegalArgumentException("不支持的维度类型: " + param.getDimension());
        }

        return results;
    }


    /**
     * 计算个人维度结果
     */
    private List<PerformanceDimensionResult> calculateIndividualResults(BaseLargeScreenQueryParamDto dto, PerformanceMetricsParamDto param) {
        List<PerformanceDimensionResult> results = new ArrayList<>();

        // 获取各项指标数据
        List<SeizureEfficiencyRankDto> seizureData = getSeizureEfficiencyData(dto, 1);
        List<CheckEfficiencyRankDto> inspectionData = getInspectionData(dto, 1);
        Map<Long, BigDecimal> trainingData = getTrainingData(dto, 1);

        // 标准化处理
        List<NormalizedData> normalizedList = normalizeIndividualData(seizureData, inspectionData, trainingData);

        // 转换为结果对象
        for (NormalizedData normalized : normalizedList) {
            PerformanceDimensionResult result = new PerformanceDimensionResult();
            result.setId(normalized.id);
            result.setName(normalized.name);
            result.setSeizureEfficiency(normalized.seizureEfficiency);
            result.setInspectionPassRate(normalized.inspectionPassRate);
            result.setTrainingScore(normalized.trainingScore);
            result.setTotalScore(normalized.totalScore);
            results.add(result);
        }

        return results;
    }

    /**
     * 计算班组维度结果
     */
    private List<PerformanceDimensionResult> calculateTeamResults(BaseLargeScreenQueryParamDto dto, PerformanceMetricsParamDto param) {
        List<PerformanceDimensionResult> results = new ArrayList<>();

        // 获取各项指标数据
        List<SeizureEfficiencyRankDto> seizureData = getSeizureEfficiencyData(dto, 2);
        List<CheckEfficiencyRankDto> inspectionData = getInspectionData(dto, 2);
        Map<Long, BigDecimal> trainingData = getTrainingData(dto, 2);

        // 标准化处理
        List<NormalizedData> normalizedList = normalizeTeamData(seizureData, inspectionData, trainingData);

        // 转换为结果对象
        for (NormalizedData normalized : normalizedList) {
            PerformanceDimensionResult result = new PerformanceDimensionResult();
            result.setId(normalized.id);
            result.setName(normalized.name);
            result.setSeizureEfficiency(normalized.seizureEfficiency);
            result.setInspectionPassRate(normalized.inspectionPassRate);
            result.setTrainingScore(normalized.trainingScore);
            result.setTotalScore(normalized.totalScore);
            results.add(result);
        }

        return results;
    }

    /**
     * 计算科室维度结果
     */
    private List<PerformanceDimensionResult> calculateDepartmentResults(BaseLargeScreenQueryParamDto dto, PerformanceMetricsParamDto param) {
        List<PerformanceDimensionResult> results = new ArrayList<>();

        // 获取各项指标数据
        List<SeizureEfficiencyRankDto> seizureData = getSeizureEfficiencyData(dto, 3);
        List<CheckEfficiencyRankDto> inspectionData = getInspectionData(dto, 3);
        Map<Long, BigDecimal> trainingData = getTrainingData(dto, 3);

        // 标准化处理
        List<NormalizedData> normalizedList = normalizeDepartmentData(seizureData, inspectionData, trainingData);

        // 转换为结果对象
        for (NormalizedData normalized : normalizedList) {
            PerformanceDimensionResult result = new PerformanceDimensionResult();
            result.setId(normalized.id);
            result.setName(normalized.name);
            result.setSeizureEfficiency(normalized.seizureEfficiency);
            result.setInspectionPassRate(normalized.inspectionPassRate);
            result.setTrainingScore(normalized.trainingScore);
            result.setTotalScore(normalized.totalScore);
            results.add(result);
        }

        return results;
    }

    /**
     * 计算大队维度结果
     */
    private List<PerformanceDimensionResult> calculateBrigadeResults(BaseLargeScreenQueryParamDto dto, PerformanceMetricsParamDto param) {
        List<PerformanceDimensionResult> results = new ArrayList<>();

        // 获取各项指标数据
        List<SeizureEfficiencyRankDto> seizureData = getSeizureEfficiencyData(dto, 4);
        List<CheckEfficiencyRankDto> inspectionData = getInspectionData(dto, 4);
        Map<Long, BigDecimal> trainingData = getTrainingData(dto, 4);

        // 标准化处理
        List<NormalizedData> normalizedList = normalizeDepartmentData(seizureData, inspectionData, trainingData);

        // 转换为结果对象
        for (NormalizedData normalized : normalizedList) {
            PerformanceDimensionResult result = new PerformanceDimensionResult();
            result.setId(normalized.id);
            result.setName(normalized.name);
            result.setSeizureEfficiency(normalized.seizureEfficiency);
            result.setInspectionPassRate(normalized.inspectionPassRate);
            result.setTrainingScore(normalized.trainingScore);
            result.setTotalScore(normalized.totalScore);
            results.add(result);
        }

        return results;
    }

    /**
     * 获取查获效率数据
     */
    private List<SeizureEfficiencyRankDto> getSeizureEfficiencyData(BaseLargeScreenQueryParamDto dto, Integer dimension) {
        SeizureEfficiencyDto result = seizureEfficiencyService.getSeizureEfficiency(dto, dimension);
        switch (dimension) {
            case 1:
                return result.getIndividualRankList();
            case 2:
                return result.getTeamRankList();
            case 3:
                return result.getDepartmentRankList();
            case 4:
                return result.getBrigadeRankList();
            default:
                return new ArrayList<>();
        }
    }

    /**
     * 获取巡检合格率数据
     */
    private List<CheckEfficiencyRankDto> getInspectionData(BaseLargeScreenQueryParamDto dto, Integer dimension) {
        CheckEfficiencyDto result = checkEfficiencyService.getCheckEfficiency(dto, dimension);
        switch (dimension) {
            case 1:
                return result.getIndividualRankList();
            case 2:
                return result.getTeamRankList();
            case 3:
                return result.getDepartmentRankList();
            case 4:
                return result.getBrigadeRankList();
            default:
                return new ArrayList<>();
        }
    }

    /**
     * 获取培训数据（抽问抽答正确率）
     */
    private Map<Long, BigDecimal> getTrainingData(BaseLargeScreenQueryParamDto dto, Integer dimension) {
        try {
            switch (dimension) {
                case 1: // 个人维度
                    return getIndividualTrainingData(dto);
                case 2: // 班组维度
                    return getTeamTrainingData(dto);
                case 3: // 科室维度
                    return getDepartmentTrainingData(dto);
                case 4: // 大队维度
                    return getBrigadeTrainingData(dto);
                default:
                    return new HashMap<>();
            }
        } catch (Exception e) {
            log.error("获取培训数据失败", e);
            return new HashMap<>();
        }
    }

    /**
     * 获取个人维度培训数据
     */
    private Map<Long, BigDecimal> getIndividualTrainingData(BaseLargeScreenQueryParamDto dto) {
        Map<Long, BigDecimal> result = new HashMap<>();

        try {
            List<Long> userIds = getAllInspectorUserIds();
            if (userIds.isEmpty()) {
                return result;
            }

            // 批量查询个人正确率
            Map<Long, BigDecimal> accuracyMap = accuracyStatisticsService.getUsersAccuracyMap(userIds,
                    formatDate(dto.getStartDate()), formatDate(dto.getEndDate()));

            accuracyMap.forEach((userId, accuracy) -> {
                if (accuracy != null) {
                    result.put(userId, accuracy);
                }
            });

            return result;
        } catch (Exception e) {
            log.error("获取个人培训数据失败", e);
            return result;
        }
    }

    /**
     * 获取班组维度培训数据
     */
    private Map<Long, BigDecimal> getTeamTrainingData(BaseLargeScreenQueryParamDto dto) {
        Map<Long, BigDecimal> result = new HashMap<>();

        try {
            // 查询所有班组
            Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
            List<SysDept> teams = sysDeptService.selectChildrenDeptById(topSiteId).stream()
                    .filter(dept -> DeptTypeEnum.TEAMS.getCode().equals(dept.getDeptType()))
                    .collect(Collectors.toList());

            if (teams.isEmpty()) return result;
            List<Long> teamIds = teams.stream().map(SysDept::getDeptId).collect(Collectors.toList());
            Map<Long, BigDecimal> teamData = accuracyStatisticsService.getTeamsAccuracyMap(teamIds, formatDate(dto.getStartDate()), formatDate(dto.getEndDate()));
            teamData.forEach((teamId, accuracy) -> {
                if (accuracy != null) {
                    result.put(teamId, accuracy);
                }
            });

            return result;
        } catch (Exception e) {
            log.error("获取班组培训数据失败", e);
            return result;
        }
    }

    /**
     * 获取科室维度培训数据
     */
    private Map<Long, BigDecimal> getDepartmentTrainingData(BaseLargeScreenQueryParamDto dto) {
        Map<Long, BigDecimal> result = new HashMap<>();

        try {
            // 查询所有科室
            Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
            List<SysDept> departments = sysDeptService.selectChildrenDeptById(topSiteId).stream()
                    .filter(dept -> DeptTypeEnum.MANAGER.getCode().equals(dept.getDeptType()))
                    .collect(Collectors.toList());

            if (departments.isEmpty()) return result;

            List<Long> deptIds = departments.stream().map(SysDept::getDeptId).collect(Collectors.toList());
            Map<Long, BigDecimal> deptData = accuracyStatisticsService.getDeptsAccuracyMap(deptIds, formatDate(dto.getStartDate()), formatDate(dto.getEndDate()));

            if (deptData != null) {
                deptData.forEach((deptId, accuracy) -> {
                    if (accuracy != null) {
                        result.put(deptId, accuracy);
                    }
                });
            }

            return result;
        } catch (Exception e) {
            log.error("获取科室培训数据失败", e);
            return result;
        }
    }

    /**
     * 获取大队维度培训数据
     */
    private Map<Long, BigDecimal> getBrigadeTrainingData(BaseLargeScreenQueryParamDto dto) {
        Map<Long, BigDecimal> result = new HashMap<>();

        try {
            // 查询所有科室
            Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
            List<SysDept> brigades = sysDeptService.selectChildrenDeptById(topSiteId).stream()
                    .filter(dept -> DeptTypeEnum.BRIGADE.getCode().equals(dept.getDeptType()))
                    .collect(Collectors.toList());

            if (brigades.isEmpty()) return result;

            List<Long> deptIds = brigades.stream().map(SysDept::getDeptId).collect(Collectors.toList());
            Map<Long, BigDecimal> deptData = accuracyStatisticsService.getDeptsAccuracyMap(deptIds, formatDate(dto.getStartDate()), formatDate(dto.getEndDate()));

            if (deptData != null) {
                deptData.forEach((deptId, accuracy) -> {
                    if (accuracy != null) {
                        result.put(deptId, accuracy);
                    }
                });
            }

            return result;
        } catch (Exception e) {
            log.error("获取大队培训数据失败", e);
            return result;
        }
    }

    /**
     * 将Date转换为LocalDate
     */
    private LocalDate dateToLocalDate(Date date) {
        if (date == null) return null;
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }


    /**
     * 标准化个人数据
     */
    private List<NormalizedData> normalizeIndividualData(
            List<SeizureEfficiencyRankDto> seizureData,
            List<CheckEfficiencyRankDto> inspectionData,
            Map<Long, BigDecimal> trainingData) {

        List<NormalizedData> results = new ArrayList<>();

        // 合并所有用户ID
        Set<Long> allUserIds = new HashSet<>();
        seizureData.forEach(item -> allUserIds.add(item.getId()));
        inspectionData.forEach(item -> allUserIds.add(item.getId()));

        Map<Long, String> nameMap = getUserNickNameMap(new ArrayList<>(allUserIds));
        for (Long userId : allUserIds) {
            NormalizedData normalized = new NormalizedData();
            normalized.id = userId;
            // 获取用户名
            String userName = nameMap.get(userId);
            normalized.name = userName != null ? userName : "未知用户";

            // 获取各项指标原始值
            BigDecimal seizureRaw = seizureData.stream().filter(item -> item.getId().equals(userId)).map(SeizureEfficiencyRankDto::getEfficiency).findFirst().orElse(BigDecimal.ZERO);
            BigDecimal inspectionRaw = inspectionData.stream().filter(item -> item.getId().equals(userId)).map(CheckEfficiencyRankDto::getPassRate).findFirst().orElse(BigDecimal.ZERO);
            BigDecimal trainingRaw = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeFromMap(userId, trainingData)));

            // 标准化处理（线性归一化）
            normalized.seizureEfficiency = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeValue(seizureRaw,
                    getMinValue(seizureData, SeizureEfficiencyRankDto::getEfficiency),
                    getMaxValue(seizureData, SeizureEfficiencyRankDto::getEfficiency))));

            normalized.inspectionPassRate = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeValue(inspectionRaw,
                    getMinValue(inspectionData, CheckEfficiencyRankDto::getPassRate),
                    getMaxValue(inspectionData, CheckEfficiencyRankDto::getPassRate))));

            // 计算总分
            normalized.totalScore = calculateWithWeights(normalized.seizureEfficiency, "w1")
                    .add(calculateWithWeights(normalized.inspectionPassRate, "w2"))
                    .add(calculateWithWeights(trainingRaw, "w3"));

            normalized.trainingScore = trainingRaw.multiply(new BigDecimal(100));
            normalized.seizureEfficiency = normalized.seizureEfficiency.multiply(new BigDecimal(100));
            normalized.inspectionPassRate = normalized.inspectionPassRate.multiply(new BigDecimal(100));

            results.add(normalized);
        }

        return results;
    }

    /**
     * 标准化班组数据
     */
    private List<NormalizedData> normalizeTeamData(
            List<SeizureEfficiencyRankDto> seizureData,
            List<CheckEfficiencyRankDto> inspectionData,
            Map<Long, BigDecimal> trainingData) {

        return normalizeGroupData(seizureData, inspectionData, trainingData, "班组");
    }

    /**
     * 标准化科室数据
     */
    private List<NormalizedData> normalizeDepartmentData(
            List<SeizureEfficiencyRankDto> seizureData,
            List<CheckEfficiencyRankDto> inspectionData,
            Map<Long, BigDecimal> trainingData) {

        return normalizeGroupData(seizureData, inspectionData, trainingData, "科室");
    }

    /**
     * 标准化组数据通用方法
     */
    private List<NormalizedData> normalizeGroupData(
            List<SeizureEfficiencyRankDto> seizureData,
            List<CheckEfficiencyRankDto> inspectionData,
            Map<Long, BigDecimal> trainingData,
            String groupType) {

        List<NormalizedData> results = new ArrayList<>();

        // 合并所有组ID
        Set<Long> allGroupIds = new HashSet<>();
        seizureData.forEach(item -> allGroupIds.add(item.getId()));
        inspectionData.forEach(item -> allGroupIds.add(item.getId()));

        Map<Long, String> nameMap = getDeptNameMap(new ArrayList<>(allGroupIds));
        for (Long groupId : allGroupIds) {
            NormalizedData normalized = new NormalizedData();
            normalized.id = groupId;

            // 获取组名称
            String groupName = nameMap.get(groupId);
            normalized.name = groupName != null ? groupName : "未知" + groupType;

            // 获取各项指标原始值
            BigDecimal seizureRaw = seizureData.stream().filter(item -> item.getId().equals(groupId)).map(SeizureEfficiencyRankDto::getEfficiency).findFirst().orElse(BigDecimal.ZERO);
            BigDecimal inspectionRaw = inspectionData.stream().filter(item -> item.getId().equals(groupId)).map(CheckEfficiencyRankDto::getPassRate).findFirst().orElse(BigDecimal.ZERO);
            BigDecimal trainingRaw = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeFromMap(groupId, trainingData)));


            // 标准化处理
            normalized.seizureEfficiency = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeValue(seizureRaw,
                    getMinValue(seizureData, SeizureEfficiencyRankDto::getEfficiency),
                    getMaxValue(seizureData, SeizureEfficiencyRankDto::getEfficiency))));

            normalized.inspectionPassRate = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeValue(inspectionRaw,
                    getMinValue(inspectionData, CheckEfficiencyRankDto::getPassRate),
                    getMaxValue(inspectionData, CheckEfficiencyRankDto::getPassRate))));

            // 计算总分
            normalized.totalScore = calculateWithWeights(normalized.seizureEfficiency, "w1")
                    .add(calculateWithWeights(normalized.inspectionPassRate, "w2"))
                    .add(calculateWithWeights(trainingRaw, "w3"));

            normalized.trainingScore = trainingRaw.multiply(new BigDecimal(100));
            normalized.seizureEfficiency = normalized.seizureEfficiency.multiply(new BigDecimal(100));
            normalized.inspectionPassRate = normalized.inspectionPassRate.multiply(new BigDecimal(100));

            results.add(normalized);
        }

        return results;
    }


    /**
     * 从正确率Map中归一化指定ID的值
     * 归一化公式：(当前值 - min) / (max - min)，与查获效率的归一化逻辑一致
     */
    private BigDecimal normalizeFromMap(Long id, Map<Long, BigDecimal> accuracyMap) {
        if (accuracyMap == null || accuracyMap.isEmpty()) {
            return BigDecimal.ZERO;
        }
        BigDecimal value = accuracyMap.getOrDefault(id, BigDecimal.ZERO);
        BigDecimal min = accuracyMap.values().stream().min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal max = accuracyMap.values().stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal difference = max.subtract(min);
        return difference.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : value.subtract(min).divide(difference, 2, RoundingMode.HALF_UP);
    }

    /**
     * 格式化仅得分显示
     */
    private String formatScoreOnly(BigDecimal score) {
        if (score == null) score = BigDecimal.ZERO;
        return score.setScale(0, RoundingMode.HALF_UP).toString() + "/--%";
    }


    private String getUserNickName(Long userId) {
        SysUser user = userMapper.selectUserById(userId);
        return user.getNickName();
    }

    private String getGroupName(Long groupId) {
        SysDept sysDept = sysDeptService.selectDeptById(groupId);
        return sysDept.getDeptName();
    }

    private BigDecimal getSeizureEfficiencyById(List<PerformanceDimensionResult> dataList, Long id) {
        return dataList.stream()
                .filter(item -> item.getId().equals(id))
                .map(PerformanceDimensionResult::getSeizureEfficiency)
                .findFirst()
                .orElse(BigDecimal.ZERO);
    }


    private BigDecimal getInspectionRateById(List<PerformanceDimensionResult> dataList, Long id) {
        return dataList.stream()
                .filter(item -> item.getId().equals(id))
                .map(PerformanceDimensionResult::getInspectionPassRate)
                .findFirst()
                .orElse(BigDecimal.ZERO);
    }

    private BigDecimal getTrainingScoreById(List<PerformanceDimensionResult> dataList, Long id) {
        return dataList.stream()
                .filter(item -> item.getId().equals(id))
                .map(PerformanceDimensionResult::getTrainingScore)
                .findFirst()
                .orElse(BigDecimal.ZERO);
    }

    private BigDecimal getTotalScoreById(List<PerformanceDimensionResult> dataList, Long id) {
        return dataList.stream()
                .filter(item -> item.getId().equals(id))
                .map(PerformanceDimensionResult::getTotalScore)
                .findFirst()
                .orElse(BigDecimal.ZERO);
    }


    private <T> BigDecimal getMinValue(List<T> dataList, java.util.function.Function<T, BigDecimal> getter) {
        return dataList.stream()
                .map(getter)
                .filter(Objects::nonNull)
                .min(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO);
    }

    private <T> BigDecimal getMaxValue(List<T> dataList, java.util.function.Function<T, BigDecimal> getter) {
        return dataList.stream()
                .map(getter)
                .filter(Objects::nonNull)
                .max(BigDecimal::compareTo)
                .orElse(BigDecimal.ONE);
    }

    private BigDecimal normalizeValue(BigDecimal rawValue, BigDecimal minValue, BigDecimal maxValue) {
        if (rawValue == null) rawValue = BigDecimal.ZERO;
        BigDecimal range = maxValue.subtract(minValue);
        if (range.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        if (rawValue.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal divide = rawValue.subtract(minValue)
                .divide(range, 2, RoundingMode.HALF_UP);

        return divide;
    }


    /**
     * 标准化值处理
     */
    private BigDecimal calculateWithWeights(BigDecimal value, String w) {
        BigDecimal bigDecimal = value != null ? value : BigDecimal.ZERO;
        GeometricMeanUtils.CalculationResult calculationResult = GeometricMeanUtils.calculateWithWeights();
        double d = 0;
        if ("w1".equals(w)) {
            d = calculationResult.getW1();
        }
        if ("w2".equals(w)) {
            d = calculationResult.getW2();
        }
        if ("w3".equals(w)) {
            d = calculationResult.getW3();
        }
        return bigDecimal.multiply(new BigDecimal(d)).setScale(4, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
    }

    /**
     * 标准化数据内部类
     */
    private static class NormalizedData {
        Long id;
        String name;
        BigDecimal seizureEfficiency;
        BigDecimal inspectionPassRate;
        BigDecimal trainingScore;
        BigDecimal totalScore;
    }

    /**
     * 获取所有安检员用户ID
     */
    private List<Long> getAllInspectorUserIds() {
        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
        if (topSiteId == null) {
            throw new ServiceException("无法找到有效的站点信息");
        }
        List<SysUser> sysUserTempList = userMapper.selectUserByDeptId(topSiteId);
        List<SysUser> users = sysUserTempList.stream().filter(item -> item.getRoles().stream().anyMatch(sysRole -> RoleTypeEnum.banzuzhang.getCode().equals(sysRole.getRoleKey()) || RoleTypeEnum.SecurityCheck.getCode().equals(sysRole.getRoleKey()))).collect(Collectors.toList());

        if (users.isEmpty()) return new ArrayList<>();

        return users.stream().map(SysUser::getUserId).collect(Collectors.toList());
    }

    /**
     * 从预加载数据中获取指定维度的值
     */
    private BigDecimal getDimensionValueFromPreloadedData(
            Long id,
            List<PerformanceDimensionResult> map,
            String resultField) {


        switch (resultField) {
            case "seizureEfficiency":
                return getSeizureEfficiencyById(map, id);
            case "inspectionPassRate":
                return getInspectionRateById(map, id);
            case "trainingScore":
                return getTrainingScoreById(map, id);
            default:
                return getTotalScoreById(map, id);
        }
    }

    /**
     * 获取时间范围的唯一键
     */
    private String getTimeRangeKey(LargeScreenDateUtils.DateRange range) {
        return DateUtils.parseDateToStr("yyyy-MM-dd", range.getStartDate()) + "_" +
                DateUtils.parseDateToStr("yyyy-MM-dd", range.getEndDate());
    }

    /**
     * 格式化日期
     */
    private String formatDate(Date date) {
        if (date == null) return null;
        return new java.text.SimpleDateFormat("yyyy-MM-dd").format(date);
    }

    /**
     * 转换查询参数为学习成长查询DTO
     */
    private SysLargeScreenLearningGrowthQueryParamDto convertToLearningGrowthQuery(BaseLargeScreenQueryParamDto dto) {
        SysLargeScreenLearningGrowthQueryParamDto query = new SysLargeScreenLearningGrowthQueryParamDto();
        query.setStartDate(dto.getStartDate());
        query.setEndDate(dto.getEndDate());
        query.setSpecifiedDate(dto.getSpecifiedDate());
        return query;
    }

    /**
     * 获取用户昵称Map
     */
    private Map<Long, String> getUserNickNameMap(List<Long> userIdList) {
        List<SysUser> userList = userMapper.selectByUserIdList(userIdList);
        Map<Long, String> nameMap = userList.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName, (existing, replacement) -> existing));
        return nameMap;
    }

    /**
     * 获取部门名称Map
     */
    private Map<Long, String> getDeptNameMap(List<Long> deptIdList) {
        List<SysDept> deptList = sysDeptService.selectDeptByIdList(deptIdList);
        Map<Long, String> nameMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName, (existing, replacement) -> existing));
        return nameMap;
    }

}



