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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.exam.domain.DailyTask;
import com.sundot.airport.exam.domain.DailyTaskDetail;
import com.sundot.airport.exam.domain.QuesCat;
import com.sundot.airport.exam.dto.SiteProfileDTO;
import com.sundot.airport.exam.dto.SiteProfileQueryDTO;
import com.sundot.airport.exam.mapper.DailyTaskDetailMapper;
import com.sundot.airport.exam.mapper.DailyTaskMapper;
import com.sundot.airport.exam.service.ISiteProfileService;
import com.sundot.airport.exam.common.service.QuesCatService;
import com.sundot.airport.system.service.ISysDeptService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <b>功能名：</b>SiteProfileServiceImpl<br>
 * <b>说明：</b> 站级画像Service实现 <br>
 * <b>著作权：</b> Copyright (C) 2025 SUNDOT CORPORATION<br>
 * <b>修改履历：
 *
 * @author Claude
 */
@Service
public class SiteProfileServiceImpl implements ISiteProfileService {

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

    @Autowired
    private DailyTaskMapper dailyTaskMapper;

    @Autowired
    private DailyTaskDetailMapper dailyTaskDetailMapper;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private QuesCatService quesCatService;

    @Autowired
    private com.sundot.airport.system.service.IBaseCheckCategoryService baseCheckCategoryService;

    @Override
    public SiteProfileDTO getSiteProfile(SiteProfileQueryDTO query) {
        log.info("获取站级画像 - siteId: {}, startDate: {}, endDate: {}",
                query.getSiteId(), query.getStartDate(), query.getEndDate());

        // 1. 参数校验
        validateQuery(query);

        // 2. 获取站级信息
        SysDept site = deptService.selectDeptById(query.getSiteId());
        if (site == null) {
            throw new ServiceException("站级不存在: siteId=" + query.getSiteId());
        }

        // 3. 验证是否为站级
        DeptHierarchy hierarchy = parseDeptHierarchy(site);
        if (!"SITE".equals(hierarchy.deptType)) {
            throw new ServiceException("该部门不是站级: deptId=" + query.getSiteId());
        }

        // 4. 构建站级画像DTO
        SiteProfileDTO profile = new SiteProfileDTO();
        profile.setSiteId(site.getDeptId());
        profile.setSiteName(site.getDeptName());
        profile.setPeriod(query.getStartDate() + " ~ " + query.getEndDate());

        // 5. 计算站级平均分
        profile.setAvgScore(calculateSiteAvgScore(query));

        // 6. 计算总错题数量
        profile.setTotalErrors(calculateTotalErrors(query));

        // 7. 计算站点整体的分类错题统计
        profile.setSiteCategoryErrors(calculateSiteCategoryErrors(query));

        // 8. 按科室分组计算各分类错题数量
        profile.setDeptCategoryErrors(calculateDeptCategoryErrors(query));

        return profile;
    }

    /**
     * 参数校验
     */
    private void validateQuery(SiteProfileQueryDTO query) {
        if (query.getSiteId() == null) {
            throw new ServiceException("站级ID不能为空");
        }
        if (query.getStartDate() == null || query.getStartDate().trim().isEmpty()) {
            throw new ServiceException("开始日期不能为空");
        }
        if (query.getEndDate() == null || query.getEndDate().trim().isEmpty()) {
            throw new ServiceException("结束日期不能为空");
        }
    }

    /**
     * 计算站级平均分
     */
    private BigDecimal calculateSiteAvgScore(SiteProfileQueryDTO query) {
        // 获取该站级下所有班组ID
        List<Long> teamIds = getTeamIdsUnderSite(query.getSiteId());

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

        // 查询这些班组在周期内的任务（COMPLETED和EXPIRED）
        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(DailyTask::getDtDeptId, teamIds);
        wrapper.ge(DailyTask::getDtBusinessDate, Date.valueOf(query.getStartDate()));
        wrapper.le(DailyTask::getDtBusinessDate, Date.valueOf(query.getEndDate()));
        wrapper.in(DailyTask::getDtStatus, "COMPLETED", "EXPIRED");
        wrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> tasks = dailyTaskMapper.selectList(wrapper);

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

        // 计算平均分（EXPIRED任务分数算0）
        BigDecimal totalScore = tasks.stream()
                .map(task -> "EXPIRED".equals(task.getDtStatus()) ? BigDecimal.ZERO : task.getDtTotalScore())
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        return totalScore.divide(new BigDecimal(tasks.size()), 2, RoundingMode.HALF_UP);
    }

