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

import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.jutil.jdk.web.db.Page;
import cn.reghao.jutil.jdk.web.db.PageList;
import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.jdk.string.SnowFlake;
import cn.reghao.tnb.common.auth.UserContext;
import cn.reghao.tnb.common.db.KeyValue;
import cn.reghao.tnb.content.app.exam.db.mapper.QuestionMapper;
import cn.reghao.tnb.content.app.exam.db.mapper.QuestionOptionMapper;
import cn.reghao.tnb.content.app.exam.db.mapper.SubjectMapper;
import cn.reghao.tnb.content.app.exam.model.constant.QuestionLevel;
import cn.reghao.tnb.content.app.exam.model.constant.QuestionType;
import cn.reghao.tnb.content.app.exam.model.dto.QuestionAddDto;
import cn.reghao.tnb.content.app.exam.model.po.Question;
import cn.reghao.tnb.content.app.exam.model.po.QuestionOption;
import cn.reghao.tnb.content.app.exam.model.po.Subject;
import cn.reghao.tnb.content.app.exam.model.query.QuestionQuery;
import cn.reghao.tnb.content.app.exam.model.vo.QuestionDetail;
import cn.reghao.tnb.content.app.exam.model.vo.QuestionOptionDetail;
import cn.reghao.tnb.content.app.exam.model.vo.QuestionView;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2024-08-24 23:58:28
 */
@Service
public class QuestionService {
    private final QuestionMapper questionMapper;
    private final QuestionOptionMapper questionOptionMapper;
    private final SubjectMapper subjectMapper;
    private SnowFlake idGenerator;

    public QuestionService(QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
                           SubjectMapper subjectMapper) {
        this.questionMapper = questionMapper;
        this.questionOptionMapper = questionOptionMapper;
        this.subjectMapper = subjectMapper;
        this.idGenerator = new SnowFlake(1L, 1L);
    }

    public Result addQuestion(QuestionAddDto questionAddDto) {
        long questionId = idGenerator.nextId();
        int type = questionAddDto.getQuestionType();
        if (type == QuestionType.QUESTION6.getCode()) {
            Question question = new Question(questionId, questionAddDto, true);
            questionMapper.save(question);

            int subjectId = question.getSubjectId();
            Arrays.stream(questionAddDto.getChildren()).forEach(questionAddDto1 -> {
                long questionId1 = idGenerator.nextId();
                Question question1 = new Question(questionId1, questionAddDto1);
                question1.setPid(questionId);
                question1.setSubjectId(subjectId);
                List<QuestionOption> options1 = getQuestionOptions(questionAddDto1);
                save(question1, options1);
            });
        } else {
            Question question = new Question(questionId, questionAddDto);
            List<QuestionOption> options = getQuestionOptions(questionAddDto);
            save(question, options);
        }

        if (type == QuestionType.QUESTION1.getCode()) {
        } else if (type == QuestionType.QUESTION2.getCode()) {
        } else if (type == QuestionType.QUESTION3.getCode()) {
        } else if (type == QuestionType.QUESTION4.getCode()) {
        } else if (type == QuestionType.QUESTION5.getCode()) {
        } else if (type == QuestionType.QUESTION6.getCode()) {
        } else {
        }

        return Result.success();
    }

    public Result deleteQuestion(long questionId) {
        Question question = questionMapper.findByQuestionId(questionId);
        if (question.getChild()) {
            List<Question> children = questionMapper.findByPid(questionId);
            children.forEach(question1 -> {
                long questionId1 = question1.getQuestionId();
                questionOptionMapper.deleteByQuestionId(questionId1);
                questionMapper.deleteByQuestionId(questionId1);
            });
        }

        questionOptionMapper.deleteByQuestionId(questionId);
        questionMapper.deleteByQuestionId(questionId);
        return Result.success();
    }

    private List<QuestionOption> getQuestionOptions(QuestionAddDto questionAddDto) {
        QuestionAddDto.Option[] optionArr = questionAddDto.getOptions();
        List<QuestionOption> options = new ArrayList<>(optionArr.length);
        for (int i = 0; i < optionArr.length; i++) {
            int pos = i+1;
            QuestionOption questionOption = new QuestionOption(pos, optionArr[i]);
            options.add(questionOption);
        }

        return options;
    }

    private void save(Question question, List<QuestionOption> options) {
        questionMapper.save(question);
        long questionId = question.getQuestionId();
        options.forEach(questionOption -> questionOption.setQuestionId(questionId));
        if (!options.isEmpty()) {
            questionOptionMapper.saveAll(options);
        }
    }

    public PageList<QuestionView> getQuestions(QuestionQuery questionQuery) {
        int total = questionMapper.countByCriteria(questionQuery);
        Page page = questionQuery.getPage();
        List<Question> list = questionMapper.findQuestionByPage(page, questionQuery);
        List<QuestionView> list1 = list.stream().map(this::getQuestionView).collect(Collectors.toList());
        return PageList.pageList(page, total, list1);
    }

    private QuestionView getQuestionView(Question question) {
        long questionId = question.getQuestionId();
        int subjectId = question.getSubjectId();
        Subject subject = subjectMapper.findById(subjectId);
        int type = question.getType();
        String typeStr = QuestionType.getDescByCode(type);
        int level = question.getLevel();
        String levelStr = QuestionLevel.getDescByCode(level);

        String createBy = UserContext.getUserId() + "";
        String createAt = DateTimeConverter.format(question.getCreateTime());
        return new QuestionView(questionId, subject.getName(), typeStr, type, levelStr, question.getContent(), createBy, createAt);
    }

    public QuestionDetail getQuestionDetail(long questionId) {
        Question question = questionMapper.findByQuestionId(questionId);
        List<QuestionOptionDetail> options = questionOptionMapper.findByQuestionId(questionId).stream()
                .map(QuestionOptionDetail::new)
                .collect(Collectors.toList());

        int subjectId = question.getSubjectId();
        Subject subject = subjectMapper.findById(subjectId);
        int type = question.getType();
        String typeStr = QuestionType.getDescByCode(type);
        int level = question.getLevel();
        String levelStr = QuestionLevel.getDescByCode(level);
        QuestionDetail questionDetail = new QuestionDetail(question, subject.getName(), typeStr, levelStr, options);
        if (type == QuestionType.QUESTION6.getCode()) {
            List<QuestionDetail> list1 = questionMapper.findByPid(questionId).stream().map(question1 -> {
                long questionId1 = question1.getQuestionId();
                int type1 = question1.getType();
                String typeStr1 = QuestionType.getDescByCode(type1);
                int level1 = question1.getLevel();
                String levelStr1 = QuestionLevel.getDescByCode(level1);
                List<QuestionOptionDetail> options1 = questionOptionMapper.findByQuestionId(questionId1).stream()
                        .map(QuestionOptionDetail::new)
                        .collect(Collectors.toList());
                return new QuestionDetail(question1, subject.getName(), typeStr1, levelStr1, options1);
            }).collect(Collectors.toList());
            questionDetail.setChildren(list1);
        }

        return questionDetail;
    }

    public List<KeyValue> getKeyValues() {
        return Arrays.stream(QuestionType.values())
                .map(type -> {
                    int code = type.getCode();
                    String desc = type.getDesc();
                    return new KeyValue(code, desc);
                }).collect(Collectors.toList());
    }
}
