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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.sundot.airport.common.core.controller.BaseController;
import com.sundot.airport.common.core.domain.AjaxResult;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.dto.*;
import com.sundot.airport.common.enums.RoleTypeEnum;
import com.sundot.airport.common.utils.DeptUtils;
import com.sundot.airport.common.utils.GeometricMeanUtils;
import com.sundot.airport.common.utils.poi.ExcelUtil;
import com.sundot.airport.system.domain.SysConfig;
import com.sundot.airport.system.mapper.SysUserMapper;
import com.sundot.airport.system.service.ISysConfigService;
import com.sundot.airport.system.service.ISysDeptService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 绩效指标管理 Controller
 *
 * @author sundot
 * @date 2026-03-16
 */
@Slf4j
@RestController
@RequestMapping("/item/indicators")
@Api(tags = "绩效指标管理")
public class PerformanceIndicatorsController extends BaseController {

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private PerformanceMetricsController performanceMetricsController;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ISysDeptService sysDeptService;


    // 绩效矩阵参数的配置键名
    private static final String CONFIG_KEY_PARAM_A = "item.performance.matrix.param_a";
    private static final String CONFIG_KEY_PARAM_B = "item.performance.matrix.param_b";
    private static final String CONFIG_KEY_PARAM_C = "item.performance.matrix.param_c";


    /**
     * 保存绩效矩阵
     * 保存前端传入的绩效矩阵参数 a、b、c
     * 默认值 a=3, b=5, c=2
     *
     * @param a
     * @param b
     * @param c
     * @return 保存结果
     */
    @GetMapping("/matrix/add")
    public AjaxResult performanceMatrix(
            @RequestParam(value = "a", defaultValue = "3") BigDecimal a,
            @RequestParam(value = "b", defaultValue = "5") BigDecimal b,
            @RequestParam(value = "c", defaultValue = "2") BigDecimal c) {

        try {
            // 保存到 sys_config 表
            saveConfig(CONFIG_KEY_PARAM_A, "绩效矩阵参数 a", a.toString());
            saveConfig(CONFIG_KEY_PARAM_B, "绩效矩阵参数 b", b.toString());
            saveConfig(CONFIG_KEY_PARAM_C, "绩效矩阵参数 c", c.toString());

            // 同步更新到 GeometricMeanUtils
            GeometricMeanUtils.setParams(a.doubleValue(), b.doubleValue(), c.doubleValue());

            return success("保存成功");
        } catch (Exception e) {
            log.error("保存绩效矩阵参数失败：{}", e.getMessage());
            return error("保存失败：" + e.getMessage());
        }
    }

    /**
     * 获取绩效矩阵参数配置
     *
     * @return 绩效矩阵参数配置
     */
    @GetMapping("/matrix/config")
    public AjaxResult getMatrixConfig() {
        try {
            String paramA = configService.selectConfigByKey(CONFIG_KEY_PARAM_A);
            String paramB = configService.selectConfigByKey(CONFIG_KEY_PARAM_B);
            String paramC = configService.selectConfigByKey(CONFIG_KEY_PARAM_C);

            // 如果不存在，返回默认值
            if (paramA == null || paramA.isEmpty()) paramA = "3";
            if (paramB == null || paramB.isEmpty()) paramB = "5";
            if (paramC == null || paramC.isEmpty()) paramC = "2";

            Map<String, Object> result = new HashMap<>();
            result.put("paramA", new BigDecimal(paramA));
            result.put("paramB", new BigDecimal(paramB));
            result.put("paramC", new BigDecimal(paramC));

            return success(result);
        } catch (Exception e) {
            log.error("获取绩效矩阵参数失败：{}", e.getMessage());
            return error("获取失败：" + e.getMessage());
        }
    }

