package com.ynfy.buss.exam.examreview.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ynfy.buss.exam.exam.enums.PaperState;
import com.ynfy.buss.exam.exam.service.IExamService;
import com.ynfy.buss.exam.examreview.dto.ExamPreviewDTO;
import com.ynfy.buss.exam.examreview.dto.PreviewSubmitDTO;
import com.ynfy.buss.exam.examreview.entity.ExamReview;
import com.ynfy.buss.exam.examreview.mapper.ExamReviewMapper;
import com.ynfy.buss.exam.examreview.service.IExamReviewService;
import com.ynfy.buss.exam.question.enums.QuestionType;
import com.ynfy.buss.exam.userexam.entity.UserExam;
import com.ynfy.buss.exam.userexam.service.IUserExamService;
import com.ynfy.buss.exam.userexamquestion.entity.UserExamQuestion;
import com.ynfy.buss.exam.userexamquestion.service.IUserExamQuestionService;
import com.ynfy.buss.exam.userexamresult.service.IUserExamResultService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 * @Description: 阅卷表
 * @Author: jeecg-boot
 * @Date: 2023-04-08
 * @Version: V1.0
 */
@Service
public class ExamReviewServiceImpl extends ServiceImpl<ExamReviewMapper, ExamReview> implements IExamReviewService {

    @Autowired
    private ExamReviewMapper examReviewMapper;

    @Autowired
    private IUserExamService userExamService;

    @Autowired
    private IUserExamQuestionService userExamQuestionService;

    @Autowired
    private IUserExamResultService userExamResultService;

    @Autowired
    private IExamService examService;

    /**
     * 统计需阅卷的考试
     *
     * @return
     */
    @Override
    public List<ExamReview> calcReview() {
        return examReviewMapper.calcReview();
    }

    @Override
    public boolean removeByExamIds(List<String> examIds) {
        LambdaQueryWrapper<ExamReview> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(ExamReview::getId, examIds);
        return remove(wrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(List<ExamReview> examReviews) {
        if (!CollectionUtils.isEmpty(examReviews)) {
            List<String> examIds = examReviews.stream().map(ExamReview::getId).collect(Collectors.toList());
            removeByExamIds(examIds);
            saveBatch(examReviews);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void submitPreview(PreviewSubmitDTO dto, LoginUser user) {
        if (StringUtils.isEmpty(dto.getUserExamId())) {
            throw new JeecgBootException("考试ID不能为空");
        }
        UserExam userExam = userExamService.listUserExam(dto.getUserExamId());
        if (Objects.isNull(userExam)) {
            throw new JeecgBootException("考试记录不存在");
        }
        if (PaperState.FINISHED.equals(userExam.getState())) {
            throw new JeecgBootException("该试卷已经阅卷，不允许重复阅卷");
        }
        List<UserExamQuestion> userExamQuestionList = userExam.getUserExamQuestionList();
        if (CollectionUtils.isEmpty(userExamQuestionList)) {
            throw new JeecgBootException("考题查询失败");
        }

        List<UserExamQuestion> rootQuestionList = userExamQuestionList.stream().filter(r -> !Objects.isNull(r.getChild()) && !r.getChild())
                .sorted(Comparator.comparing(UserExamQuestion::getQuestionIndex)).collect(Collectors.toList());
        List<UserExamQuestion> childQuestionList = userExamQuestionList.stream().filter(r -> !Objects.isNull(r.getChild()) && r.getChild())
                .sorted(Comparator.comparing(UserExamQuestion::getQuestionIndex)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(rootQuestionList)) {
            //组装题目、子题目和答案
            examService.assembleUserExamQuestion(dto.getUserExamId(), rootQuestionList, childQuestionList, true, false, true, true, false);
        }
        Map<Integer, UserExamQuestion> userExamQuestionMap = rootQuestionList.stream().collect(Collectors.toMap(UserExamQuestion::getQuestionIndex, a -> a, (k1, k2) -> k1));

        List<ExamPreviewDTO> examPreviews = dto.getExamPreviews();

        if (!CollectionUtils.isEmpty(examPreviews)) {
            List<UserExamQuestion> resultList = new ArrayList<>();
            for (ExamPreviewDTO o : examPreviews) {
                //根据题目序号中获取考题
                UserExamQuestion userExamQuestion = examService.getUserExamQuestionByIndex(o.getIndex(), userExamQuestionMap);
                if (Objects.isNull(userExamQuestion) || userExamQuestion.getQuestionType() != QuestionType.SIMPLE.getCode()) {
                    return;
                }
                userExamQuestion.setActualScore(o.getActualScore());
                userExamQuestion.setIsRight(o.getIsRight());
                resultList.add(userExamQuestion);
            }
            //主观题得分
            double subjectiveScore = resultList.stream().mapToDouble(UserExamQuestion::getActualScore).sum();
            //组合题
            List<UserExamQuestion> combinationQuestionList = rootQuestionList.stream().filter(q ->
                    QuestionType.COMBINATION.getCode().equals(q.getQuestionType())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(combinationQuestionList)) {
                combinationQuestionList.forEach(question -> {
                    //组合题子题目中包含简答题，重新计算分值
                    long simpleCount = question.getSubQuestionList().stream().filter(q -> QuestionType.SIMPLE.getCode()
                            .equals(q.getQuestionType())).count();
                    if (simpleCount > 0) {
                        //更新组合题得分
                        question.setActualScore(question.getSubQuestionList().stream().filter(o ->
                                !Objects.isNull(o.getActualScore())).mapToDouble(UserExamQuestion::getActualScore).sum());
                        if (question.getActualScore() > 0) {
                            question.setIsRight(true);
                        } else {
                            question.setIsRight(false);
                        }
                        resultList.add(question);
                    }
                });
            }

            //更新评分
            if (!CollectionUtils.isEmpty(resultList)) {
                userExamQuestionService.updateBatchById(resultList);
            }

            //用户得分，主观题得分，更新阅卷人，阅卷时间,考试状态
            userExam.setSubjectiveScore(subjectiveScore);//主观题得分
            userExam.setUserScore(NumberUtil.round(NumberUtil.add(userExam.getUserScore().doubleValue(), subjectiveScore),
                    1).doubleValue());//用户最终得分
            userExam.setPreviewTime(new Date());
            //阅卷人
            userExam.setPreviewUser(user.getRealname());
            userExam.setState(PaperState.FINISHED);
            int pass = userExam.getUserScore() >= userExam.getQualifyScore() ? 1 : 0;
            userExam.setPassed(pass);
            userExamService.updateById(userExam);

            //考试完成后加入成绩
            userExamResultService.joinResult(userExam.getUserId(), userExam.getExamId(), userExam.getUserScore(), pass);
        }
    }


    @Override
    public IPage<ExamReview> selectPageList(IPage<ExamReview> page, ExamReview examReview, LoginUser user) {
        return examReviewMapper.selectPageList(page, examReview, user);
    }

}
