package com.qxgmat.service;

import com.github.pagehelper.Page;
import com.nuliji.tools.AbstractService;
import com.nuliji.tools.exception.ParameterException;
import com.nuliji.tools.exception.SystemException;
import com.nuliji.tools.mybatis.Example;
import com.qxgmat.data.constants.enums.logic.SentenceLogic;
import com.qxgmat.data.constants.enums.logic.TextbookLogic;
import com.qxgmat.data.dao.TextbookPaperMapper;
import com.qxgmat.data.dao.entity.*;
import com.qxgmat.data.relation.entity.SentenceQuestionRelation;
import com.qxgmat.data.relation.entity.TextbookQuestionRelation;
import com.qxgmat.service.inline.QuestionService;
import com.qxgmat.service.inline.TextbookQuestionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TextbookPaperService extends AbstractService {
    private static final Logger logger = LoggerFactory.getLogger(TextbookPaperService.class);

    final static String formatSet = "FIND_IN_SET('%d', question_no_ids)";
    final static String formatTitle = "";

    @Value("${paper.textbookLength}")
    private Integer paperLength;

    @Resource
    private TextbookPaperMapper textbookPaperMapper;

    @Resource
    private QuestionService questionService;

    @Resource
    private TextbookQuestionService textbookQuestionService;

    public void initUserPaper(UserPaper userPaper, Integer id){
        TextbookPaper paper = get(id);
        userPaper.setTitle(paper.getTitle());
        userPaper.setQuestionNoIds(paper.getQuestionNoIds());
        userPaper.setTime(0);
    }
    /**
     * 添加长难句题目：加入题库，关联题目，并关联长难句paper
     * @param relation
     * @return
     */
    @Transactional
    public TextbookQuestion addQuestion(TextbookQuestionRelation relation){
        Question question = relation.getQuestion();
        question = questionService.add(question);
        // 绑定关系
        relation.setQuestionId(question.getId());

        TextbookQuestion textbookQuestion =  textbookQuestionService.add(relation);

        // 绑定关系
        if (question.getQuestionType().equals(TextbookLogic.DS.key)){
            addQuestionToPaper(textbookQuestion, TextbookLogic.DS);
            addQuestionToPaper(textbookQuestion, TextbookLogic.DS_PS);
        }else if (question.getQuestionType().equals(TextbookLogic.PS.key)){
            addQuestionToPaper(textbookQuestion, TextbookLogic.PS);
            addQuestionToPaper(textbookQuestion, TextbookLogic.DS_PS);
        }

        textbookQuestionService.edit(textbookQuestion);
        return textbookQuestion;
    }

    /**
     * 更新机经题目：更新题库
     * @param relation
     * @return
     */
    @Transactional
    public TextbookQuestion editQuestion(TextbookQuestionRelation relation){
        Question question = relation.getQuestion();
        question = questionService.edit(question);

        TextbookQuestion textbookQuestion = textbookQuestionService.edit(relation);

        return textbookQuestion;
    }

    /**
     * 获取可用的试卷列表：单个分组逻辑
     * @param logic
     * @return
     */
    public List<TextbookPaper> listByLogic(TextbookLogic logic){
        Example example = new Example(SentencePaper.class);
        example.and(
                example.createCriteria()
                        .andEqualTo("logic", logic.key)
                        .andEqualTo("status", 1)
        );
        example.orderBy("no").asc();
        return select(textbookPaperMapper, example);
    }

    private void addQuestionToPaper(TextbookQuestion question, TextbookLogic logic){
        // 获取最后一个paper
        TextbookPaper paper = getLastBySet(logic, question.getSetId());
        Integer no = 0;
        if (paper == null || paper.getQuestionNumber().equals(paperLength)){
            if (paper != null){
                no = paper.getNo();
            }
            Calendar calendar = Calendar.getInstance();
            paper = add(TextbookPaper.builder()
                    .logic(SentenceLogic.NO.key)
                    .title(String.format(formatTitle, no))
                    .year(calendar.get(Calendar.YEAR))
                    .setId(question.getSetId())
                    .no(no+1)
                    .questionNumber(1)
                    .status(1)
                    .questionNoIds(new Integer[]{question.getId()}).build()
            );
        }else{
            // 加入
            List<Integer> list = Arrays.stream(paper.getQuestionNoIds()).collect(Collectors.toList());
            list.add(question.getId());
            paper.setQuestionNumber(paper.getQuestionNumber() + 1);
            paper.setQuestionNoIds(list.toArray(new Integer[0]));
            paper = edit(paper);
        }
    }

    private void removeQuestionFromPaper(TextbookQuestion question){
        List<TextbookPaper> paperList = listByQuestion(question);
        for(TextbookPaper paper : paperList){
            paper.setQuestionNumber(paper.getQuestionNumber() - 1);
            List<Integer> list = Arrays.stream(paper.getQuestionNoIds()).collect(Collectors.toList());
            list.remove(question.getId());
            paper.setQuestionNoIds(list.toArray(new Integer[0]));
            edit(paper);
        }
    }

    private List<TextbookPaper> listByQuestion(TextbookQuestion question){
        Example example = new Example(SentencePaper.class);
        example.and(
                example.createCriteria()
                        .andCondition(String.format(formatSet, question.getId()))
        );
        return select(textbookPaperMapper, example);
    }

    private TextbookPaper getLastBySet(TextbookLogic logic, Integer setId){
        Example example = new Example(TextbookPaper.class);
        example.and(
                example.createCriteria()
                        .andEqualTo("logic", logic.key)
                        .andEqualTo("setId", setId)
        );
        example.orderBy("createTime").desc();
        return one(textbookPaperMapper, example);
    }

    public TextbookPaper add(TextbookPaper paper){
        int result = insert(textbookPaperMapper, paper);
        paper = one(textbookPaperMapper, paper.getId());
        if(paper == null){
            throw new SystemException("题目添加失败");
        }
        return paper;
    }

    public TextbookPaper edit(TextbookPaper paper){
        TextbookPaper in = one(textbookPaperMapper, paper.getId());
        if(in == null){
            throw new ParameterException("题目不存在");
        }
        int result = update(textbookPaperMapper, paper);
        return paper;
    }

    public boolean delete(Number id){
        TextbookPaper in = one(textbookPaperMapper, id);
        if(in == null){
            throw new ParameterException("题目不存在");
        }
        int result = delete(textbookPaperMapper, id);
        return result > 0;
    }

    public TextbookPaper get(Number id){
        TextbookPaper in = one(textbookPaperMapper, id);

        if(in == null){
            throw new ParameterException("题目不存在");
        }
        return in;
    }

    public Page<TextbookPaper> select(int page, int pageSize){
        return select(textbookPaperMapper, page, pageSize);
    }


    public Page<TextbookPaper> select(int page, int pageSize, String keyword){
        Example example = new Example(TextbookPaper.class);
        example.and(
                example.createCriteria()
                        .andEqualTo("status", 1)
        );
        if (keyword != null)
            example.and(
                    example.createCriteria()
                            .andLike("title", keyword)
            );
        return select(textbookPaperMapper, example, page, pageSize);
    }

    public List<TextbookPaper> select(Collection ids){
        return select(textbookPaperMapper, ids);
    }

}