    /**
     * 绩效查询
     * 调用现有的 /metrics 接口获取绩效数据
     *
     * @param param 查询参数
     * @return 绩效数据列表
     */
    @GetMapping("/query")
    public AjaxResult queryPerformance(PerformanceMetricsParamDto param) {
        try {
            // 设置默认值
            if (param.getDimension() == null) {
                param.setDimension(4); // 默认查询大队
            }
            if (param.getSortOrder() == null) {
                param.setSortOrder(2); // 默认降序
            }

            return performanceMetricsController.getPerformanceMetrics(param);
        } catch (Exception e) {
            log.error("绩效查询失败：{}", e.getMessage());
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }


    /**
     * 导出绩效数据
     * 根据维度不同导出不同的内容
     *
     * @param response HTTP 响应
     * @param param    查询参数
     */
    @GetMapping("/export")
    public void exportPerformance(HttpServletResponse response, PerformanceMetricsParamDto param) {
        // 设置默认值
        if (param.getDimension() == null) {
            param.setDimension(4); // 默认查询大队
        }
        if (param.getSortOrder() == null) {
            param.setSortOrder(2); // 默认降序
        }

        // 查询绩效数据
        AjaxResult result = performanceMetricsController.getPerformanceMetrics(param);
        List<PerformanceMetricsResultDto> dataList = (List<PerformanceMetricsResultDto>) result.get("data");

        String fileName = "绩效数据";

        // 根据维度转换数据
        if (param.getDimension() == 1) {
            // 人员维度 - 导出个人绩效（包含姓名、班组名、科室名、大队名）
            List<PerformanceMetricsPersonalExportDto> exportList = convertToPersonalExportList(dataList, param.getStartTime(), param.getEndTime());
            ExcelUtil<PerformanceMetricsPersonalExportDto> util = new ExcelUtil<>(PerformanceMetricsPersonalExportDto.class);
            util.exportExcel(response, exportList, fileName);
        } else if (param.getDimension() == 2) {
            // 班组维度 - 导出班组绩效（包含班组名、科室名、大队名）
            List<PerformanceMetricsTeamExportDto> exportList = convertToTeamExportList(dataList, param.getStartTime(), param.getEndTime());
            ExcelUtil<PerformanceMetricsTeamExportDto> util = new ExcelUtil<>(PerformanceMetricsTeamExportDto.class);
            util.exportExcel(response, exportList, fileName);
        } else if (param.getDimension() == 3) {
            // 科室维度 - 导出科室绩效（包含科室名、大队名）
            List<PerformanceMetricsDeptExportDto> exportList = convertToDeptExportList(dataList, param.getStartTime(), param.getEndTime());
            ExcelUtil<PerformanceMetricsDeptExportDto> util = new ExcelUtil<>(PerformanceMetricsDeptExportDto.class);
            util.exportExcel(response, exportList, fileName);
        } else if (param.getDimension() == 4) {
            // 大队维度 - 导出大队绩效（仅大队名）
            List<PerformanceMetricsBrigadeExportDto> exportList = convertToBrigadeExportList(dataList, param.getStartTime(), param.getEndTime());
            ExcelUtil<PerformanceMetricsBrigadeExportDto> util = new ExcelUtil<>(PerformanceMetricsBrigadeExportDto.class);
            util.exportExcel(response, exportList, fileName);
        }
    }

    /**
     * 班组组建
     *
     * @param param 组建参数
     * @return 组建结果
     */
    @PostMapping("/team/build")
    public AjaxResult teamBuild(@RequestBody TeamBuildParamDto param) {
        try {
            // 参数校验
            if (param.getTeamCount() == null || param.getTeamCount() < 1 || param.getTeamCount() > 10) {
                return error("重点班组数量必须在1-10之间");
            }
            if (param.getTargetSize() == null || param.getTargetSize() < 2) {
                return error("目标班组人数至少为2人");
            }
            if (param.getLeaderCondition() == null || param.getLeaderCondition() < 1 || param.getLeaderCondition() > 3) {
                return error("组建班组长条件必须为1-综合能力、2-管理能力、3-业务能力");
            }

            // 查询个人维度的绩效数据（包含班组长和安检员）
            PerformanceMetricsParamDto metricsParam = new PerformanceMetricsParamDto();
            metricsParam.setDimension(1); // 个人维度
            metricsParam.setStartTime(DateUtil.parse(param.getStartTime(), "yyyy-MM-dd"));
            metricsParam.setEndTime(DateUtil.parse(param.getEndTime(), "yyyy-MM-dd"));
            metricsParam.setSortField("totalScore");
            metricsParam.setSortOrder(2); // 降序

            AjaxResult result = performanceMetricsController.getPerformanceMetrics(metricsParam);
            List<PerformanceMetricsResultDto> personalMetrics = (List<PerformanceMetricsResultDto>) result.get("data");

            if (personalMetrics == null || personalMetrics.isEmpty()) {
                return error("未查询到绩效数据");
            }

            // 获取所有班组长和安检员的用户信息
            Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(getDeptId()));
            if (topSiteId == null) {
                return error("无法找到有效的站点信息");
            }

            List<SysUser> allUsers = userMapper.selectUserByDeptId(topSiteId);
            Map<Long, SysUser> userMap = allUsers.stream()
                    .filter(user -> user.getRoles() != null)
                    .filter(user -> user.getRoles().stream()
                            .anyMatch(role -> RoleTypeEnum.banzuzhang.getCode().equals(role.getRoleKey())
                                    || RoleTypeEnum.SecurityCheck.getCode().equals(role.getRoleKey())))
                    .collect(Collectors.toMap(SysUser::getUserId, user -> user, (u1, u2) -> u1));

            // 根据组建条件选择班组长
            List<TeamBuildResultDto> teamResults = new ArrayList<>();
            Set<Long> selectedUserIds = new HashSet<>(); // 记录已选中的用户

            // 1. 选择班组长
            List<TeamMemberDto> leaders = selectLeaders(param, personalMetrics, userMap);
            if (leaders.size() < param.getTeamCount()) {
                return error("班组长人数不足，无法组建" + param.getTeamCount() + "个重点班组");
            }

            // 2. 选择成员并分配
            List<TeamMemberDto> members = selectMembers(param, personalMetrics, userMap, selectedUserIds);

            // 3. 组建班组
            int memberCount = param.getTargetSize() - 1; // 每个班组的成员数 = 目标人数 - 1个班组长
            int totalMembersNeeded = param.getTeamCount() * memberCount; // 总共需要的成员数

            if (members.size() < totalMembersNeeded) {
                return error("成员人数不足，需要" + totalMembersNeeded + "人，但只有" + members.size() + "人");
            }

            // 4. 分配成员到各个班组
            for (int i = 0; i < param.getTeamCount(); i++) {
                TeamBuildResultDto teamResult = new TeamBuildResultDto();
                teamResult.setTeamNo(i + 1);

                List<TeamMemberDto> teamMembers = new ArrayList<>();
                // 添加班组长
                teamMembers.add(leaders.get(i));
                selectedUserIds.add(leaders.get(i).getUserId());

                // 随机分配成员
                for (int j = 0; j < memberCount; j++) {
                    int randomIndex = new Random().nextInt(members.size());
                    TeamMemberDto member = members.remove(randomIndex);
                    teamMembers.add(member);
                    selectedUserIds.add(member.getUserId());
                }

                teamResult.setMembers(teamMembers);
                teamResults.add(teamResult);
            }

            return success(teamResults);
        } catch (Exception e) {
            log.error("班组组建失败：{}", e.getMessage());
            return error("班组组建失败：" + e.getMessage());
        }
    }

