package com.ruoyi.abuwx.service.impl.exam;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import com.ruoyi.abuwx.domain.exam.ExmQuestionAnswer;
import com.ruoyi.abuwx.domain.exam.ExmQuestionOption;
import com.ruoyi.abuwx.domain.exam.ExmQuestionType;
import com.ruoyi.abuwx.service.exam.IExmQuestionAnswerService;
import com.ruoyi.abuwx.service.exam.IExmQuestionOptionService;
import com.ruoyi.abuwx.service.exam.IExmQuestionTypeService;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.abuwx.util.ex.QuestionUtil;
import com.ruoyi.common.utils.ex.CurLoginUserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.abuwx.mapper.exam.ExmQuestionMapper;
import com.ruoyi.abuwx.domain.exam.ExmQuestion;
import com.ruoyi.abuwx.service.exam.IExmQuestionService;

/**
 * 试题Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-05-17
 */
@Service
public class ExmQuestionServiceImpl implements IExmQuestionService 
{
    @Autowired
    private ExmQuestionMapper exmQuestionMapper;

    @Autowired
    private IExmQuestionTypeService exmQuestionTypeService;

    @Autowired
    private IExmQuestionAnswerService questionAnswerService;

    @Autowired
    private IExmQuestionOptionService questionOptionService;

    /**
     * 查询试题
     * 
     * @param id 试题主键
     * @return 试题
     */
    @Override
    public ExmQuestion selectExmQuestionById(Long id)
    {
        return exmQuestionMapper.selectExmQuestionById(id);
    }

    /**
     * 查询试题列表
     * 
     * @param exmQuestion 试题
     * @return 试题
     */
    @Override
    public List<ExmQuestion> selectExmQuestionList(ExmQuestion exmQuestion)
    {
        return exmQuestionMapper.selectExmQuestionList(exmQuestion);
    }

    /**
     * 新增试题
     * 
     * @param exmQuestion 试题
     * @return 结果
     */
    @Override
    public int insertExmQuestion(ExmQuestion exmQuestion)
    {
        int result = 0;
        ExmQuestionType questionType = exmQuestionTypeService.selectExmQuestionTypeById(exmQuestion.getQuestionTypeId());
        if (questionType == null){
            throw new BaseException("未选择题库或者选择题库不存在");
        }
        List<String> options = exmQuestion.getQuestionOptions();
        List<String> answers = exmQuestion.getQuestionAnswers();
        List<BigDecimal> scores = exmQuestion.getScores();

        //校验
        addValid(exmQuestion, options, answers, scores,
                questionType);
        exmQuestion.setCreateTime(new Date());
        exmQuestion.setCreateUserId(CurLoginUserUtil.getUserId());
        result = exmQuestionMapper.insertExmQuestion(exmQuestion);

        // 添加答案
        addQuestionAnswer(exmQuestion, answers, scores);

        // 添加选项
        addQuestionOption(exmQuestion, options);

        // 保存附件
//        addQuestionFile(question, options);
        return result;
    }

    /**
     * 修改试题
     * 
     * @param exmQuestion 试题
     * @return 结果
     */
    @Override
    public int updateExmQuestion(ExmQuestion exmQuestion)
    {
        exmQuestion.setUpdateTime(DateUtils.getNowDate());
        return exmQuestionMapper.updateExmQuestion(exmQuestion);
    }

    /**
     * 批量删除试题
     * 
     * @param ids 需要删除的试题主键
     * @return 结果
     */
    @Override
    public int deleteExmQuestionByIds(Long[] ids)
    {
        return exmQuestionMapper.deleteExmQuestionByIds(ids);
    }

    /**
     * 删除试题信息
     * 
     * @param id 试题主键
     * @return 结果
     */
    @Override
    public int deleteExmQuestionById(Long id)
    {
        return exmQuestionMapper.deleteExmQuestionById(id);
    }

