package cn.reghao.tnb.content.app.exam.service;

import cn.reghao.jutil.jdk.db.Page;
import cn.reghao.jutil.jdk.db.PageList;
import cn.reghao.tnb.account.api.dto.AccountInfo;
import cn.reghao.tnb.account.api.iface.AccountQuery;
import cn.reghao.tnb.content.app.exam.db.mapper.*;
import cn.reghao.tnb.content.app.exam.model.constant.QuestionType;
import cn.reghao.tnb.content.app.exam.model.dto.ExamMarkForm;
import cn.reghao.tnb.content.app.exam.model.dto.UserAnswer;
import cn.reghao.tnb.content.app.exam.model.po.*;
import cn.reghao.tnb.content.app.exam.model.query.ExamQuery;
import cn.reghao.tnb.content.app.exam.model.vo.*;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2024-08-29 09:55:20
 */
@Service
public class ExamResultService {
    @DubboReference(check = false, retries = 0)
    private AccountQuery accountQuery;

    private final PaperMapper paperMapper;
    private final PaperQuestionMapper paperQuestionMapper;
    private final PaperResultMapper paperResultMapper;
    private final PaperAnswerMapper paperAnswerMapper;
    private final QuestionMapper questionMapper;
    private final QuestionOptionMapper questionOptionMapper;
    private final PaperService paperService;

    public ExamResultService(PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
                             PaperResultMapper paperResultMapper, PaperAnswerMapper paperAnswerMapper,
                             QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
                             PaperService paperService) {
        this.paperMapper = paperMapper;
        this.paperQuestionMapper = paperQuestionMapper;
        this.paperResultMapper = paperResultMapper;
        this.paperAnswerMapper = paperAnswerMapper;
        this.questionMapper = questionMapper;
        this.questionOptionMapper = questionOptionMapper;
        this.paperService = paperService;
    }

    public PageList<ExamMark> getExamReviewList(ExamQuery examQuery) {
        int total = paperResultMapper.countByCriteria(examQuery);
        Page page = examQuery.getPage();
        List<ExamResults> list = paperResultMapper.findExamResultsByPage(page, examQuery);
        List<ExamMark> list1 = list.stream()
                .map(examResults -> {
                    long userId = examResults.getStudent();
                    String student = ""+userId;
                    AccountInfo accountInfo = accountQuery.getAccountInfo(userId);
                    if (accountInfo != null) {
                        student = accountInfo.getScreenName();
                    }
                    return new ExamMark(examResults, student);
                })
                .collect(Collectors.toList());
        return PageList.pageList(page, total, list1);
    }

    @Transactional(rollbackFor = Exception.class)
    public void markExamResult(ExamMarkForm examMarkForm) {
        int resultId = examMarkForm.getResultId();
        examMarkForm.getPaperMarks().forEach(examMarkResult -> {
            int questionId = examMarkResult.getQuestionId();
            String review = examMarkResult.getReview();
            int score = examMarkResult.getScore();
            paperAnswerMapper.updatePaperAnswer(resultId, questionId, review, score);
        });
        paperResultMapper.updateSetResultMarked(resultId);
    }

    public PageList<ExamScore> getExamScoreList() {
        ExamQuery examQuery = new ExamQuery.Builder().marked(true).build();
        int total = paperResultMapper.countByCriteria(examQuery);
        Page page = examQuery.getPage();
        List<ExamResults> list = paperResultMapper.findExamResultsByPage(page, examQuery);
        List<ExamScore> list1 = list.stream()
                .map(examResults -> {
                    long userId = examResults.getStudent();
                    AccountInfo accountInfo = accountQuery.getAccountInfo(userId);
                    String student = ""+userId;
                    if (accountInfo != null) {
                        student = accountInfo.getScreenName();
                    }
                    return new ExamScore(examResults, student);
                })
                .collect(Collectors.toList());
        return PageList.pageList(page, total, list1);
    }