    /**
     * 根据条件选择班组长
     */
    private List<TeamMemberDto> selectLeaders(TeamBuildParamDto param,
                                              List<PerformanceMetricsResultDto> personalMetrics,
                                              Map<Long, SysUser> userMap) {
        List<TeamMemberDto> leaders = new ArrayList<>();

        // 筛选出班组长角色的用户绩效数据
        List<PerformanceMetricsResultDto> leaderMetrics = personalMetrics.stream()
                .filter(metric -> {
                    SysUser user = userMap.get(metric.getId());
                    return user != null && user.getRoles().stream()
                            .anyMatch(role -> RoleTypeEnum.banzuzhang.getCode().equals(role.getRoleKey()));
                })
                .collect(Collectors.toList());

        Integer leaderCondition = param.getLeaderCondition();
        if (leaderCondition == 1) {
            // 综合能力：个人总分和班组总分之和除以2
            // 获取班组绩效数据
            PerformanceMetricsParamDto teamParam = new PerformanceMetricsParamDto();
            teamParam.setDimension(2);
            teamParam.setStartTime(DateUtil.parse(param.getStartTime(), "yyyy-MM-dd"));
            teamParam.setEndTime(DateUtil.parse(param.getEndTime(), "yyyy-MM-dd"));
            teamParam.setSortField("totalScore");
            teamParam.setSortOrder(2);

            AjaxResult teamResult = performanceMetricsController.getPerformanceMetrics(teamParam);
            List<PerformanceMetricsResultDto> teamMetrics = (List<PerformanceMetricsResultDto>) teamResult.get("data");
            Map<Long, BigDecimal> teamScoreMap = teamMetrics.stream()
                    .collect(Collectors.toMap(PerformanceMetricsResultDto::getId, PerformanceMetricsResultDto::getTotalScore, (s1, s2) -> s1));

            // 计算综合得分
            for (PerformanceMetricsResultDto metric : leaderMetrics) {
                SysUser user = userMap.get(metric.getId());
                if (user != null && user.getDeptId() != null) {
                    BigDecimal teamScore = teamScoreMap.getOrDefault(user.getDeptId(), BigDecimal.ZERO);
                    BigDecimal comprehensiveScore = metric.getTotalScore()
                            .add(teamScore)
                            .divide(new BigDecimal("2"), 2, BigDecimal.ROUND_HALF_UP);

                    TeamMemberDto leader = new TeamMemberDto();
                    leader.setUserId(user.getUserId());
                    leader.setName(user.getNickName());
                    leader.setUserName(user.getUserName());
                    leader.setRole("班组长");
                    leader.setScore(comprehensiveScore);
                    leaders.add(leader);
                }
            }

            // 按综合得分降序排序
            leaders.sort((a, b) -> b.getScore().compareTo(a.getScore()));

        } else if (leaderCondition == 2) {
            // 管理能力：使用班组维度的绩效总分
            PerformanceMetricsParamDto teamParam = new PerformanceMetricsParamDto();
            teamParam.setDimension(2);
            teamParam.setStartTime(DateUtil.parse(param.getStartTime(), "yyyy-MM-dd"));
            teamParam.setEndTime(DateUtil.parse(param.getEndTime(), "yyyy-MM-dd"));
            teamParam.setSortField("totalScore");
            teamParam.setSortOrder(2);

            AjaxResult teamResult = performanceMetricsController.getPerformanceMetrics(teamParam);
            List<PerformanceMetricsResultDto> teamMetrics = (List<PerformanceMetricsResultDto>) teamResult.get("data");
            Map<Long, BigDecimal> teamScoreMap = teamMetrics.stream()
                    .collect(Collectors.toMap(PerformanceMetricsResultDto::getId, PerformanceMetricsResultDto::getTotalScore, (s1, s2) -> s1));

            // 获取班组长所在的班组得分
            for (PerformanceMetricsResultDto metric : leaderMetrics) {
                SysUser user = userMap.get(metric.getId());
                if (user != null && user.getDeptId() != null) {
                    BigDecimal teamScore = teamScoreMap.getOrDefault(user.getDeptId(), BigDecimal.ZERO);

                    TeamMemberDto leader = new TeamMemberDto();
                    leader.setUserId(user.getUserId());
                    leader.setName(user.getNickName());
                    leader.setUserName(user.getUserName());
                    leader.setRole("班组长");
                    leader.setScore(teamScore);
                    leaders.add(leader);
                }
            }

            // 按班组得分降序排序
            leaders.sort((a, b) -> b.getScore().compareTo(a.getScore()));

        } else if (leaderCondition == 3) {
            // 业务能力：使用个人的绩效总分
            for (PerformanceMetricsResultDto metric : leaderMetrics) {
                SysUser user = userMap.get(metric.getId());
                if (user != null) {
                    TeamMemberDto leader = new TeamMemberDto();
                    leader.setUserId(user.getUserId());
                    leader.setName(user.getNickName());
                    leader.setUserName(user.getUserName());
                    leader.setRole("班组长");
                    leader.setScore(metric.getTotalScore());
                    leaders.add(leader);
                }
            }

            // 按个人总分降序排序
            leaders.sort((a, b) -> b.getScore().compareTo(a.getScore()));
        }

        // 取前 teamCount 个班组长
        int teamCount = param.getTeamCount();
        return leaders.subList(0, Math.min(teamCount, leaders.size()));
    }