    private void addValid(ExmQuestion question, List<String> options, List<String> answers, List<BigDecimal> scores,
                          ExmQuestionType questionType) {
        if (!(CurLoginUserUtil.isSelf(questionType.getCreateUserId()) || CurLoginUserUtil.isAdmin())) {// 子管理可以改自己创建的题库，管理员可以改所有子管理的题库
            throw new BaseException("无操作权限");
        }

        if (StringUtils.isNull(question.getType())) {
            throw new BaseException("参数错误：type");
        }
        if (StringUtils.isEmpty(question.getTitle())) {
            throw new BaseException("参数错误：title");
        }
        if (StringUtils.isEmpty(answers)) {
            throw new BaseException("参数错误：answers");
        }
        if (StringUtils.isNull(question.getScore())) {
            throw new BaseException("参数错误：score");
        }

        if (QuestionUtil.hasSingleChoice(question)) {// 如果是单选
            if (question.getMarkType() != 1) {
                throw new BaseException("参数错误：markType");
            }
            if (StringUtils.isEmpty(question.getMarkOptions())) {
                throw new BaseException("参数错误：markOptions");
            }
            if (StringUtils.isEmpty(options)) {
                throw new BaseException("参数错误：options");
            }
            if (options.size() < 2) {
                throw new BaseException("参数错误：options长度小于2");
            }
            if (answers.size() != 1) {
                throw new BaseException("参数错误：answers");
            }
            if (!"ABCDEFG".contains(answers.get(0))) {
                throw new BaseException("参数错误：answer");
            }
            int answerIndex = answers.get(0).getBytes()[0] - 65;
            if (options.size() < answerIndex + 1) {// 总共四个选项，答案是E就是有问题的
                throw new BaseException("选项和答案不匹配");
            }
            if (StringUtils.isEmpty(scores)) {
                throw new BaseException("参数错误：scores");
            }
        } else if (QuestionUtil.hasMultipleChoice(question)) {// 如果是多选
            if (question.getMarkType() != 1) {
                throw new BaseException("参数错误：markType");
            }
            if (StringUtils.isEmpty(question.getMarkOptions())) {
                throw new BaseException("参数错误：markOptions");
            }
            if (StringUtils.isEmpty(options)) {
                throw new BaseException("参数错误：options");
            }
            if (options.size() < 2) {
                throw new BaseException("参数错误：options长度小于2");
            }
            if (answers.size() < 2) { // 最少两个答案
                throw new BaseException("参数错误：answers最少两个答案");
            }
            for (int i = 0; i < answers.size(); i++) {
                if (!"ABCDEFG".contains(answers.get(i))) {
                    throw new BaseException("参数错误：answers");
                }
                int answerIndex = answers.get(i) .getBytes()[0] - 65;
                if (options.size() < answerIndex + 1) {// 总共四个选项，答案包含E就是有问题的
                    throw new BaseException("选项和答案不匹配");
                }
            }
            if (scores.size() != 1) {
                throw new BaseException("参数错误：scores");
            }
            if (question.getScore().subtract(scores.get(0)).doubleValue() <= 0) {
                throw new BaseException("漏选分数大于试题分数");
            }
        } else if (QuestionUtil.hasFillBlank(question)) {
            if (question.getMarkType() != 1 && question.getMarkType() != 2) {
                throw new BaseException("参数错误：markType");
            }
            if (StringUtils.isEmpty(options)) {
                throw new BaseException("参数错误：options");
            }
            int fillBlankNum = QuestionUtil.getFillBlankNum(question.getTitle());
            if (fillBlankNum == 0) {
                throw new BaseException("最少1个填空");
            }
            if (fillBlankNum > 7) {
                throw new BaseException("最多7个填空");
            }
            if (fillBlankNum != answers.size()) {
                throw new BaseException("填空和答案数量不匹配");
            }

            if (QuestionUtil.hasObjective(question)) {
                if (StringUtils.isEmpty(question.getMarkOptions())) {
                    if (question.getMarkOptionVos().size() > 2) {
                        throw new BaseException("参数错误：scoreOption");
                    }
                    for (Integer markOption : question.getMarkOptionVos()) {
                        if (markOption != 2 && markOption != 3) {// 分值选项（2：答案无顺序；3：不区分大小写；)
                            throw new BaseException("参数错误：scoreOption");
                        }
                    }
                }

                if (StringUtils.isEmpty(scores)) {
                    throw new BaseException("参数错误：scores");
                }
                if (scores.size() != answers.size()) {
                    throw new BaseException("答案和分数不匹配");
                }

                BigDecimal totalScore = BigDecimal.ZERO;
                for (BigDecimal answerScore : scores) {
                    totalScore.add(answerScore);
                }
                if (totalScore.subtract(question.getScore()).doubleValue() != 0) {
                    throw new BaseException("单项分值合计和总分数不匹配");
                }
            }
            if (QuestionUtil.hasSubjective(question)) {
                if (StringUtils.isEmpty(question.getMarkOptions())) {
                    throw new BaseException("参数错误：scoreOption");
                }
                // if (ValidateUtil.isValid(scores)) {
                // throw new MyException("参数错误：scores");
                // } // 主观填空允许有子分数
            }
        } else if (QuestionUtil.hasTrueFalse(question)) {
            if (question.getMarkType() != 1) {
                throw new BaseException("参数错误：markType");
            }
            if (StringUtils.isEmpty(question.getMarkOptions())) {
                throw new BaseException("参数错误：markOptions");
            }
            if (StringUtils.isEmpty(options)) {
                throw new BaseException("参数错误：options");
            }
            if (answers.size() != 1) {
                throw new BaseException("参数错误：answers");
            }

            if (!"对是√否错×".contains(answers.get(0))) {
                throw new BaseException("参数错误：answers");
            }

            if (StringUtils.isEmpty(scores)) {
                throw new BaseException("参数错误：scores");
            }
        } else if (QuestionUtil.hasQA(question)) {
            if (question.getMarkType() != 1 && question.getMarkType() != 2) {
                throw new BaseException("参数错误：markType");
            }
            if (StringUtils.isEmpty(options)) {
                throw new BaseException("参数错误：options");
            }
            if (QuestionUtil.hasObjective(question)) {
                if (StringUtils.isEmpty(question.getMarkOptions())) {
                    if (question.getMarkOptionVos().size() != 1) {
                        throw new BaseException("参数错误：scoreOption");
                    }
                    for (Integer scoreOption : question.getMarkOptionVos()) {
                        if (scoreOption != 3) {// 分值选项（1：漏选得分；2：答案无顺序；3：不区分大小写；)
                            throw new BaseException("参数错误：scoreOption");
                        }
                    }
                }

                if (StringUtils.isEmpty(scores)) {
                    throw new BaseException("参数错误：scores");
                }
                if (scores.size() != answers.size()) {
                    throw new BaseException("答案和分数不匹配");
                }

                BigDecimal totalScore = BigDecimal.ZERO;
                for (BigDecimal answerScore : scores) {
                    totalScore.add(answerScore);
                }
                if (totalScore.subtract(question.getScore()).doubleValue() != 0) {
                    throw new BaseException("单项分值合计和总分数不匹配");
                }
            }
            if (QuestionUtil.hasSubjective(question)) {
                if (StringUtils.isEmpty(question.getMarkOptions())) {
                    throw new BaseException("参数错误：scoreOption");
                }
                if (StringUtils.isEmpty(scores)) {
                    throw new BaseException("参数错误：scores");
                }
            }
        }
    }

