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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sundot.airport.exam.domain.DailyTask;
import com.sundot.airport.exam.domain.DailyTaskDetail;
import com.sundot.airport.exam.domain.WeakModuleAnalysis;
import com.sundot.airport.exam.dto.GlobalStatisticsDTO;
import com.sundot.airport.exam.dto.UserStatisticsDTO;
import com.sundot.airport.exam.enums.DailyTaskStatusEnum;
import com.sundot.airport.exam.mapper.DailyTaskDetailMapper;
import com.sundot.airport.exam.mapper.DailyTaskMapper;
import com.sundot.airport.exam.service.IDailyStatisticsService;
import com.sundot.airport.exam.service.IWeakModuleAnalysisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <b>功能名：</b>DailyStatisticsServiceImpl<br>
 * <b>说明：</b> 每日答题统计Service实现 <br>
 * <b>著作权：</b> Copyright (C) 2025 SUNDOT CORPORATION<br>
 * <b>修改履历：
 *
 * @author Simon Lin
 */
@Service
public class DailyStatisticsServiceImpl implements IDailyStatisticsService {

    @Autowired
    private DailyTaskMapper dailyTaskMapper;

    @Autowired
    private DailyTaskDetailMapper dailyTaskDetailMapper;

    @Autowired
    private IWeakModuleAnalysisService weakModuleAnalysisService;

    @Override
    public UserStatisticsDTO getUserStatistics(Long userId) {
        UserStatisticsDTO dto = new UserStatisticsDTO();

        // 1. 查询任务统计
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.eq(DailyTask::getDtUserId, userId);
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> allTasks = dailyTaskMapper.selectList(taskWrapper);

        dto.setTotalTasks(allTasks.size());
        dto.setCompletedTasks((int) allTasks.stream()
                .filter(t -> t.getDtStatus().equals(DailyTaskStatusEnum.COMPLETED.getCode()))
                .count());
        dto.setPendingTasks((int) allTasks.stream()
                .filter(t -> t.getDtStatus().equals(DailyTaskStatusEnum.PENDING.getCode()) ||
                        t.getDtStatus().equals(DailyTaskStatusEnum.IN_PROGRESS.getCode()))
                .count());
        dto.setExpiredTasks((int) allTasks.stream()
                .filter(t -> t.getDtStatus().equals(DailyTaskStatusEnum.EXPIRED.getCode()))
                .count());

        // 2. 查询答题统计（从任务明细中查询）
        // 获取所有用户的任务ID
        List<String> taskIds = allTasks.stream()
                .map(DailyTask::getDtId)
                .collect(Collectors.toList());

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

            dto.setTotalQuestions(allDetails.size());
            dto.setCorrectQuestions((int) allDetails.stream()
                    .filter(detail -> Boolean.TRUE.equals(detail.getDtdIsCorrect()))
                    .count());
        } else {
            dto.setTotalQuestions(0);
            dto.setCorrectQuestions(0);
        }