    /**
     * 选择成员（安检员角色）
     */
    private List<TeamMemberDto> selectMembers(TeamBuildParamDto param,
                                              List<PerformanceMetricsResultDto> personalMetrics,
                                              Map<Long, SysUser> userMap,
                                              Set<Long> selectedUserIds) {
        List<TeamMemberDto> members = new ArrayList<>();

        // 筛选出安检员角色的用户绩效数据
        List<PerformanceMetricsResultDto> memberMetrics = personalMetrics.stream()
                .filter(metric -> {
                    SysUser user = userMap.get(metric.getId());
                    return user != null && user.getRoles().stream()
                            .anyMatch(role -> RoleTypeEnum.SecurityCheck.getCode().equals(role.getRoleKey()));
                })
                .collect(Collectors.toList());

        // 转换为成员DTO
        for (PerformanceMetricsResultDto metric : memberMetrics) {
            if (selectedUserIds.contains(metric.getId())) {
                continue; // 跳过已选中的用户
            }

            SysUser user = userMap.get(metric.getId());
            if (user != null) {
                TeamMemberDto member = new TeamMemberDto();
                member.setUserId(user.getUserId());
                member.setName(user.getNickName());
                member.setUserName(user.getUserName());
                member.setRole("安检员");
                member.setScore(metric.getTotalScore());
                members.add(member);
            }
        }

        // 按个人总分降序排序
        members.sort((a, b) -> b.getScore().compareTo(a.getScore()));

        return members;
    }


