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

import cn.hutool.core.collection.CollectionUtil;
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.GroupedBoxPlotDataDto;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.dto.PerformanceMetricsParamDto;
import com.sundot.airport.common.dto.PerformanceMetricsResultDto;
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.DeptUtils;
import com.sundot.airport.common.utils.GeometricMeanUtils;
import com.sundot.airport.common.utils.StringUtils;
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.domain.dto.ConcealmentPositionTop1DTO;
import com.sundot.airport.item.domain.dto.ProhibitedItemsTop3DTO;
import com.sundot.airport.item.mapper.ItemLargeScreenMapper;
import com.sundot.airport.item.service.SeizureDistributionService;
import com.sundot.airport.item.service.SeizureEfficiencyService;
import com.sundot.airport.system.mapper.SysDeptMapper;
import com.sundot.airport.system.mapper.SysUserMapper;
import com.sundot.airport.system.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

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

import static com.sundot.airport.common.core.domain.AjaxResult.success;
import static com.sundot.airport.common.utils.SecurityUtils.getDeptId;

/**
 * 绩效指标Controller
 *
 * @author ruoyi
 * @date 2025-07-25
 */
@Slf4j
@RestController
@RequestMapping("/item/performance")
public class PerformanceMetricsController {


    @Autowired
    private SeizureEfficiencyService seizureEfficiencyService;

    @Autowired
    private ICheckEfficiencyService checkEfficiencyService;


    @Autowired
    private SeizureDistributionService seizureDistributionService;

    @Autowired
    private ISysDeptService sysDeptService;


    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private IAccuracyStatisticsService accuracyStatisticsService;

    @Autowired
    private ItemLargeScreenMapper itemLargeScreenMapper;

    /**
     * 查询查获效率统计
     */
    @GetMapping("/list")
    public AjaxResult list(BaseLargeScreenQueryParamDto dto) {
        SeizureEfficiencyDto result = seizureEfficiencyService.getSeizureEfficiency(dto, null);
        return success(result);
    }

    /**
     * 获取查获数量分布直方图数据
     *
     * @return 直方图数据列表，每个元素包含：组下限、组上限、该组内安检员人数
     */
    @GetMapping("/histogram")
    public AjaxResult getSeizureHistogramData(BaseLargeScreenQueryParamDto dto) {
        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
        if (topSiteId == null) {
            return AjaxResult.error("无法找到有效的站点信息");
        }
        dto.setInspectStationId(topSiteId);
        // 计算查获数量分布
        List<SeizureDistributionService.SeizureHistogramData> result =
                seizureDistributionService.calculateSeizureDistribution(dto);

        return success(result);
    }


    /**
     * 获取查获数量箱线图数据
     *
     * @return 箱线图数据，包含最小观察值、Q1、中位数、Q3、最大观察值、离群点等信息
     */
    @GetMapping("/boxplot")
    public AjaxResult getSeizureBoxPlotData(BaseLargeScreenQueryParamDto dto) {
        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
        if (topSiteId == null) {
            return AjaxResult.error("无法找到有效的站点信息");
        }
        dto.setInspectStationId(topSiteId);
        // 计算查获数量箱线图数据
        List<GroupedBoxPlotDataDto> result = seizureDistributionService.calculateBoxPlotData(dto);

        return success(result);
    }

