package com.seer.teach.teacher.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seer.teach.common.enums.teacher.ModuleEnum;
import com.seer.teach.common.enums.teacher.TaskStatusEnum;
import com.seer.teach.teacher.common.req.DoExerciseReq;
import com.seer.teach.teacher.common.resp.DoExerciseResp;
import com.seer.teach.teacher.convert.QuestionConvert;
import com.seer.teach.teacher.convert.TaskConvert;
import com.seer.teach.teacher.module.entity.BankQuestionsEntity;
import com.seer.teach.teacher.module.entity.EvaluationQuestionsEntity;
import com.seer.teach.teacher.module.entity.EvaluationTasksEntity;
import com.seer.teach.teacher.module.mapper.EvaluationTasksMapper;
import com.seer.teach.teacher.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 评测任务服务实现类。提供评测任务创建、题目生成与存储、结果推送及记录查询等功能。
 * </p>
 *
 * @author Captain
 * @since 2025-05-13
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class EvaluationTasksServiceImpl extends ServiceImpl<EvaluationTasksMapper, EvaluationTasksEntity> implements EvaluationTasksService {

    private final static Integer QUESTION_COUNT = 30;

    private final static String DEFAULT_ANSWER = "未回答";

    private final KnowledgePointService knowledgePointService;

    private final VersionsService versionsService;

    private final BankQuestionsService bankQuestionsService;

    private final EvaluationQuestionsService evaluationQuestionsService;

    /**
     * 执行评测练习流程：根据用户请求生成评测题目并保存评测任务及相关题目信息。
     *
     * @param params 包含知识点ID等参数的请求对象
     * @return 返回用于前端展示的评测练习响应数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public DoExerciseResp doExercise(DoExerciseReq params) {
        Integer userId = StpUtil.getLoginIdAsInt();
        // 根据用户和知识点生成评测题目
        List<BankQuestionsEntity> questions = bankQuestionsService.generateEvaluationQuestions(userId, params.getId(), QUESTION_COUNT);
        // 创建评测任务
        EvaluationTasksEntity taskData = insertEvaluationTask(params, userId);
        // 将题目关联到当前任务中
        List<EvaluationQuestionsEntity> evaluationQuestions = insertEvaluationQuestion(questions, taskData.getId());
        List<Integer> ids = evaluationQuestions.stream()
                .map(EvaluationQuestionsEntity::getId).collect(Collectors.toList());
        Map<Integer, Integer> idQuestionIdMaps = evaluationQuestions.stream()
                .collect(Collectors.toMap(EvaluationQuestionsEntity::getId, EvaluationQuestionsEntity::getQuestionId));
        return bankQuestionsService.buildDoExerciseResp(taskData.getId(),questions,ids,idQuestionIdMaps, ModuleEnum.EVALUATION.getCode());
    }

    /**
     * 将生成的题目录入评测题目表，并绑定至指定的评测任务。
     *
     * @param questions 题目列表
     * @param taskId    当前评测任务ID
     * @return 录入后的评测题目实体列表
     */
    private List<EvaluationQuestionsEntity> insertEvaluationQuestion(List<BankQuestionsEntity> questions, Integer taskId) {
        List<EvaluationQuestionsEntity> savQuestions = questions.stream()
                .map(q -> QuestionConvert.INSTANCE.toEvaluationQuestionEntity(q.getId(), taskId, DEFAULT_ANSWER))
                .collect(Collectors.toList());
        evaluationQuestionsService.saveBatch(savQuestions);
        return savQuestions;
    }

    /**
     * 构建并插入一条新的评测任务记录。
     *
     * @param params 请求参数，包含知识点ID等信息
     * @param userId 用户ID
     * @return 新增的任务实体对象
     */
    private EvaluationTasksEntity insertEvaluationTask(DoExerciseReq params, Integer userId) {
        Integer knowId = params.getId();
        Integer gradeId = knowledgePointService.getGradeIdByKnowId(knowId);
        Integer subject = versionsService.getSubjectIdByKnowID(knowId);
        EvaluationTasksEntity taskData = TaskConvert.INSTANCE.toEvaluationTaskEntity(userId, knowId, subject, gradeId, TaskStatusEnum.STUDYING.getCode(), LocalDateTime.now(), QUESTION_COUNT);
        this.save(taskData);
        return taskData;
    }

    /**
     * 分页获取用户的评测任务历史记录。
     *
     * @param userId 用户ID
     * @param page   当前页码（从1开始）
     * @param size   每页条数
     * @return 分页后的评测任务列表
     */
    @Override
    public IPage<EvaluationTasksEntity> getEvaluationRecordByDeviceId(Integer userId, Integer page, Integer size) {
        Page<EvaluationTasksEntity> pageParam = new Page<>(page, size);
        return page(pageParam, new LambdaQueryWrapper<EvaluationTasksEntity>()
                .eq(EvaluationTasksEntity::getUserId, userId)
                .orderByDesc(EvaluationTasksEntity::getCreateTime));
    }
}