    /**
     * 转换为人员导出 DTO 列表
     */
    private List<PerformanceMetricsPersonalExportDto> convertToPersonalExportList(List<PerformanceMetricsResultDto> dataList, Date startTime, Date endTime) {
        return dataList.stream()
                .map(item -> {
                    PerformanceMetricsPersonalExportDto dto = new PerformanceMetricsPersonalExportDto();
                    dto.setName(item.getName());
                    dto.setClassName(item.getClassName());
                    dto.setDeptName(item.getDeptName());
                    dto.setBrigadeName(item.getBrigadeName());
                    dto.setSeizureEfficiency(item.getSeizureEfficiency());
                    dto.setInspectionPassRate(item.getInspectionPassRate());
                    dto.setTrainingScore(item.getTrainingScore());
                    dto.setTotalScore(item.getTotalScore());
                    dto.setStartTime(DateUtil.format(startTime, "yyyy-MM-dd"));
                    dto.setEndTime(DateUtil.format(endTime, "yyyy-MM-dd"));
                    return dto;
                })
                .collect(Collectors.toList());
    }

    /**
     * 转换为班组导出 DTO 列表
     */
    private List<PerformanceMetricsTeamExportDto> convertToTeamExportList(List<PerformanceMetricsResultDto> dataList, Date startTime, Date endTime) {
        return dataList.stream()
                .map(item -> {
                    PerformanceMetricsTeamExportDto dto = new PerformanceMetricsTeamExportDto();
                    dto.setName(item.getName());
                    dto.setDeptName(item.getDeptName());
                    dto.setBrigadeName(item.getBrigadeName());
                    dto.setSeizureEfficiency(item.getSeizureEfficiency());
                    dto.setInspectionPassRate(item.getInspectionPassRate());
                    dto.setTrainingScore(item.getTrainingScore());
                    dto.setTotalScore(item.getTotalScore());
                    dto.setStartTime(DateUtil.format(startTime, "yyyy-MM-dd"));
                    dto.setEndTime(DateUtil.format(endTime, "yyyy-MM-dd"));
                    return dto;
                })
                .collect(Collectors.toList());
    }