    private void addQuestionAnswer(ExmQuestion question, List<String> answers, List<BigDecimal> scores) {
        List<ExmQuestionAnswer> questionAnswerList = questionAnswerService.getList(question.getId());
        for (ExmQuestionAnswer questionAnswer : questionAnswerList) {
            questionAnswerService.deleteExmQuestionAnswerById(questionAnswer.getId());
        }

        if (QuestionUtil.hasSingleChoice(question) || QuestionUtil.hasTrueFalse(question)) {
            ExmQuestionAnswer questionAnswer = new ExmQuestionAnswer();
            questionAnswer.setAnswer(answers.get(0));
            questionAnswer.setScore(null);
            questionAnswer.setQuestionId(question.getId());
            questionAnswer.setNo(1l);
            questionAnswerService.insertExmQuestionAnswer(questionAnswer);
        } else if ((QuestionUtil.hasQA(question) && QuestionUtil.hasSubjective(question))) {// 答案有逗号，接收参数会分隔，这里合并一下
            ExmQuestionAnswer questionAnswer = new ExmQuestionAnswer();
            questionAnswer.setAnswer(StringUtils.join(answers, ","));
            questionAnswer.setScore(null);
            questionAnswer.setQuestionId(question.getId());
            questionAnswer.setNo(1l);
            questionAnswerService.insertExmQuestionAnswer(questionAnswer);
        } else if (QuestionUtil.hasMultipleChoice(question)) {
            ExmQuestionAnswer questionAnswer = new ExmQuestionAnswer();
            Collections.sort(answers);// 页面前选b在选a，传值为ba，排序后在保存
            questionAnswer.setAnswer(StringUtils.join(answers, ","));
            questionAnswer.setScore(scores.get(0));
            questionAnswer.setQuestionId(question.getId());
            questionAnswer.setNo(1l);
            questionAnswerService.insertExmQuestionAnswer(questionAnswer);
        } else if (QuestionUtil.hasFillBlank(question)
                || (QuestionUtil.hasQA(question) && QuestionUtil.hasObjective(question))) {
            for (int i = 0; i < answers.size(); i++) {
                ExmQuestionAnswer questionAnswer = new ExmQuestionAnswer();
                questionAnswer.setAnswer(answers.get(i));
                questionAnswer.setScore(scores.get(i));
                questionAnswer.setQuestionId(question.getId());
                questionAnswer.setNo(i + 1l);
                questionAnswerService.insertExmQuestionAnswer(questionAnswer);
            }
        }
    }

    private void addQuestionOption(ExmQuestion question, List<String> options) {
        List<ExmQuestionOption> questionOptionList = questionOptionService.getList(question.getId());
        for (ExmQuestionOption questionOption : questionOptionList) {
            questionOptionService.deleteExmQuestionOptionById(questionOption.getId());
        }
        if (QuestionUtil.hasSingleChoice(question) || QuestionUtil.hasMultipleChoice(question)) {
            for (int i = 0; i < options.size(); i++) {
                ExmQuestionOption questionOption = new ExmQuestionOption();
                questionOption.setQuestionId(question.getId());
                questionOption.setOptions(options.get(i));
                questionOption.setNo(i + 1l);
                questionOptionService.insertExmQuestionOption(questionOption);
            }
        }
    }
}
