package cn.com.qmth.examcloud.core.questions.service.impl;

import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.IdUtils;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Course;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
import cn.com.qmth.examcloud.core.questions.service.QuestionProviderService;
import cn.com.qmth.examcloud.question.commons.core.question.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Pattern;

/**
 * @author weiwenhai
 * @date 2018.9.10
 * @company qmth
 * @describle 试题对象服务实现类
 * @code 012
 */
@Service("questionProviderService")
public class QuestionProviderServiceImpl implements QuestionProviderService {

    @Autowired
    QuesRepo quesRepo;

    @Autowired
    MongoTemplate mongoTemplate;

    @Override
    public String save(DefaultQuestion defaultQuestion) {
        Question question = new Question();
        if (!StringUtils.isBlank(defaultQuestion.getId())) {
            question.setId(defaultQuestion.getId());
        }
        //初始化默认课程
        Course course = new Course();
        course.setId("k12");
        course.setCode("k12");
        course.setName("k12");
        course.setLevel("ALL");
        course.setOrgId(defaultQuestion.getRootOrgId().toString());
        course.setCreateTime(CommonUtils.getCurDateTime());
        course.setEnable("true");
        question.setCourse(course);
        question.setOrgId(defaultQuestion.getRootOrgId().toString());
        question.setCreateTime(CommonUtils.getCurDateTime());
        question.setDifficulty("中");
        question.setDifficultyDegree(0.5);
        question.setIsolated(true);
        question.setPublicity(true);
        question.setProperties(defaultQuestion.getProperties());
        DefaultQuestionStructure defaultQuestionStructure = (DefaultQuestionStructure) defaultQuestion.getMasterVersion();
        //判断试题单元对象
        List<DefaultQuestionUnit> questionUnitList = defaultQuestionStructure.getQuestionUnitList();
        if (questionUnitList == null || questionUnitList.size() < 1) {
            throw new StatusException("Q-012033", "试题单元对象为空");
        }
        if (questionUnitList.size() == 1) {
            DefaultQuestionUnit defaultQuestionUnit = questionUnitList.get(0);
            //判断试题题型
            if (defaultQuestionUnit.getQuestionType() == null) {
                throw new StatusException("Q-012039", "试题单元中题型为空");
            }
            //设置题干
            question.setQuesBody(defaultQuestionUnit.getBody());
            QuesStructType type = buildQuesType(defaultQuestionUnit.getQuestionType());
            if (type == null) {
                throw new StatusException("Q-012043", "试题单元中题型值不对");
            }
            //设置题型
            question.setQuestionType(type);
            //如果是选择题，判断选项
            if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
                List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
                if (questionOptionList == null || questionOptionList.size() < 1) {
                    throw new StatusException("Q-012049", "试题单元中选项为空");
                }
                //设置选项
                List<QuesOption> quesOptions = buildOptions(questionOptionList, defaultQuestionUnit.getRightAnswer());
                question.setQuesOptions(quesOptions);
            }
            //设置答案
            question.setQuesAnswer(buildAnswer(defaultQuestionUnit));
        } else {
            //套题
            //设置题干
            question.setQuesBody(defaultQuestionStructure.getBody());
            question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
            //生成子题
            List<Question> subList = new ArrayList<>();
            for (DefaultQuestionUnit defaultQuestionUnit : questionUnitList) {
                Question subQues = new Question();
                subQues.setId(IdUtils.uuid());
                subQues.setDifficulty("中");
                subQues.setDifficultyDegree(0.5);
                subQues.setPublicity(true);
                //判断试题题型
                if (defaultQuestionUnit.getQuestionType() == null) {
                    throw new StatusException("Q-012039", "试题单元中题型为空");
                }
                //设置题干
                subQues.setQuesBody(defaultQuestionUnit.getBody());
                QuesStructType type = buildQuesType(defaultQuestionUnit.getQuestionType());
                if (type == null) {
                    throw new StatusException("Q-012043", "试题单元中题型值不对");
                }
                //设置题型
                subQues.setQuestionType(type);
                //如果是选择题，判断选项
                if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
                    List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
                    if (questionOptionList == null || questionOptionList.size() < 1) {
                        throw new StatusException("Q-012049", "试题单元中选项为空");
                    }
                    //设置选项
                    List<QuesOption> quesOptions = buildOptions(questionOptionList, defaultQuestionUnit.getRightAnswer());
                    subQues.setQuesOptions(quesOptions);
                }
                //设置答案
                subQues.setQuesAnswer(buildAnswer(defaultQuestionUnit));
                subList.add(subQues);
            }
            question.setSubQuestions(subList);
        }
        question = quesRepo.save(question);
        return question.getId();
    }

    //构建题型
    private QuesStructType buildQuesType(QuestionType type) {
        if (type == QuestionType.SINGLE_CHOICE) {
            return QuesStructType.SINGLE_ANSWER_QUESTION;
        } else if (type == QuestionType.MULTIPLE_CHOICE) {
            return QuesStructType.MULTIPLE_ANSWER_QUESTION;
        } else if (type == QuestionType.FILL_UP) {
            return QuesStructType.FILL_BLANK_QUESTION;
        } else if (type == QuestionType.ESSAY) {
            return QuesStructType.TEXT_ANSWER_QUESTION;
        } else if (type == QuestionType.TRUE_OR_FALSE) {
            return QuesStructType.BOOL_ANSWER_QUESTION;
        } else {
            return null;
        }
    }

    //构建选择题选项
    private List<QuesOption> buildOptions(List<DefaultQuestionOption> questionOptionList, String[] rightAnswer) {
        List<QuesOption> quesOptions = new ArrayList<>();
        for (int i = 0; i < questionOptionList.size(); i++) {
            DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
            QuesOption option = new QuesOption();
            option.setNumber(String.valueOf(i + 1));
            option.setOptionBody(defaultQuestionOption.getBody());
            if (Arrays.asList(rightAnswer).contains(String.valueOf(i))) {
                option.setIsCorrect((short) 1);
            } else {
                option.setIsCorrect((short) 0);
            }
            quesOptions.add(option);
        }
        return quesOptions;
    }

    //构建答案
    private String buildAnswer(DefaultQuestionUnit defaultQuestionUnit) {
        QuestionType questionType = defaultQuestionUnit.getQuestionType();
        String answer = "";
        String[] answers = defaultQuestionUnit.getRightAnswer();
        if (answers == null || answers.length < 1) {
            return answer;
        }
        if (questionType == QuestionType.SINGLE_CHOICE || questionType == QuestionType.MULTIPLE_CHOICE) {
            for (int i = 0; i < answers.length; i++) {
                int number = Integer.valueOf(answers[i]);
                if (i == 0) {
                    answer = CommonUtils.getOptionNum(number);
                } else {
                    answer = answer + "," + CommonUtils.getOptionNum(number);
                }
            }
            return answer;
        } else if (questionType == QuestionType.FILL_UP) {
            for (int i = 0; i < answers.length; i++) {
                if (i == 0) {
                    answer = answers[i];
                } else {
                    answer = answer + "##" + answers[i];
                }
            }
            return answer;
        } else if (questionType == QuestionType.ESSAY) {
            if (answers[0].equals("true")) {
                answer = "正确";
            } else {
                answer = "错误";
            }
            return answer;
        } else {
            for (int i = 0; i < answers.length; i++) {
                answer = answer + answers[i];
            }
            return answer;
        }
    }

    @Override
    public Page<DefaultQuestion> findQustions(Long rootOrgId, Map<String, String> map, int curPage, int pageSize) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orgId").is(rootOrgId.toString()));
        query.addCriteria(Criteria.where("isolated").is(true));
        if (map != null && map.size() > 0) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                if (entry.getKey().equals("questionType")) {
                    if (!StringUtils.isBlank(entry.getValue())) {
                        if (entry.getValue().equals(QuestionType.SINGLE_CHOICE.toString())) {
                            query.addCriteria(Criteria.where("questionType").is(QuesStructType.SINGLE_ANSWER_QUESTION));
                        } else if (entry.getValue().equals(QuestionType.MULTIPLE_CHOICE.toString())) {
                            query.addCriteria(Criteria.where("questionType").is(QuesStructType.MULTIPLE_ANSWER_QUESTION));
                        } else if (entry.getValue().equals(QuestionType.ESSAY.toString())) {
                            query.addCriteria(Criteria.where("questionType").is(QuesStructType.TEXT_ANSWER_QUESTION));
                        } else if (entry.getValue().equals(QuestionType.FILL_UP.toString())) {
                            query.addCriteria(Criteria.where("questionType").is(QuesStructType.FILL_BLANK_QUESTION));
                        } else if (entry.getValue().equals(QuestionType.TRUE_OR_FALSE.toString())) {
                            query.addCriteria(Criteria.where("questionType").is(QuesStructType.BOOL_ANSWER_QUESTION));
                        } else {
                            throw new StatusException("Q-", "题型格式不对！");
                        }
                    }
                } else if (entry.getKey().equals("difficulty")) {
                    Pattern p = Pattern.compile(entry.getValue());
                    String key = "properties." + entry.getKey();
                    query.addCriteria(Criteria.where(key).regex(p));
                } else {
                    String la = entry.getValue();
                    if (!StringUtils.isBlank(la)) {
                        la = la.replaceAll(",", "*");
                        Pattern pattern = Pattern.compile(la, Pattern.CASE_INSENSITIVE);
                        String key = "properties." + entry.getKey();
                        query.addCriteria(Criteria.where(key).regex(pattern));
                    }
                }
            }
        }
        long count = this.mongoTemplate.count(query, Question.class);
        query.limit(pageSize);
        query.skip((curPage - 1L) * pageSize);
        List<Question> questionList = this.mongoTemplate.find(query, Question.class);
        List<DefaultQuestion> defaultQuestions = buildDefaultQuestions(questionList);
        Page<DefaultQuestion> questions = new PageImpl<DefaultQuestion>(defaultQuestions, PageRequest.of(curPage - 1, pageSize), count);
        return questions;
    }

    private List<DefaultQuestion> buildDefaultQuestions(List<Question> questionList) {
        List<DefaultQuestion> defaultQuestions = new ArrayList<>();
        if (questionList != null && questionList.size() > 0) {
            for (Question question : questionList) {
                DefaultQuestion defaultQuestion = getDefaultQuestion(question);
                defaultQuestions.add(defaultQuestion);
            }
            return defaultQuestions;
        }
        return defaultQuestions;
    }

    private DefaultQuestion getDefaultQuestion(Question question) {
        if (question != null) {
            DefaultQuestionStructure defaultQuestionStructure = new DefaultQuestionStructure();
            //生成新的题单元集合
            List<DefaultQuestionUnit> questionUnitList = new ArrayList<>();
            if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                defaultQuestionStructure.setBody(question.getQuesBody());
                //获取套题下面所有子题
                List<Question> subQuesList = question.getSubQuestions();
                if (subQuesList != null && subQuesList.size() > 0) {
                    for (int i = 0; i < subQuesList.size(); i++) {
                        Question subQuestion = subQuesList.get(i);
                        DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(subQuestion);
                        questionUnitList.add(defaultQuestionUnit);
                    }
                }
            } else {
                DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(question);
                questionUnitList.add(defaultQuestionUnit);
            }
            defaultQuestionStructure.setQuestionUnitList(questionUnitList);
            DefaultQuestion defaultQuestion = new DefaultQuestion();
            defaultQuestion.setId(question.getId());
            defaultQuestion.setIsolated(true);
            defaultQuestion.setRootOrgId(Long.valueOf(question.getOrgId()));
            defaultQuestion.setProperties(question.getProperties());
            defaultQuestion.setMasterVersion(defaultQuestionStructure);
            return defaultQuestion;
        }
        return null;
    }

    /**
     * 构建试题单元
     *
     * @param question
     * @return
     */
    private DefaultQuestionUnit buildQuestionUnit(Question question) {
        DefaultQuestionUnit defaultQuestionUnit = new DefaultQuestionUnit();
        defaultQuestionUnit.setBody(question.getQuesBody());
        defaultQuestionUnit.setQuestionType(getByOldType(question.getQuestionType()));
        defaultQuestionUnit.setAnswerType(question.getAnswerType());//作答类型
        //如果是单选或者多选，添加选项和答案转换
        if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
            List<DefaultQuestionOption> defaultQuestionOptions = new ArrayList<>();
            List<QuesOption> quesOptions = question.getQuesOptions();
            if (quesOptions != null && quesOptions.size() > 0) {
                for (int i = 0; i < quesOptions.size(); i++) {
                    QuesOption quesOption = quesOptions.get(i);
                    DefaultQuestionOption defaultQuestionOption = new DefaultQuestionOption();
                    defaultQuestionOption.setBody(quesOption.getOptionBody());
                    defaultQuestionOptions.add(defaultQuestionOption);
                }
            }
            defaultQuestionUnit.setQuestionOptionList(defaultQuestionOptions);
            defaultQuestionUnit.setRightAnswer(getSelectQuestionAnswer(quesOptions));
        } else {
            defaultQuestionUnit.setRightAnswer(getAnswer(question));
        }
        return defaultQuestionUnit;
    }

    /**
     * 题型转换方法
     *
     * @param quesStructType
     * @return
     */
    private QuestionType getByOldType(QuesStructType quesStructType) {
        if (quesStructType == QuesStructType.BOOL_ANSWER_QUESTION) {
            return QuestionType.TRUE_OR_FALSE;
        }
        if (quesStructType == QuesStructType.FILL_BLANK_QUESTION) {
            return QuestionType.FILL_UP;
        }
        if (quesStructType == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
            return QuestionType.MULTIPLE_CHOICE;
        }
        if (quesStructType == QuesStructType.SINGLE_ANSWER_QUESTION) {
            return QuestionType.SINGLE_CHOICE;
        }
        if (quesStructType == QuesStructType.TEXT_ANSWER_QUESTION) {
            return QuestionType.ESSAY;
        }
        return null;
    }


    /**
     * 设置单选题和多选题  答案
     *
     * @param quesOptions
     * @return
     */
    private String[] getSelectQuestionAnswer(List<QuesOption> quesOptions) {
        String[] rightAnswer = null;
        List<String> list = new ArrayList<>();
        if (quesOptions != null && quesOptions.size() > 0) {
            for (int i = 0; i < quesOptions.size(); i++) {
                QuesOption quesOption = quesOptions.get(i);
                if (quesOption.getIsCorrect() == 1) {
                    list.add(String.valueOf(i));
                }
            }
            rightAnswer = list.toArray(new String[list.size()]);
            return rightAnswer;
        }
        return rightAnswer;
    }

    /**
     * 设置试题答案
     *
     * @param question
     * @return
     */
    private String[] getAnswer(Question question) {
        String[] rightAnswer = null;
        //判断题答案
        if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
            if (question.getQuesAnswer().equals("正确")) {
                rightAnswer = new String[1];
                rightAnswer[0] = "true";
                return rightAnswer;
            }
            if (question.getQuesAnswer().equals("错误")) {
                rightAnswer = new String[1];
                rightAnswer[0] = "false";
                return rightAnswer;
            }
        }
        //填空题答案
        if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
            rightAnswer = question.getQuesAnswer().split("##");
            return rightAnswer;
        }
        rightAnswer = new String[1];
        rightAnswer[0] = question.getQuesAnswer();
        return rightAnswer;
    }

    @Override
    public String saveList(List<DefaultQuestion> defaultQuestions) {
        if (defaultQuestions != null && defaultQuestions.size() > 0) {
            List<Question> questions = new ArrayList<>();
            for (DefaultQuestion defaultQuestion : defaultQuestions) {
                Question question = new Question();
                if (!StringUtils.isBlank(defaultQuestion.getId())) {
                    question.setId(defaultQuestion.getId());
                }
                //初始化默认课程
                Course course = new Course();
                course.setId("k12");
                course.setCode("k12");
                course.setName("k12");
                course.setLevel("ALL");
                course.setOrgId(defaultQuestion.getRootOrgId().toString());
                course.setCreateTime(CommonUtils.getCurDateTime());
                course.setEnable("true");
                question.setCourse(course);
                question.setOrgId(defaultQuestion.getRootOrgId().toString());
                question.setCreateTime(CommonUtils.getCurDateTime());
                question.setDifficulty("中");
                question.setDifficultyDegree(0.5);
                question.setIsolated(true);
                question.setPublicity(true);
                question.setProperties(defaultQuestion.getProperties());
                DefaultQuestionStructure defaultQuestionStructure = (DefaultQuestionStructure) defaultQuestion.getMasterVersion();
                //判断试题单元对象
                List<DefaultQuestionUnit> questionUnitList = defaultQuestionStructure.getQuestionUnitList();
                if (questionUnitList == null || questionUnitList.size() < 1) {
                    throw new StatusException("Q-012033", "试题单元对象为空");
                }
                if (questionUnitList.size() == 1) {
                    DefaultQuestionUnit defaultQuestionUnit = questionUnitList.get(0);
                    //判断试题题型
                    if (defaultQuestionUnit.getQuestionType() == null) {
                        throw new StatusException("Q-012039", "试题单元中题型为空");
                    }
                    //设置题干
                    question.setQuesBody(defaultQuestionUnit.getBody());
                    QuesStructType type = buildQuesType(defaultQuestionUnit.getQuestionType());
                    if (type == null) {
                        throw new StatusException("Q-012043", "试题单元中题型值不对");
                    }
                    //设置题型
                    question.setQuestionType(type);
                    //如果是选择题，判断选项
                    if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
                        List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
                        if (questionOptionList == null || questionOptionList.size() < 1) {
                            throw new StatusException("Q-012049", "试题单元中选项为空");
                        }
                        //设置选项
                        List<QuesOption> quesOptions = buildOptions(questionOptionList, defaultQuestionUnit.getRightAnswer());
                        question.setQuesOptions(quesOptions);
                    }
                    //设置答案
                    question.setQuesAnswer(buildAnswer(defaultQuestionUnit));
                } else {
                    //套题
                    //设置题干
                    question.setQuesBody(defaultQuestionStructure.getBody());
                    question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
                    //生成子题
                    List<Question> subList = new ArrayList<>();
                    for (DefaultQuestionUnit defaultQuestionUnit : questionUnitList) {
                        Question subQues = new Question();
                        subQues.setId(IdUtils.uuid());
                        subQues.setDifficulty("中");
                        subQues.setDifficultyDegree(0.5);
                        subQues.setPublicity(true);
                        //判断试题题型
                        if (defaultQuestionUnit.getQuestionType() == null) {
                            throw new StatusException("Q-012039", "试题单元中题型为空");
                        }
                        //设置题干
                        subQues.setQuesBody(defaultQuestionUnit.getBody());
                        QuesStructType type = buildQuesType(defaultQuestionUnit.getQuestionType());
                        if (type == null) {
                            throw new StatusException("Q-012043", "试题单元中题型值不对");
                        }
                        //设置题型
                        subQues.setQuestionType(type);
                        //如果是选择题，判断选项
                        if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
                            List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
                            if (questionOptionList == null || questionOptionList.size() < 1) {
                                throw new StatusException("Q-012049", "试题单元中选项为空");
                            }
                            //设置选项
                            List<QuesOption> quesOptions = buildOptions(questionOptionList, defaultQuestionUnit.getRightAnswer());
                            subQues.setQuesOptions(quesOptions);
                        }
                        //设置答案
                        subQues.setQuesAnswer(buildAnswer(defaultQuestionUnit));
                        subList.add(subQues);
                    }
                    question.setSubQuestions(subList);
                }
                questions.add(question);
            }
            quesRepo.saveAll(questions);
            return "success";
        }
        return "failure";
    }

    @Override
    public List<DefaultQuestion> findQuestions(Set<String> questionIds) {
        List<Question> questions = quesRepo.findByIdIn(questionIds);
        if (questions == null || questions.size() < 1) {
            throw new StatusException("Q-012515", "questions is null");
        }
        List<DefaultQuestion> defaultQuestions = new ArrayList<>();
        for (Question question : questions) {
            DefaultQuestion defaultQuestion = getDefaultQuestion(question);
            defaultQuestions.add(defaultQuestion);
        }
        return defaultQuestions;
    }
}