        // 计算总正确率
        if (dto.getTotalQuestions() > 0) {
            BigDecimal correctRate = BigDecimal.valueOf(dto.getCorrectQuestions())
                    .divide(BigDecimal.valueOf(dto.getTotalQuestions()), 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100));
            dto.setOverallCorrectRate(correctRate);
        } else {
            dto.setOverallCorrectRate(BigDecimal.ZERO);
        }

        // 3. 计算得分统计
        List<DailyTask> completedTasks = allTasks.stream()
                .filter(t -> t.getDtStatus().equals(DailyTaskStatusEnum.COMPLETED.getCode()))
                .collect(Collectors.toList());

        if (!completedTasks.isEmpty()) {
            // 平均分
            BigDecimal totalScore = completedTasks.stream()
                    .map(DailyTask::getDtTotalScore)
                    .filter(score -> score != null)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            dto.setAverageScore(totalScore.divide(
                    BigDecimal.valueOf(completedTasks.size()), 2, RoundingMode.HALF_UP));

            // 最高分
            dto.setHighestScore(completedTasks.stream()
                    .map(DailyTask::getDtTotalScore)
                    .filter(score -> score != null)
                    .max(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO));

            // 最低分
            dto.setLowestScore(completedTasks.stream()
                    .map(DailyTask::getDtTotalScore)
                    .filter(score -> score != null)
                    .min(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO));
        } else {
            dto.setAverageScore(BigDecimal.ZERO);
            dto.setHighestScore(BigDecimal.ZERO);
            dto.setLowestScore(BigDecimal.ZERO);
        }

        // 4. 查询薄弱模块分析
        List<WeakModuleAnalysis> allModuleAnalysis = weakModuleAnalysisService.getAllModuleAnalysis(userId);

        // 转换为DTO
        List<UserStatisticsDTO.ModuleStatistics> allModules = allModuleAnalysis.stream()
                .map(this::convertToModuleStatistics)
                .collect(Collectors.toList());
        dto.setAllModules(allModules);

        // 筛选薄弱模块
        List<UserStatisticsDTO.ModuleStatistics> weakModules = allModules.stream()
                .filter(UserStatisticsDTO.ModuleStatistics::getIsWeak)
                .collect(Collectors.toList());
        dto.setWeakModules(weakModules);

        return dto;
    }

    /**
     * 转换为模块统计DTO
     */
    private UserStatisticsDTO.ModuleStatistics convertToModuleStatistics(WeakModuleAnalysis analysis) {
        UserStatisticsDTO.ModuleStatistics stats = new UserStatisticsDTO.ModuleStatistics();
        stats.setModuleId(analysis.getWmaModuleId());
        stats.setModuleName(analysis.getWmaModuleName());
        stats.setTotalCount(analysis.getWmaTotalCount());
        stats.setCorrectCount(analysis.getWmaCorrectCount());
        stats.setCorrectRate(analysis.getWmaCorrectRate().multiply(BigDecimal.valueOf(100)));
        stats.setLast3Total(analysis.getWmaLast3Total());
        stats.setLast3Correct(analysis.getWmaLast3Correct());
        stats.setLast3Rate(analysis.getWmaLast3Rate().multiply(BigDecimal.valueOf(100)));
        stats.setIsWeak(analysis.getWmaIsWeak());
        return stats;
    }

    @Override
    public GlobalStatisticsDTO getGlobalStatistics() {
        GlobalStatisticsDTO dto = new GlobalStatisticsDTO();

        // 1. 查询所有任务（未删除）
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> allTasks = dailyTaskMapper.selectList(taskWrapper);

        // 2. 基础统计
        dto.setTotalTasks(allTasks.size());

        // 统计用户数（去重）
        Set<Long> uniqueUsers = allTasks.stream()
                .map(DailyTask::getDtUserId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        dto.setTotalUsers(uniqueUsers.size());

        // 3. 按状态统计
        long completedCount = allTasks.stream()
                .filter(t -> DailyTaskStatusEnum.COMPLETED.getCode().equals(t.getDtStatus()))
                .count();
        long pendingCount = allTasks.stream()
                .filter(t -> DailyTaskStatusEnum.PENDING.getCode().equals(t.getDtStatus()))
                .count();
        long inProgressCount = allTasks.stream()
                .filter(t -> DailyTaskStatusEnum.IN_PROGRESS.getCode().equals(t.getDtStatus()))
                .count();
        long expiredCount = allTasks.stream()
                .filter(t -> DailyTaskStatusEnum.EXPIRED.getCode().equals(t.getDtStatus()))
                .count();

        dto.setCompletedTasks((int) completedCount);
        dto.setPendingTasks((int) (pendingCount + inProgressCount));
        dto.setExpiredTasks((int) expiredCount);

        // 计算任务完成率
        if (allTasks.size() > 0) {
            dto.setTaskCompletionRate(
                    BigDecimal.valueOf(completedCount)
                            .multiply(BigDecimal.valueOf(100))
                            .divide(BigDecimal.valueOf(allTasks.size()), 2, RoundingMode.HALF_UP)
            );
        } else {
            dto.setTaskCompletionRate(BigDecimal.ZERO);
        }

        // 状态统计详情
        GlobalStatisticsDTO.StatusStatistics statusStats = new GlobalStatisticsDTO.StatusStatistics();
        statusStats.setPendingCount((int) pendingCount);
        statusStats.setInProgressCount((int) inProgressCount);
        statusStats.setCompletedCount((int) completedCount);
        statusStats.setExpiredCount((int) expiredCount);

        if (allTasks.size() > 0) {
            int total = allTasks.size();
            statusStats.setPendingRate(BigDecimal.valueOf(pendingCount).multiply(BigDecimal.valueOf(100))
                    .divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
            statusStats.setInProgressRate(BigDecimal.valueOf(inProgressCount).multiply(BigDecimal.valueOf(100))
                    .divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
            statusStats.setCompletedRate(BigDecimal.valueOf(completedCount).multiply(BigDecimal.valueOf(100))
                    .divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
            statusStats.setExpiredRate(BigDecimal.valueOf(expiredCount).multiply(BigDecimal.valueOf(100))
                    .divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
        }
        dto.setStatusStatistics(statusStats);

        // 4. 查询所有答题明细
        List<String> taskIds = allTasks.stream()
                .map(DailyTask::getDtId)
                .collect(Collectors.toList());

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

            dto.setTotalQuestions(allDetails.size());
            int correctCount = (int) allDetails.stream()
                    .filter(detail -> Boolean.TRUE.equals(detail.getDtdIsCorrect()))
                    .count();
            dto.setCorrectQuestions(correctCount);

            // 计算总正确率
            if (allDetails.size() > 0) {
                dto.setOverallCorrectRate(
                        BigDecimal.valueOf(correctCount)
                                .multiply(BigDecimal.valueOf(100))
                                .divide(BigDecimal.valueOf(allDetails.size()), 2, RoundingMode.HALF_UP)
                );
            } else {
                dto.setOverallCorrectRate(BigDecimal.ZERO);
            }

            // 5. 按模块统计
            Map<String, List<DailyTaskDetail>> moduleDetailsMap = allDetails.stream()
                    .filter(d -> d.getDtdModuleId() != null)
                    .collect(Collectors.groupingBy(DailyTaskDetail::getDtdModuleId));

            List<GlobalStatisticsDTO.ModuleStatistics> moduleStatsList = new ArrayList<>();
            for (Map.Entry<String, List<DailyTaskDetail>> entry : moduleDetailsMap.entrySet()) {
                List<DailyTaskDetail> moduleDetails = entry.getValue();
                GlobalStatisticsDTO.ModuleStatistics moduleStat = new GlobalStatisticsDTO.ModuleStatistics();
                moduleStat.setModuleId(entry.getKey());
                moduleStat.setModuleName(moduleDetails.get(0).getDtdModuleName());
                moduleStat.setTotalCount(moduleDetails.size());
                int moduleCorrect = (int) moduleDetails.stream()
                        .filter(d -> Boolean.TRUE.equals(d.getDtdIsCorrect()))
                        .count();
                moduleStat.setCorrectCount(moduleCorrect);
                moduleStat.setCorrectRate(
                        BigDecimal.valueOf(moduleCorrect)
                                .multiply(BigDecimal.valueOf(100))
                                .divide(BigDecimal.valueOf(moduleDetails.size()), 2, RoundingMode.HALF_UP)
                );
                moduleStatsList.add(moduleStat);
            }
            // 按正确率升序排序（薄弱模块在前）
            moduleStatsList.sort(Comparator.comparing(GlobalStatisticsDTO.ModuleStatistics::getCorrectRate));
            dto.setModuleStatistics(moduleStatsList);
        } else {
            dto.setTotalQuestions(0);
            dto.setCorrectQuestions(0);
            dto.setOverallCorrectRate(BigDecimal.ZERO);
            dto.setModuleStatistics(new ArrayList<>());
        }

        // 6. 得分统计（已完成的任务）
        List<DailyTask> completedTasks = allTasks.stream()
                .filter(t -> DailyTaskStatusEnum.COMPLETED.getCode().equals(t.getDtStatus()))
                .filter(t -> t.getDtTotalScore() != null)
                .collect(Collectors.toList());

        if (!completedTasks.isEmpty()) {
            BigDecimal totalScore = completedTasks.stream()
                    .map(DailyTask::getDtTotalScore)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            dto.setAverageScore(totalScore.divide(
                    BigDecimal.valueOf(completedTasks.size()), 2, RoundingMode.HALF_UP));

            dto.setHighestScore(completedTasks.stream()
                    .map(DailyTask::getDtTotalScore)
                    .max(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO));

            dto.setLowestScore(completedTasks.stream()
                    .map(DailyTask::getDtTotalScore)
                    .min(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO));
        } else {
            dto.setAverageScore(BigDecimal.ZERO);
            dto.setHighestScore(BigDecimal.ZERO);
            dto.setLowestScore(BigDecimal.ZERO);
        }

        // 7. 按部门统计（Top 10）
        Map<Long, List<DailyTask>> deptTasksMap = allTasks.stream()
                .filter(t -> t.getDtDeptId() != null)
                .collect(Collectors.groupingBy(DailyTask::getDtDeptId));

        List<GlobalStatisticsDTO.DeptStatistics> deptStatsList = new ArrayList<>();
        for (Map.Entry<Long, List<DailyTask>> entry : deptTasksMap.entrySet()) {
            List<DailyTask> deptTasks = entry.getValue();
            GlobalStatisticsDTO.DeptStatistics deptStat = new GlobalStatisticsDTO.DeptStatistics();
            deptStat.setDeptId(entry.getKey());
            deptStat.setDeptName(deptTasks.get(0).getDtDeptName());
            deptStat.setTotalTasks(deptTasks.size());

            long deptCompleted = deptTasks.stream()
                    .filter(t -> DailyTaskStatusEnum.COMPLETED.getCode().equals(t.getDtStatus()))
                    .count();
            deptStat.setCompletedTasks((int) deptCompleted);
            deptStat.setCompletionRate(
                    BigDecimal.valueOf(deptCompleted)
                            .multiply(BigDecimal.valueOf(100))
                            .divide(BigDecimal.valueOf(deptTasks.size()), 2, RoundingMode.HALF_UP)
            );

            // 计算部门平均分
            List<DailyTask> deptCompletedTasks = deptTasks.stream()
                    .filter(t -> DailyTaskStatusEnum.COMPLETED.getCode().equals(t.getDtStatus()))
                    .filter(t -> t.getDtTotalScore() != null)
                    .collect(Collectors.toList());

            if (!deptCompletedTasks.isEmpty()) {
                BigDecimal deptTotalScore = deptCompletedTasks.stream()
                        .map(DailyTask::getDtTotalScore)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                deptStat.setAverageScore(deptTotalScore.divide(
                        BigDecimal.valueOf(deptCompletedTasks.size()), 2, RoundingMode.HALF_UP));
            } else {
                deptStat.setAverageScore(BigDecimal.ZERO);
            }

            deptStatsList.add(deptStat);
        }

        // 按任务数降序，取Top 10
        deptStatsList.sort(Comparator.comparing(GlobalStatisticsDTO.DeptStatistics::getTotalTasks).reversed());
        dto.setTopDepts(deptStatsList.stream().limit(10).collect(Collectors.toList()));

        // 8. 按角色统计
        Map<String, List<DailyTask>> roleTasksMap = allTasks.stream()
                .filter(t -> t.getDtRole() != null && !t.getDtRole().isEmpty())
                .flatMap(t -> {
                    // 处理多角色（逗号分隔）
                    String[] roles = t.getDtRole().split(",");
                    return Arrays.stream(roles).map(role -> new AbstractMap.SimpleEntry<>(role.trim(), t));
                })
                .collect(Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue, Collectors.toList())
                ));

        List<GlobalStatisticsDTO.RoleStatistics> roleStatsList = new ArrayList<>();
        for (Map.Entry<String, List<DailyTask>> entry : roleTasksMap.entrySet()) {
            List<DailyTask> roleTasks = entry.getValue();
            GlobalStatisticsDTO.RoleStatistics roleStat = new GlobalStatisticsDTO.RoleStatistics();
            roleStat.setRoleName(entry.getKey());
            roleStat.setTotalTasks(roleTasks.size());

            long roleCompleted = roleTasks.stream()
                    .filter(t -> DailyTaskStatusEnum.COMPLETED.getCode().equals(t.getDtStatus()))
                    .count();
            roleStat.setCompletedTasks((int) roleCompleted);
            roleStat.setCompletionRate(
                    BigDecimal.valueOf(roleCompleted)
                            .multiply(BigDecimal.valueOf(100))
                            .divide(BigDecimal.valueOf(roleTasks.size()), 2, RoundingMode.HALF_UP)
            );

            // 计算角色平均分
            List<DailyTask> roleCompletedTasks = roleTasks.stream()
                    .filter(t -> DailyTaskStatusEnum.COMPLETED.getCode().equals(t.getDtStatus()))
                    .filter(t -> t.getDtTotalScore() != null)
                    .collect(Collectors.toList());

            if (!roleCompletedTasks.isEmpty()) {
                BigDecimal roleTotalScore = roleCompletedTasks.stream()
                        .map(DailyTask::getDtTotalScore)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                roleStat.setAverageScore(roleTotalScore.divide(
                        BigDecimal.valueOf(roleCompletedTasks.size()), 2, RoundingMode.HALF_UP));
            } else {
                roleStat.setAverageScore(BigDecimal.ZERO);
            }

            roleStatsList.add(roleStat);
        }

        // 按任务数降序排序
        roleStatsList.sort(Comparator.comparing(GlobalStatisticsDTO.RoleStatistics::getTotalTasks).reversed());
        dto.setRoleStatistics(roleStatsList);

        return dto;
    }
}