    public ExamResult getExamResult(int resultId) {
        PaperResult paperResult = paperResultMapper.findById(resultId);
        if (paperResult.getMarked()) {
            return null;
        }

        List<PaperAnswer> paperAnswers = paperAnswerMapper.findByResultId(resultId);
        Map<Integer, PaperAnswer> answerMap = paperAnswers.stream()
                .collect(Collectors.toMap(PaperAnswer::getQuestionId, paperAnswer -> paperAnswer));

        int paperId = paperResult.getPaperId();
        Paper paper = paperMapper.findById(paperId);
        List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
        paperQuestions.sort(Comparator.comparingInt(PaperQuestion::getPos));

        List<Integer> questionIds = paperQuestions.stream()
                .map(PaperQuestion::getQuestionId)
                .collect(Collectors.toList());
        List<QuestionInfo> questionInfos = paperService.getPaperQuestions(paperId);
        List<QuestionInfo> list = new ArrayList<>();
        for (QuestionInfo questionInfo : questionInfos) {
            List<QuestionInfo> children = questionInfo.getChildren();
            if (children != null) {
                list.addAll(children);
            }
        }

        if (!list.isEmpty()) {
            questionInfos.addAll(list);
        }

        List<QuestionResult> questionResults = getQuestionResults(questionIds, questionInfos, answerMap);
        return new ExamResult(paper, paperResult, questionResults);
    }

    private List<QuestionResult> getQuestionResults(List<Integer> questionIds,
                                                   List<QuestionInfo> questionInfos,
                                                   Map<Integer, PaperAnswer> answerMap) {
        Map<Integer, QuestionInfo> questionMap = questionInfos.stream()
                .collect(Collectors.toMap(QuestionInfo::getQuestionId, k -> k));

        List<Question> questions = questionMapper.findByQuestionIds(questionIds);
        return questions.stream().map(question -> {
            int questionId = question.getId();
            boolean child = question.getChild();
            QuestionResult questionResult;
            if (child) {
                List<QuestionResult> children = questionMapper.findByPid(questionId).stream()
                        .map(question1 -> getQuestionResult(question1, questionMap, answerMap))
                        .collect(Collectors.toList());
                int userScore = children.stream()
                        .map(QuestionResult::getUserScore)
                        .mapToInt(Integer::intValue)
                        .sum();

                questionResult = new QuestionResult();
                QuestionInfo questionInfo = questionMap.get(questionId);
                questionResult.setQuestionInfo(questionInfo);
                questionResult.setChildren(children);
                questionResult.setUserScore(userScore);
            } else {
                questionResult = getQuestionResult(question, questionMap, answerMap);
            }
            return questionResult;
        }).collect(Collectors.toList());
    }

    private QuestionResult getQuestionResult(Question question,
                                             Map<Integer, QuestionInfo> questionMap,
                                             Map<Integer, PaperAnswer> answerMap) {
        int questionId = question.getId();
        List<QuestionOption> questionOptions = questionOptionMapper.findByQuestionId(questionId);
        List<QuestionOption> correctOptions = questionOptions.stream()
                .filter(QuestionOption::getCorrect)
                .collect(Collectors.toList());

        QuestionResult questionResult = new QuestionResult();
        PaperAnswer paperAnswer = answerMap.get(questionId);
        String answer = paperAnswer.getAnswer();
        int type = question.getType();
        if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION4.getCode()) {
            int userPos = Integer.parseInt(answer);
            int correctPos = correctOptions.get(0).getPos();
            questionResult.setUserAnswer(userPos);
            questionResult.setCorrectAnswer(correctPos);
            questionResult.setUserScore(paperAnswer.getScore());
        } else if (type == QuestionType.QUESTION2.getCode() || type == QuestionType.QUESTION3.getCode()) {
            List<Integer> userPosList = Arrays.stream(answer.split(","))
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
            List<Integer> correctPosList = correctOptions.stream()
                    .map(QuestionOption::getPos)
                    .collect(Collectors.toList());
            questionResult.setUserAnswer(userPosList);
            questionResult.setCorrectAnswer(correctPosList);
            questionResult.setUserScore(paperAnswer.getScore());
        } else if (type == QuestionType.QUESTION5.getCode() || type == QuestionType.QUESTION6.getCode()) {
            // 填空题
            // 问答题
            questionResult.setUserAnswer(answer);
            String correctAnswer = correctOptions.get(0).getContent();
            questionResult.setCorrectAnswer(correctAnswer);
            questionResult.setUserScore(paperAnswer.getScore());
        } else {
        }

        QuestionInfo questionInfo = questionMap.get(questionId);
        questionResult.setQuestionInfo(questionInfo);
        return questionResult;
    }
}