    /**
     * 查询全站查获违禁品 TOP3
     *
     * @param startDate 查询开始时间
     *                  endDate 查询结束时间
     * @return 违禁品 TOP3 数据，包含物品名称、查获数量、占比
     */
    @GetMapping("/prohibited-top3")
    public AjaxResult getProhibitedItemsTop3(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
                                             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
        try {
            BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
            dto.setStartDate(startDate);
            dto.setEndDate(endDate);
            // 获取当前用户所在站点 ID
            Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
            if (topSiteId == null) {
                return AjaxResult.error("无法找到有效的站点信息");
            }
            dto.setInspectStationId(topSiteId);

            // 查询违禁品 TOP3
            List<ProhibitedItemsTop3DTO> top3List = itemLargeScreenMapper.selectProhibitedItemsTop3(dto);

            // 计算总数和占比
            BigDecimal totalQuantity = itemLargeScreenMapper.getTotalSum(dto);
            for (int i = 0; i < top3List.size(); i++) {
                ProhibitedItemsTop3DTO item = top3List.get(i);
                item.setRank(i + 1);

                // 计算占比
                if (totalQuantity.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal percentage = item.getQuantity()
                            .multiply(new BigDecimal("100"))
                            .divide(totalQuantity, 2, RoundingMode.HALF_UP);
                    item.setPercentage(percentage);
                } else {
                    item.setPercentage(BigDecimal.ZERO);
                }
            }

            return success(top3List);
        } catch (Exception e) {
            log.error("查询全站查获违禁品 TOP3 失败：{}", e.getMessage());
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 查询隐匿重点部位 Top1
     *
     * @param startDate 查询开始时间
     *                  endDate 查询结束时间
     * @return 隐匿重点部位 Top1 数据
     */
    @GetMapping("/concealment-position-top1")
    public AjaxResult getConcealmentPositionTop1(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
                                                 @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
        try {
            BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
            dto.setStartDate(startDate);
            dto.setEndDate(endDate);
            // 获取当前用户所在站点 ID
            Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
            if (topSiteId == null) {
                return AjaxResult.error("无法找到有效的站点信息");
            }
            dto.setInspectStationId(topSiteId);

            // 查询隐匿重点部位 Top1
            List<ConcealmentPositionTop1DTO> top1List = itemLargeScreenMapper.selectConcealmentPositionTop1(dto);

            if (top1List == null || top1List.isEmpty()) {
                return success(new ArrayList<>());
            }

            return success(top1List);
        } catch (Exception e) {
            log.error("查询隐匿重点部位 Top1 失败：{}", e.getMessage());
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 绩效指标列表
     *
     * @param param 查询参数
     * @return 组织/姓名、查获效率、巡检合格率、培训得分、总分
     */
    @PostMapping("/metrics")
    public AjaxResult getPerformanceMetrics(@RequestBody PerformanceMetricsParamDto param) {
        try {
            // 参数校验和默认值设置
            validateAndSetDefaults(param);

            List<PerformanceMetricsResultDto> result = calculatePerformanceMetrics(param);

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

            sortAndRank(result, param);

            return success(result);
        } catch (Exception e) {
            return AjaxResult.error("获取绩效指标失败: " + e.getMessage());
        }
    }


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


        if (result == null || result.isEmpty()) {
            return;
        }

        // 收集所有需要查询的 ID
        Set<Long> ids = result.stream()
                .map(PerformanceMetricsResultDto::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 (PerformanceMetricsResultDto item : result) {
            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 validateAndSetDefaults(PerformanceMetricsParamDto param) {
        if (param.getDimension() == null) {
            param.setDimension(1); // 默认个人维度
        }
        if (param.getSortOrder() == null) {
            param.setSortOrder(2); // 默认降序
        }
    }

    /**
     * 计算绩效指标
     */
    private List<PerformanceMetricsResultDto> calculatePerformanceMetrics(PerformanceMetricsParamDto param) {
        List<PerformanceMetricsResultDto> result = new ArrayList<>();

        if (param.getDimension() == 1) {
            // 个人维度
            result = calculatePersonalMetrics(param);
        } else if (param.getDimension() == 2) {
            // 班组维度
            result = calculateTeamMetrics(param);
        } else if (param.getDimension() == 3) {
            // 科室维度
            result = calculateDepartmentMetrics(param);
        } else if (param.getDimension() == 4) {
            // 大队维度
            result = calculateBrigadeMetrics(param);
        }

        return result;
    }

    /**
     * 计算查获效率
     *
     * @param param
     * @return
     */
    private List<SeizureEfficiencyRankDto> calculateSeizureEfficiency(PerformanceMetricsParamDto param) {
        List<SeizureEfficiencyRankDto> rankList = new ArrayList<>();

        BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
        dto.setStartDate(param.getStartTime());
        dto.setEndDate(param.getEndTime());
        SeizureEfficiencyDto result = seizureEfficiencyService.getSeizureEfficiency(dto, param.getDimension());
        if (param.getDimension() == 1) {
            // 个人维度
            rankList = result.getIndividualRankList();
        } else if (param.getDimension() == 2) {
            // 班组维度
            rankList = result.getTeamRankList();
        } else if (param.getDimension() == 3) {
            // 科室维度
            rankList = result.getDepartmentRankList();
        } else if (param.getDimension() == 4) {
            // 大队维度
            rankList = result.getBrigadeRankList();
        }
        return rankList;
    }


    /**
     * 计算个人绩效指标
     */
    private List<PerformanceMetricsResultDto> calculatePersonalMetrics(PerformanceMetricsParamDto param) {
        List<PerformanceMetricsResultDto> result = new ArrayList<>();

        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
        if (topSiteId == null) {
            throw new ServiceException("无法找到有效的站点信息");
        }

        // 根据大队 ID 筛选
        if (param.getBrigadeId() != null) {
            topSiteId = param.getBrigadeId();
        }

        // 根据科室 ID 筛选
        if (param.getDeptId() != null) {
            topSiteId = param.getDeptId();
        }

        // 根据班组 ID 筛选
        if (param.getTeamId() != null) {
            topSiteId = param.getTeamId();
        }

        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 result;

        // 根据姓名模糊筛选
        if (StringUtils.isNotEmpty(param.getUserName())) {
            users = users.stream()
                    .filter(user -> user.getNickName() != null
                            && user.getNickName().contains(param.getUserName()))
                    .collect(Collectors.toList());
        }

        if (users.isEmpty()) return result;

        //查获效率
        List<SeizureEfficiencyRankDto> rankList = calculateSeizureEfficiency(param);
        //巡检合格率
        List<CheckEfficiencyRankDto> checkRankList = calculateCheckEfficiency(param);

        // 批量查询抽问抽答正确率
        List<Long> userIds = users.stream().map(SysUser::getUserId).collect(Collectors.toList());
        String startDate = formatDate(param.getStartTime());
        String endDate = formatDate(param.getEndTime());
        Map<Long, BigDecimal> accuracyMap = accuracyStatisticsService.getUsersAccuracyMap(userIds, startDate, endDate);

        // 批量查询指标数据
        List<MetricData> metricDataList = new ArrayList<>();
        for (SysUser user : users) {
            try {
                MetricData data = new MetricData();
                data.id = user.getUserId();
                data.name = user.getNickName();
                data.seizureEfficiency = queryPersonalSeizureEfficiency(user.getUserId(), rankList);
                data.inspectionPassRate = queryPersonalInspectionRate(user.getUserId(), checkRankList);
                data.trainingScore = queryPersonalTrainingScore(user.getUserId(), accuracyMap);
                metricDataList.add(data);
            } catch (Exception e) {
                log.error("查询用户{}指标失败：{}", user.getUserName(), e.getMessage());
            }
        }

        // 集体处理
        return normalizeAndCreateResult(metricDataList);
    }

    /**
     * 计算班组绩效指标
     */
    private List<PerformanceMetricsResultDto> calculateTeamMetrics(PerformanceMetricsParamDto param) {
        List<PerformanceMetricsResultDto> result = new ArrayList<>();
        // 查询所有班组
        Long topSiteId = DeptUtils.getTopSiteId(deptMapper.selectDeptById(getDeptId()));

        // 根据大队 ID 筛选
        if (param.getBrigadeId() != null) {
            topSiteId = param.getBrigadeId();
        }

        // 根据科室 ID 筛选
        if (param.getDeptId() != null) {
            topSiteId = param.getDeptId();
        }

        List<SysDept> teams = sysDeptService.selectChildrenDeptById(topSiteId).stream()
                .filter(dept -> DeptTypeEnum.TEAMS.getCode().equals(dept.getDeptType()))
                .collect(Collectors.toList());

        // 根据班组 ID 筛选
        if (param.getTeamId() != null && CollectionUtil.isNotEmpty(teams)) {
            teams = teams.stream()
                    .filter(item -> param.getTeamId().equals(item.getDeptId()))
                    .collect(Collectors.toList());
        }

        if (teams.isEmpty()) return result;

        //查获效率
        List<SeizureEfficiencyRankDto> rankList = calculateSeizureEfficiency(param);
        //巡检合格率
        List<CheckEfficiencyRankDto> checkRankList = calculateCheckEfficiency(param);

        // 批量查询抽问抽答正确率
        List<Long> teamIds = teams.stream().map(SysDept::getDeptId).collect(Collectors.toList());
        String startDate = formatDate(param.getStartTime());
        String endDate = formatDate(param.getEndTime());
        Map<Long, BigDecimal> accuracyMap = accuracyStatisticsService.getTeamsAccuracyMap(teamIds, startDate, endDate);

        // 批量查询指标数据
        List<MetricData> metricDataList = new ArrayList<>();
        for (SysDept team : teams) {
            try {
                MetricData data = new MetricData();
                data.id = team.getDeptId();
                data.name = team.getDeptName();
                data.seizureEfficiency = queryTeamSeizureEfficiency(team.getDeptId(), rankList);
                data.inspectionPassRate = queryTeamInspectionRate(team.getDeptId(), checkRankList);
                data.trainingScore = queryTeamTrainingScore(team.getDeptId(), accuracyMap);
                metricDataList.add(data);
            } catch (Exception e) {
                log.error("查询班组{}指标失败：{}", team.getDeptName(), e.getMessage());
            }
        }

        // 集体处理
        return normalizeAndCreateResult(metricDataList);
    }

    /**
     * 计算科室绩效指标
     */
    private List<PerformanceMetricsResultDto> calculateDepartmentMetrics(PerformanceMetricsParamDto param) {
        List<PerformanceMetricsResultDto> result = new ArrayList<>();

        // 查询所有科室
        Long topSiteId = DeptUtils.getTopSiteId(deptMapper.selectDeptById(getDeptId()));

        // 根据大队 ID 筛选
        if (param.getBrigadeId() != null) {
            topSiteId = param.getBrigadeId();
        }

        List<SysDept> departments = sysDeptService.selectChildrenDeptById(topSiteId).stream()
                .filter(dept -> DeptTypeEnum.MANAGER.getCode().equals(dept.getDeptType()))
                .collect(Collectors.toList());

        // 根据科室 ID 筛选
        if (param.getDeptId() != null && CollectionUtil.isNotEmpty(departments)) {
            departments = departments.stream()
                    .filter(item -> param.getDeptId().equals(item.getDeptId()))
                    .collect(Collectors.toList());
        }

        if (departments.isEmpty()) return result;

        //查获效率
        List<SeizureEfficiencyRankDto> rankList = calculateSeizureEfficiency(param);
        //巡检合格率
        List<CheckEfficiencyRankDto> checkRankList = calculateCheckEfficiency(param);

        // 批量查询抽问抽答正确率
        List<Long> deptIds = departments.stream().map(SysDept::getDeptId).collect(Collectors.toList());
        String startDate = formatDate(param.getStartTime());
        String endDate = formatDate(param.getEndTime());
        Map<Long, BigDecimal> accuracyMap = accuracyStatisticsService.getDeptsAccuracyMap(deptIds, startDate, endDate);

        // 批量查询指标数据
        List<MetricData> metricDataList = new ArrayList<>();
        for (SysDept dept : departments) {
            try {
                MetricData data = new MetricData();
                data.id = dept.getDeptId();
                data.name = dept.getDeptName();
                data.seizureEfficiency = queryDepartmentSeizureEfficiency(dept.getDeptId(), rankList);
                data.inspectionPassRate = queryDepartmentInspectionRate(dept.getDeptId(), checkRankList);
                data.trainingScore = queryDepartmentTrainingScore(dept.getDeptId(), accuracyMap);
                metricDataList.add(data);
            } catch (Exception e) {
                log.error("查询科室{}指标失败：{}", dept.getDeptName(), e.getMessage());
            }
        }

        // 集体处理
        return normalizeAndCreateResult(metricDataList);
    }

    /**
     * 计算大队绩效指标
     */
    private List<PerformanceMetricsResultDto> calculateBrigadeMetrics(PerformanceMetricsParamDto param) {
        List<PerformanceMetricsResultDto> result = new ArrayList<>();

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

        // 根据大队 ID 筛选
        if (param.getBrigadeId() != null && CollectionUtil.isNotEmpty(brigades)) {
            brigades = brigades.stream()
                    .filter(item -> param.getBrigadeId().equals(item.getDeptId()))
                    .collect(Collectors.toList());
        }

        if (brigades.isEmpty()) return result;

        //查获效率
        List<SeizureEfficiencyRankDto> rankList = calculateSeizureEfficiency(param);
        //巡检合格率
        List<CheckEfficiencyRankDto> checkRankList = calculateCheckEfficiency(param);

        // 批量查询抽问抽答正确率
        List<Long> deptIds = brigades.stream().map(SysDept::getDeptId).collect(Collectors.toList());
        String startDate = formatDate(param.getStartTime());
        String endDate = formatDate(param.getEndTime());
        Map<Long, BigDecimal> accuracyMap = accuracyStatisticsService.getDeptsAccuracyMap(deptIds, startDate, endDate);

        // 批量查询指标数据
        List<MetricData> metricDataList = new ArrayList<>();
        for (SysDept dept : brigades) {
            try {
                MetricData data = new MetricData();
                data.id = dept.getDeptId();
                data.name = dept.getDeptName();
                data.seizureEfficiency = queryDepartmentSeizureEfficiency(dept.getDeptId(), rankList);
                data.inspectionPassRate = queryDepartmentInspectionRate(dept.getDeptId(), checkRankList);
                data.trainingScore = queryDepartmentTrainingScore(dept.getDeptId(), accuracyMap);
                metricDataList.add(data);
            } catch (Exception e) {
                log.error("查询科室{}指标失败：{}", dept.getDeptName(), e.getMessage());
            }
        }

        // 集体处理
        return normalizeAndCreateResult(metricDataList);
    }

    /**
     * 集体处理
     */
    private List<PerformanceMetricsResultDto> normalizeAndCreateResult(List<MetricData> dataList) {
        List<PerformanceMetricsResultDto> result = new ArrayList<>();

        if (dataList.isEmpty()) return result;

        // 标准化各项指标
        List<NormalizedData> normalizedList = new ArrayList<>();
        for (MetricData data : dataList) {
            NormalizedData normalized = new NormalizedData();
            normalized.id = data.id;
            normalized.name = data.name;
            normalized.seizureEfficiency = data.seizureEfficiency.multiply(new BigDecimal(100));
            normalized.inspectionPassRate = data.inspectionPassRate.multiply(new BigDecimal(100));
            normalized.trainingScore = data.trainingScore.multiply(new BigDecimal(100));
            // 总分 = 查获效率 + 巡检合格率 + 抽问抽答正确率
            normalized.totalScore = normalizeValue(data.seizureEfficiency, "w1")
                    .add(normalizeValue(data.inspectionPassRate, "w2"))
                    .add(normalizeValue(data.trainingScore, "w3"));
            normalizedList.add(normalized);
        }

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

        return result;
    }

    /**
     * 标准化值处理
     */
    private BigDecimal normalizeValue(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 void sortAndRank(List<PerformanceMetricsResultDto> result, PerformanceMetricsParamDto param) {
        // 排序
        String sortField = param.getSortField();
        if (sortField == null) sortField = "totalScore";

        Comparator<PerformanceMetricsResultDto> comparator;
        switch (sortField) {
            case "seizureEfficiency":
                comparator = Comparator.comparing(PerformanceMetricsResultDto::getSeizureEfficiency,
                        Comparator.nullsFirst(BigDecimal::compareTo));
                break;
            case "inspectionPassRate":
                comparator = Comparator.comparing(PerformanceMetricsResultDto::getInspectionPassRate,
                        Comparator.nullsFirst(BigDecimal::compareTo));
                break;
            case "trainingScore":
                comparator = Comparator.comparing(PerformanceMetricsResultDto::getTrainingScore,
                        Comparator.nullsFirst(BigDecimal::compareTo));
                break;
            default: // totalScore
                comparator = Comparator.comparing(PerformanceMetricsResultDto::getTotalScore,
                        Comparator.nullsFirst(BigDecimal::compareTo));
                break;
        }

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

        result.sort(comparator);

        // 设置排名
        for (int i = 0; i < result.size(); i++) {
            result.get(i).setRank(i + 1);
        }
    }

    /**
     * 实现个人查获效率查询
     * 个人查获效率=（个人查获效率－个人最低查获效率）/（个人最高查获效率－个人最低查获效率）
     */
    private BigDecimal queryPersonalSeizureEfficiency(Long userId, List<SeizureEfficiencyRankDto> rankList) {
        BigDecimal reduce = rankList.stream().filter(rank -> rank.getId().equals(userId)).map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal min = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rankList.stream().map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal max = rankList.stream().map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal difference = max.subtract(min);
        BigDecimal normalized = difference.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : reduce.subtract(min).divide(difference, 2, RoundingMode.HALF_UP);
        normalized = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalized));
        return normalized;
    }

    /**
     * 实现个人巡检合格率查询
     *
     * @param userId
     * @param rankList
     * @return
     */
    private BigDecimal queryPersonalInspectionRate(Long userId, List<CheckEfficiencyRankDto> rankList) {
        BigDecimal reduce = rankList.stream().filter(rank -> rank.getId().equals(userId)).map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal min = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rankList.stream().map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal max = rankList.stream().map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal difference = max.subtract(min);
        BigDecimal normalized = difference.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : reduce.subtract(min).divide(difference, 2, RoundingMode.HALF_UP);
        normalized = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalized));
        return normalized;
    }

    /**
     * 实现个人抽问抽答正确率查询
     * 归一化公式：(当前值 - min) / (max - min)
     */
    private BigDecimal queryPersonalTrainingScore(Long userId, Map<Long, BigDecimal> accuracyMap) {
        return new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeFromMap(userId, accuracyMap)));
    }

    /**
     * 实现班组查获效率查询
     * 组织查获效率=（组织查获效率－组织最低查获效率）/（组织最高查获效率－组织最低查获效率）
     */
    private BigDecimal queryTeamSeizureEfficiency(Long teamId, List<SeizureEfficiencyRankDto> rankList) {
        BigDecimal reduce = rankList.stream().filter(rank -> rank.getId().equals(teamId)).map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal min = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rankList.stream().map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal max = rankList.stream().map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal difference = max.subtract(min);
        BigDecimal normalized = difference.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : reduce.subtract(min).divide(difference, 2, RoundingMode.HALF_UP);
        normalized = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalized));
        return normalized;
    }

    /**
     * 实现班组巡检合格率查询
     */
    private BigDecimal queryTeamInspectionRate(Long teamId, List<CheckEfficiencyRankDto> rankList) {
        BigDecimal reduce = rankList.stream().filter(rank -> rank.getId().equals(teamId)).map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal min = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rankList.stream().map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal max = rankList.stream().map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal difference = max.subtract(min);
        BigDecimal normalized = difference.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : reduce.subtract(min).divide(difference, 2, RoundingMode.HALF_UP);
        normalized = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalized));
        return normalized;
    }

    /**
     * 实现班组抽问抽答正确率查询
     * 归一化公式：(当前值 - min) / (max - min)
     */
    private BigDecimal queryTeamTrainingScore(Long teamId, Map<Long, BigDecimal> accuracyMap) {
        return new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeFromMap(teamId, accuracyMap)));
    }

    /**
     * 实现科室查获效率查询
     * 组织查获效率=（组织查获效率－组织最低查获效率）/（组织最高查获效率－组织最低查获效率）
     */
    private BigDecimal queryDepartmentSeizureEfficiency(Long deptId, List<SeizureEfficiencyRankDto> rankList) {
        BigDecimal reduce = rankList.stream().filter(rank -> rank.getId().equals(deptId)).map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal min = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rankList.stream().map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal max = rankList.stream().map(rank -> rank.getEfficiency() == null ? BigDecimal.ZERO : rank.getEfficiency()).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal difference = max.subtract(min);
        BigDecimal normalized = difference.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : reduce.subtract(min).divide(difference, 2, RoundingMode.HALF_UP);
        normalized = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalized));
        return normalized;
    }

    /**
     * 实现科室巡检合格率查询
     */
    private BigDecimal queryDepartmentInspectionRate(Long deptId, List<CheckEfficiencyRankDto> rankList) {
        BigDecimal reduce = rankList.stream().filter(rank -> rank.getId().equals(deptId)).map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal min = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rankList.stream().map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal max = rankList.stream().map(rank -> rank.getPassRate() == null ? BigDecimal.ZERO : rank.getPassRate()).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal difference = max.subtract(min);
        BigDecimal normalized = difference.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : reduce.subtract(min).divide(difference, 2, RoundingMode.HALF_UP);
        normalized = new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalized));
        return normalized;
    }

    /**
     * 实现科室抽问抽答正确率查询
     * 归一化公式：(当前值 - min) / (max - min)
     */
    private BigDecimal queryDepartmentTrainingScore(Long deptId, Map<Long, BigDecimal> accuracyMap) {
        return new BigDecimal("0.8").add(new BigDecimal("0.2").multiply(normalizeFromMap(deptId, accuracyMap)));
    }

    /**
     * 从正确率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);
    }

    /**
     * Date转yyyy-MM-dd字符串
     */
    private String formatDate(Date date) {
        if (date == null) {
            return null;
        }
        return new SimpleDateFormat("yyyy-MM-dd").format(date);
    }

    /**
     * 指标数据内部类
     */
    private static class MetricData {
        Long id;
        String name;
        BigDecimal seizureEfficiency;
        BigDecimal inspectionPassRate;
        BigDecimal trainingScore;
    }

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

    /**
     * 计算巡检合格率
     *
     * @param param
     * @return
     */
    private List<CheckEfficiencyRankDto> calculateCheckEfficiency(PerformanceMetricsParamDto param) {
        List<CheckEfficiencyRankDto> rankList = new ArrayList<>();
        BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
        dto.setStartDate(param.getStartTime());
        dto.setEndDate(param.getEndTime());
        CheckEfficiencyDto result = checkEfficiencyService.getCheckEfficiency(dto, param.getDimension());
        if (param.getDimension() == 1) {
            // 个人维度
            rankList = result.getIndividualRankList();
        } else if (param.getDimension() == 2) {
            // 班组维度
            rankList = result.getTeamRankList();
        } else if (param.getDimension() == 3) {
            // 科室维度
            rankList = result.getDepartmentRankList();
        } else if (param.getDimension() == 3) {
            // 大队维度
            rankList = result.getBrigadeRankList();
        }
        return rankList;
    }

}