    /**
     * 计算总错题数量
     */
    private Integer calculateTotalErrors(SiteProfileQueryDTO query) {
        // 获取该站级下所有班组ID
        List<Long> teamIds = getTeamIdsUnderSite(query.getSiteId());

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

        // 查询这些班组在周期内的任务（COMPLETED和EXPIRED）
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.in(DailyTask::getDtDeptId, teamIds);
        taskWrapper.ge(DailyTask::getDtBusinessDate, Date.valueOf(query.getStartDate()));
        taskWrapper.le(DailyTask::getDtBusinessDate, Date.valueOf(query.getEndDate()));
        taskWrapper.in(DailyTask::getDtStatus, "COMPLETED", "EXPIRED");
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

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

        int totalErrors = 0;

        for (DailyTask task : tasks) {
            if ("EXPIRED".equals(task.getDtStatus())) {
                // EXPIRED任务：所有题目都算错题
                LambdaQueryWrapper<DailyTaskDetail> allWrapper = new LambdaQueryWrapper<>();
                allWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                allWrapper.eq(DailyTaskDetail::getDelStatus, 0);
                totalErrors += dailyTaskDetailMapper.selectCount(allWrapper).intValue();
            } else {
                // COMPLETED任务：只统计错题
                LambdaQueryWrapper<DailyTaskDetail> errorWrapper = new LambdaQueryWrapper<>();
                errorWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                errorWrapper.eq(DailyTaskDetail::getDtdIsCorrect, false);
                errorWrapper.eq(DailyTaskDetail::getDelStatus, 0);
                totalErrors += dailyTaskDetailMapper.selectCount(errorWrapper).intValue();
            }
        }

        return totalErrors;
    }

    /**
     * 计算站点整体的分类错题统计（按一级分类）
     */
    private List<SiteProfileDTO.CategoryErrorStatistics> calculateSiteCategoryErrors(SiteProfileQueryDTO query) {
        List<SiteProfileDTO.CategoryErrorStatistics> categoryErrorsList = new ArrayList<>();

        // 获取该站级下所有班组ID
        List<Long> teamIds = getTeamIdsUnderSite(query.getSiteId());

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

        // 查询这些班组在周期内的任务（COMPLETED和EXPIRED）
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.in(DailyTask::getDtDeptId, teamIds);
        taskWrapper.ge(DailyTask::getDtBusinessDate, Date.valueOf(query.getStartDate()));
        taskWrapper.le(DailyTask::getDtBusinessDate, Date.valueOf(query.getEndDate()));
        taskWrapper.in(DailyTask::getDtStatus, "COMPLETED", "EXPIRED");
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

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

        // 获取站点所有错题明细
        List<DailyTaskDetail> errorDetails = new ArrayList<>();

        for (DailyTask task : tasks) {
            if ("EXPIRED".equals(task.getDtStatus())) {
                // EXPIRED任务：所有题目都算错题
                LambdaQueryWrapper<DailyTaskDetail> allWrapper = new LambdaQueryWrapper<>();
                allWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                allWrapper.eq(DailyTaskDetail::getDelStatus, 0);
                errorDetails.addAll(dailyTaskDetailMapper.selectList(allWrapper));
            } else {
                // COMPLETED任务：只统计错题
                LambdaQueryWrapper<DailyTaskDetail> errorWrapper = new LambdaQueryWrapper<>();
                errorWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                errorWrapper.eq(DailyTaskDetail::getDtdIsCorrect, false);
                errorWrapper.eq(DailyTaskDetail::getDelStatus, 0);
                errorDetails.addAll(dailyTaskDetailMapper.selectList(errorWrapper));
            }
        }

        if (errorDetails.isEmpty()) {
            return categoryErrorsList;
        }

        // 按一级分类分组统计错题
        Map<String, Integer> level1CategoryErrorCounts = groupErrorsByLevel1Category(errorDetails);

        // 获取所有一级分类
        com.sundot.airport.system.domain.BaseCheckCategory queryParam = new com.sundot.airport.system.domain.BaseCheckCategory();
        queryParam.setLevel(1);
        List<com.sundot.airport.system.domain.BaseCheckCategory> level1Categories =
                baseCheckCategoryService.selectBaseCheckCategoryList(queryParam);

        // 构建站点分类错题统计列表
        for (com.sundot.airport.system.domain.BaseCheckCategory level1Category : level1Categories) {
            String categoryId = String.valueOf(level1Category.getId());
            Integer errorCount = level1CategoryErrorCounts.getOrDefault(categoryId, 0);

            // 只添加有错题的分类
            if (errorCount > 0) {
                SiteProfileDTO.CategoryErrorStatistics stats = new SiteProfileDTO.CategoryErrorStatistics();
                stats.setCategoryId(categoryId);
                stats.setCategoryName(level1Category.getName());
                stats.setErrorCount(errorCount);
                categoryErrorsList.add(stats);
            }
        }

        // 处理"未分类"的错题
        Integer uncategorizedCount = level1CategoryErrorCounts.getOrDefault(null, 0);
        if (uncategorizedCount > 0) {
            SiteProfileDTO.CategoryErrorStatistics uncategorized = new SiteProfileDTO.CategoryErrorStatistics();
            uncategorized.setCategoryId(null);
            uncategorized.setCategoryName("未分类");
            uncategorized.setErrorCount(uncategorizedCount);
            categoryErrorsList.add(uncategorized);
        }

        // 按错题数量降序排序
        categoryErrorsList.sort((a, b) -> b.getErrorCount().compareTo(a.getErrorCount()));

        return categoryErrorsList;
    }