    /**
     * 转换为科室导出 DTO 列表
     */
    private List<PerformanceMetricsDeptExportDto> convertToDeptExportList(List<PerformanceMetricsResultDto> dataList, Date startTime, Date endTime) {
        return dataList.stream()
                .map(item -> {
                    PerformanceMetricsDeptExportDto dto = new PerformanceMetricsDeptExportDto();
                    dto.setName(item.getName());
                    dto.setBrigadeName(item.getBrigadeName());
                    dto.setSeizureEfficiency(item.getSeizureEfficiency());
                    dto.setInspectionPassRate(item.getInspectionPassRate());
                    dto.setTrainingScore(item.getTrainingScore());
                    dto.setTotalScore(item.getTotalScore());
                    dto.setStartTime(DateUtil.format(startTime, "yyyy-MM-dd"));
                    dto.setEndTime(DateUtil.format(endTime, "yyyy-MM-dd"));
                    return dto;
                })
                .collect(Collectors.toList());
    }

    /**
     * 转换为大队导出 DTO 列表
     */
    private List<PerformanceMetricsBrigadeExportDto> convertToBrigadeExportList(List<PerformanceMetricsResultDto> dataList, Date startTime, Date endTime) {
        return dataList.stream()
                .map(item -> {
                    PerformanceMetricsBrigadeExportDto dto = new PerformanceMetricsBrigadeExportDto();
                    dto.setName(item.getName());
                    dto.setSeizureEfficiency(item.getSeizureEfficiency());
                    dto.setInspectionPassRate(item.getInspectionPassRate());
                    dto.setTrainingScore(item.getTrainingScore());
                    dto.setTotalScore(item.getTotalScore());
                    dto.setStartTime(DateUtil.format(startTime, "yyyy-MM-dd"));
                    dto.setEndTime(DateUtil.format(endTime, "yyyy-MM-dd"));
                    return dto;
                })
                .collect(Collectors.toList());
    }


    /**
     * 保存配置到 sys_config 表
     */
    private void saveConfig(String configKey, String configName, String configValue) {
        try {
            SysConfig queryConfig = new SysConfig();
            queryConfig.setConfigKey(configKey);
            List<SysConfig> configList = configService.selectConfigList(queryConfig);
            if (CollectionUtil.isNotEmpty(configList)) {
                SysConfig config = configList.get(0);
                config.setConfigValue(configValue);
                configService.updateConfig(config);
            } else {
                // 新增配置
                SysConfig config = new SysConfig();
                config.setConfigName(configName);
                config.setConfigKey(configKey);
                config.setConfigValue(configValue);
                config.setConfigType("N"); // 非系统内置
                configService.insertConfig(config);
            }
        } catch (Exception e) {
            log.error("保存配置失败：{}", e.getMessage());
            throw e;
        }
    }

}
