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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysRole;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.exam.domain.*;
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.IDailyTaskConfigService;
import com.sundot.airport.exam.service.IDailyTaskGenerationService;
import com.sundot.airport.exam.service.IQuestionSelectionService;
import com.sundot.airport.exam.util.BusinessDateUtil;
import com.sundot.airport.exam.common.service.QuesCatService;
import com.sundot.airport.system.service.ISysDeptService;
import com.sundot.airport.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <b>功能名：</b>DailyTaskGenerationServiceImpl<br>
 * <b>说明：</b> 每日任务生成Service实现 <br>
 * <b>著作权：</b> Copyright (C) 2025 SUNDOT CORPORATION<br>
 * <b>修改履历：
 *
 * @author Simon Lin
 */
@Service
public class DailyTaskGenerationServiceImpl implements IDailyTaskGenerationService {

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

    @Autowired
    private IDailyTaskConfigService configService;

    @Autowired
    private IQuestionSelectionService questionSelectionService;

    @Autowired
    private DailyTaskMapper dailyTaskMapper;

    @Autowired
    private DailyTaskDetailMapper dailyTaskDetailMapper;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private QuesCatService quesCatService;

    /**
     * 总分
     */
    private static final BigDecimal TOTAL_SCORE = new BigDecimal("100.00");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleClockInEvent(Long userId, Long deptId) {
        log.info("处理考勤打卡事件 - userId: {}, deptId: {}", userId, deptId);

        // 1. 获取用户信息
        SysUser user = userService.selectUserById(userId);
        if (user == null) {
            log.error("用户不存在: userId={}", userId);
            return;
        }

        // 2. 获取用户的所有角色ID列表
        List<Long> roleIds = user.getRoles().stream()
                .map(SysRole::getRoleId)
                .collect(Collectors.toList());

        if (roleIds.isEmpty()) {
            log.info("用户 {} 未分配角色，不生成任务", userId);
            return;
        }

        // 3. 收集所有角色匹配的有效配置
        List<DailyTaskConfig> matchedConfigs = new java.util.ArrayList<>();
        for (Long roleId : roleIds) {
            DailyTaskConfig config = configService.getEffectiveConfig(roleId, deptId);
            if (config != null) {
                matchedConfigs.add(config);
            }
        }

        if (matchedConfigs.isEmpty()) {
            log.info("用户 {} 的所有角色都没有匹配的推题配置，不生成任务", userId);
            return;
        }

        // 4. 选择最新的配置（根据创建时间降序排序，取第一个）
        DailyTaskConfig config = matchedConfigs.stream()
                .sorted((c1, c2) -> c2.getCreateTime().compareTo(c1.getCreateTime()))
                .findFirst()
                .orElse(null);

        log.info("用户 {} 匹配到 {} 个有效配置，选择最新配置ID: {}", userId, matchedConfigs.size(), config.getDtcId());

        // 5. 检查今天已生成的任务数量
        int existingTaskCount = getTodayTaskCount(userId);
        int requiredTaskCount = config.getDtcDailySets();

        if (existingTaskCount >= requiredTaskCount) {
            log.info("用户 {} 今天已有 {} 个答题任务，配置要求 {} 个，不再生成",
                    userId, existingTaskCount, requiredTaskCount);
            return;
        }

        // 6. 计算需要生成的任务数量
        int tasksToGenerate = requiredTaskCount - existingTaskCount;
        log.info("用户 {} 今天已有 {} 个任务，需要补充生成 {} 个任务",
                userId, existingTaskCount, tasksToGenerate);

        // 7. 生成剩余任务
        generateDailyTask(userId, config, tasksToGenerate);

        log.info("用户 {} 的每日任务生成完成", userId);
    }

    @Override
    public boolean hasTaskToday(Long userId) {
        return getTodayTaskCount(userId) > 0;
    }

    /**
     * 获取用户今天已生成的任务数量
     *
     * @param userId 用户ID
     * @return 任务数量
     */
    private int getTodayTaskCount(Long userId) {
        // 获取当前业务日期
        LocalDate businessDate = BusinessDateUtil.getCurrentBusinessDate();

        // 查询该业务日期的任务数量
        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DailyTask::getDtUserId, userId);
        wrapper.eq(DailyTask::getDtBusinessDate, businessDate);
        wrapper.eq(DailyTask::getDelStatus, 0);