    /**
     * 按科室分组计算各分类错题数量（按一级分类）
     * 只统计在该周期内有任务的科室
     */
    private List<SiteProfileDTO.DeptCategoryErrors> calculateDeptCategoryErrors(SiteProfileQueryDTO query) {
        List<SiteProfileDTO.DeptCategoryErrors> result = new ArrayList<>();

        // 获取该站级下所有科室
        List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());
        List<SysDept> deptsUnderSite = new ArrayList<>();

        for (SysDept dept : allDepts) {
            if ("0".equals(dept.getDelFlag())) {
                DeptHierarchy h = parseDeptHierarchy(dept);
                // 筛选该站级下的所有科室
                if ("DEPT".equals(h.deptType) && query.getSiteId().equals(h.siteId)) {
                    deptsUnderSite.add(dept);
                }
            }
        }

        // 获取所有一级分类
        com.sundot.airport.system.domain.BaseCheckCategory queryParam = new com.sundot.airport.system.domain.BaseCheckCategory();
        queryParam.setLevel(1);
        List<com.sundot.airport.system.domain.BaseCheckCategory> level1Categories =
                baseCheckCategoryService.selectBaseCheckCategoryList(queryParam);

        // 为每个科室计算分类错题
        for (SysDept dept : deptsUnderSite) {
            // 获取该科室下所有班组ID
            List<Long> teamIds = getTeamIdsUnderDept(dept.getDeptId());

            if (teamIds.isEmpty()) {
                continue;
            }

            // 查询这些班组在周期内的任务
            LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
            taskWrapper.in(DailyTask::getDtDeptId, teamIds);
            taskWrapper.ge(DailyTask::getDtBusinessDate, Date.valueOf(query.getStartDate()));
            taskWrapper.le(DailyTask::getDtBusinessDate, Date.valueOf(query.getEndDate()));
            taskWrapper.in(DailyTask::getDtStatus, "COMPLETED", "EXPIRED");
            taskWrapper.eq(DailyTask::getDelStatus, 0);
            List<DailyTask> tasks = dailyTaskMapper.selectList(taskWrapper);

            // 如果该科室在该周期内没有任务，跳过
            if (tasks.isEmpty()) {
                continue;
            }

            // 获取该科室所有错题明细
            List<DailyTaskDetail> errorDetails = new ArrayList<>();

            for (DailyTask task : tasks) {
                if ("EXPIRED".equals(task.getDtStatus())) {
                    // EXPIRED任务：所有题目都算错题
                    LambdaQueryWrapper<DailyTaskDetail> allWrapper = new LambdaQueryWrapper<>();
                    allWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                    allWrapper.eq(DailyTaskDetail::getDelStatus, 0);
                    errorDetails.addAll(dailyTaskDetailMapper.selectList(allWrapper));
                } else {
                    // COMPLETED任务：只统计错题
                    LambdaQueryWrapper<DailyTaskDetail> errorWrapper = new LambdaQueryWrapper<>();
                    errorWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                    errorWrapper.eq(DailyTaskDetail::getDtdIsCorrect, false);
                    errorWrapper.eq(DailyTaskDetail::getDelStatus, 0);
                    errorDetails.addAll(dailyTaskDetailMapper.selectList(errorWrapper));
                }
            }

            if (errorDetails.isEmpty()) {
                continue;
            }

            // 按一级分类分组统计错题
            Map<String, Integer> level1CategoryErrorCounts = groupErrorsByLevel1Category(errorDetails);

            // 构建该科室的分类错题列表
            List<SiteProfileDTO.CategoryErrorStatistics> categoryErrorsList = new ArrayList<>();

            for (com.sundot.airport.system.domain.BaseCheckCategory level1Category : level1Categories) {
                String categoryId = String.valueOf(level1Category.getId());
                Integer errorCount = level1CategoryErrorCounts.getOrDefault(categoryId, 0);

                // 只添加有错题的分类
                if (errorCount > 0) {
                    SiteProfileDTO.CategoryErrorStatistics stats = new SiteProfileDTO.CategoryErrorStatistics();
                    stats.setCategoryId(categoryId);
                    stats.setCategoryName(level1Category.getName());
                    stats.setErrorCount(errorCount);
                    categoryErrorsList.add(stats);
                }
            }

            // 处理"未分类"的错题
            Integer uncategorizedCount = level1CategoryErrorCounts.getOrDefault(null, 0);
            if (uncategorizedCount > 0) {
                SiteProfileDTO.CategoryErrorStatistics uncategorized = new SiteProfileDTO.CategoryErrorStatistics();
                uncategorized.setCategoryId(null);
                uncategorized.setCategoryName("未分类");
                uncategorized.setErrorCount(uncategorizedCount);
                categoryErrorsList.add(uncategorized);
            }

            // 按错题数量降序排序
            categoryErrorsList.sort((a, b) -> b.getErrorCount().compareTo(a.getErrorCount()));

            // 构建科室错题统计
            SiteProfileDTO.DeptCategoryErrors deptErrors = new SiteProfileDTO.DeptCategoryErrors();
            deptErrors.setDeptId(dept.getDeptId());
            deptErrors.setDeptName(dept.getDeptName());
            deptErrors.setCategoryErrors(categoryErrorsList);

            result.add(deptErrors);
        }

        return result;
    }

    /**
     * 获取站级下所有班组ID
     */
    private List<Long> getTeamIdsUnderSite(Long siteId) {
        List<Long> teamIds = new ArrayList<>();
        List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());

        for (SysDept dept : allDepts) {
            if ("0".equals(dept.getDelFlag())) {
                DeptHierarchy h = parseDeptHierarchy(dept);
                // 筛选该站级下的所有班组
                if ("TEAM".equals(h.deptType) && siteId.equals(h.siteId)) {
                    teamIds.add(dept.getDeptId());
                }
            }
        }

        return teamIds;
    }

    /**
     * 获取科室下所有班组ID
     */
    private List<Long> getTeamIdsUnderDept(Long deptId) {
        List<Long> teamIds = new ArrayList<>();
        List<SysDept> allDepts = deptService.selectDeptInfoAll(new SysDept());

        for (SysDept dept : allDepts) {
            if ("0".equals(dept.getDelFlag())) {
                DeptHierarchy h = parseDeptHierarchy(dept);
                // 筛选该科室下的所有班组
                if ("TEAM".equals(h.deptType) && deptId.equals(h.deptId)) {
                    teamIds.add(dept.getDeptId());
                }
            }
        }

        return teamIds;
    }

    /**
     * 解析部门层级
     */
    private DeptHierarchy parseDeptHierarchy(SysDept dept) {
        DeptHierarchy hierarchy = new DeptHierarchy();

        String ancestors = dept.getAncestors();
        Long deptId = dept.getDeptId();

        if (ancestors == null || ancestors.trim().isEmpty()) {
            // 没有ancestors，当前dept_id可能是站级
            hierarchy.siteId = deptId;
            hierarchy.deptId = deptId;
            hierarchy.teamId = deptId;
            hierarchy.deptType = "SITE";
            return hierarchy;
        }

        // 分割ancestors：0,211,205
        String[] ancestorIds = ancestors.split(",");

        // ancestors[0] = 0 (root)
        // ancestors[1] = 站级ID
        // ancestors[2] = 科级ID
        // dept_id = 班组ID（如果有3层以上）

        if (ancestorIds.length >= 2) {
            hierarchy.siteId = Long.parseLong(ancestorIds[1].trim());
        }

        if (ancestorIds.length >= 3) {
            hierarchy.deptId = Long.parseLong(ancestorIds[2].trim());
        }

        // 判断部门类型
        if (ancestorIds.length == 1) {
            // ancestors = "0"，dept_id是站级
            hierarchy.siteId = deptId;
            hierarchy.deptId = deptId;
            hierarchy.teamId = deptId;
            hierarchy.deptType = "SITE";
        } else if (ancestorIds.length == 2) {
            // ancestors = "0,211"，dept_id是科级
            hierarchy.deptId = deptId;
            hierarchy.teamId = deptId;
            hierarchy.deptType = "DEPT";
        } else if (ancestorIds.length >= 3) {
            // ancestors = "0,211,205"，dept_id是班组
            hierarchy.teamId = deptId;
            hierarchy.deptType = "TEAM";
        }

        return hierarchy;
    }

    /**
     * 部门层级内部类
     */
    private static class DeptHierarchy {
        Long siteId;      // 站级ID
        Long deptId;      // 科级ID
        Long teamId;      // 班组ID
        String deptType;  // 部门类型：SITE/DEPT/TEAM
    }

    /**
     * 按一级分类分组统计错题数量
     * <p>
     * 1. 从DailyTaskDetail中获取二级分类ID（dtdModuleId，即qc_id）
     * 2. 通过qc_id查询edu_cs_ques_cat获取二级分类名称（qc_name）
     * 3. 通过qc_name在base_check_category中查找对应的一级分类
     * 4. 按一级分类ID分组统计
     * 5. 如果找不到对应的一级分类，则归入null（未分类）
     * </p>
     *
     * @param errorDetails 错题明细列表
     * @return 一级分类ID -> 错题数量的Map，key为null表示未分类
     */
    private Map<String, Integer> groupErrorsByLevel1Category(List<DailyTaskDetail> errorDetails) {
        Map<String, Integer> result = new HashMap<>();

        // 缓存二级分类名称到一级分类ID的映射
        Map<String, String> level2NameToLevel1IdCache = new HashMap<>();

        for (DailyTaskDetail detail : errorDetails) {
            String qcId = detail.getDtdModuleId(); // 二级分类ID（edu_cs_ques_cat.qc_id）

            if (qcId == null || qcId.trim().isEmpty()) {
                // 未分类
                result.put(null, result.getOrDefault(null, 0) + 1);
                continue;
            }

            // 查询二级分类名称
            LambdaQueryWrapper<QuesCat> catWrapper = new LambdaQueryWrapper<>();
            catWrapper.eq(QuesCat::getQcId, qcId);
            catWrapper.eq(QuesCat::getDelStatus, 0);
            QuesCat quesCat = quesCatService.getOne(catWrapper);

            if (quesCat == null || quesCat.getQcName() == null) {
                // 找不到二级分类，归入未分类
                result.put(null, result.getOrDefault(null, 0) + 1);
                continue;
            }

            String qcName = quesCat.getQcName();

            // 检查缓存
            String level1CategoryId;
            if (level2NameToLevel1IdCache.containsKey(qcName)) {
                level1CategoryId = level2NameToLevel1IdCache.get(qcName);
            } else {
                // 通过二级分类名称查找对应的一级分类
                com.sundot.airport.system.domain.BaseCheckCategory level1Category =
                        baseCheckCategoryService.selectLevel1ByLevel2Name(qcName);

                if (level1Category != null) {
                    level1CategoryId = String.valueOf(level1Category.getId());
                    level2NameToLevel1IdCache.put(qcName, level1CategoryId);
                } else {
                    // 找不到一级分类，归入未分类
                    level1CategoryId = null;
                    level2NameToLevel1IdCache.put(qcName, null);
                }
            }

            // 按一级分类ID统计
            result.put(level1CategoryId, result.getOrDefault(level1CategoryId, 0) + 1);
        }

        return result;
    }
}