        return dailyTaskMapper.selectCount(wrapper).intValue();
    }

    /**
     * 生成每日任务（生成多个独立任务）
     *
     * @param userId 用户ID
     * @param config 配置信息
     * @param taskCount 需要生成的任务数量
     */
    private void generateDailyTask(Long userId, DailyTaskConfig config, int taskCount) {
        LocalDate businessDate = BusinessDateUtil.getCurrentBusinessDate();
        int questionsPerSet = config.getDtcQuestionsPerSet();

        log.info("为用户 {} 生成每日任务，任务数: {}, 每任务题量: {}", userId, taskCount, questionsPerSet);

        // 生成多个独立的任务
        for (int taskNo = 1; taskNo <= taskCount; taskNo++) {
            // 1. 创建任务主记录
            DailyTask task = createDailyTask(userId, config, taskNo);
            dailyTaskMapper.insert(task);

            log.info("为用户 {} 生成第 {} 个任务，任务ID: {}, 题量: {}",
                    userId, taskNo, task.getDtId(), questionsPerSet);

            // 2. 调用组题算法生成题目
            List<Ques> questions = questionSelectionService.generateQuestions(userId, questionsPerSet);

            if (CollUtil.isEmpty(questions)) {
                throw new ServiceException("题库题目不足，无法生成第 " + taskNo + " 个任务");
            }

            // 3. 计算每题分值
            List<BigDecimal> scores = calculateQuestionScores(questions.size());

            // 4. 创建任务明细
            for (int questionNo = 1; questionNo <= questions.size(); questionNo++) {
                Ques question = questions.get(questionNo - 1);
                BigDecimal score = scores.get(questionNo - 1);

                DailyTaskDetail detail = createTaskDetail(task, question, questionNo, score);
                dailyTaskDetailMapper.insert(detail);
            }

            log.info("第 {} 个任务生成成功，任务ID: {}, 共 {} 道题目", taskNo, task.getDtId(), questions.size());
        }

        log.info("用户 {} 的所有每日任务生成完成，共 {} 个任务", userId, taskCount);
    }

    /**
     * 创建任务主记录
     */
    private DailyTask createDailyTask(Long userId, DailyTaskConfig config, int taskNo) {
        LocalDate businessDate = BusinessDateUtil.getCurrentBusinessDate();

        // Calculate expire time: next day 7:00 AM
        LocalDateTime expireDateTime = businessDate.plusDays(1).atTime(7, 0);
        Date expireTime = java.sql.Timestamp.valueOf(expireDateTime);

        // 查询用户信息
        SysUser user = userService.selectUserById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在: userId=" + userId);
        }

        // 获取用户姓名
        String userName = user.getNickName();

        // 获取部门信息（班组）
        Long deptId = user.getDeptId();
        String deptName = null;
        Long departmentId = null;
        String departmentName = null;

        if (deptId != null) {
            SysDept dept = deptService.selectDeptById(deptId);
            if (dept != null) {
                deptName = dept.getDeptName();

                // 获取科室信息（班组的上级）
                Long parentId = dept.getParentId();
                if (parentId != null && parentId != 0) {
                    SysDept parentDept = deptService.selectDeptById(parentId);
                    if (parentDept != null) {
                        departmentId = parentDept.getDeptId();
                        departmentName = parentDept.getDeptName();
                    }
                }
            }
        }

        // 获取角色信息（取第一个角色的roleName或roleId）
        String roleName = null;
        if (user.getRoles() != null && !user.getRoles().isEmpty()) {
            // 获取所有角色名称，用逗号分隔
            roleName = user.getRoles().stream()
                    .map(SysRole::getRoleName)
                    .collect(Collectors.joining(","));
        }

        DailyTask task = new DailyTask();
        task.setDtId(IdUtil.getSnowflakeNextIdStr());
        task.setDtUserId(userId);
        task.setDtUserName(userName);
        task.setDtRole(roleName);
        task.setDtDeptId(deptId);
        task.setDtDeptName(deptName);
        task.setDtDepartmentId(departmentId);
        task.setDtDepartmentName(departmentName);
        task.setDtConfigId(config.getDtcId());
        task.setDtBusinessDate(java.sql.Date.valueOf(businessDate));
        task.setDtClockTime(new Date());
        task.setDtTotalScore(BigDecimal.ZERO);
        task.setDtStatus(DailyTaskStatusEnum.PENDING.getCode());
        task.setDtExpireTime(expireTime);
        task.setDtTimeLimit(config.getDtcTimeLimit()); // 设置答题时间限制
        task.setDelStatus(0);
        task.setCreateTime(new Date());
        task.setCreateUid(userId.toString());

        return task;
    }

    /**
     * 创建任务明细
     */
    private DailyTaskDetail createTaskDetail(DailyTask task, Ques question, int questionNo, BigDecimal score) {
        DailyTaskDetail detail = new DailyTaskDetail();
        detail.setDtdId(IdUtil.getSnowflakeNextIdStr());
        detail.setDtdTaskId(task.getDtId());
        detail.setDtdQuestionNo(questionNo);
        detail.setDtdQuesId(question.getQuId());
        detail.setDtdQuesContent(question.getQuContent());
        detail.setDtdQuesType(question.getQuType().name());

        // 使用 qc_id 关联题目分类，如果为空则显示"未分类"
        String qcId = question.getQcId();
        String categoryName = "未分类";
        if (qcId != null && !qcId.isEmpty()) {
            quesCatService.get(qcId).ifPresent(cat -> {
                // 使用 dtdModuleName 暂存分类名称
            });
            categoryName = quesCatService.get(qcId)
                    .map(QuesCat::getQcName)
                    .orElse("未分类");
        }
        detail.setDtdModuleId(qcId);
        detail.setDtdModuleName(categoryName);

        detail.setDtdScore(score);
        detail.setDtdAnswerStatus("PENDING");
        detail.setDtdIsCorrect(null);
        detail.setDtdActualScore(BigDecimal.ZERO);
        detail.setDelStatus(0);
        detail.setCreateTime(new Date());
        detail.setCreateUid(task.getDtUserId().toString());

        return detail;
    }

    /**
     * 计算每题分值
     * <p>
     * 规则：100分均分给所有题目，最后一题补齐小数差
     * 例如：3题 -> 33.33, 33.33, 33.34
     * </p>
     *
     * @param questionCount 题目数量
     * @return 每题分值列表
     */
    private List<BigDecimal> calculateQuestionScores(int questionCount) {
        // 计算平均分（保留2位小数，向下取整）
        BigDecimal avgScore = TOTAL_SCORE.divide(
                new BigDecimal(questionCount), 2, RoundingMode.DOWN);

        // 计算前N-1题的总分
        BigDecimal sumOfFirstN = avgScore.multiply(new BigDecimal(questionCount - 1));

        // 最后一题补齐差额
        BigDecimal lastScore = TOTAL_SCORE.subtract(sumOfFirstN);

        // 构造分值列表
        List<BigDecimal> scores = new java.util.ArrayList<>();
        for (int i = 0; i < questionCount - 1; i++) {
            scores.add(avgScore);
        }
        scores.add(lastScore);

        return scores;
    }
}
