package com.qxgmat.service.inline;

import com.github.pagehelper.Page;
import com.nuliji.tools.AbstractService;
import com.nuliji.tools.PageResult;
import com.nuliji.tools.Transform;
import com.nuliji.tools.exception.ParameterException;
import com.nuliji.tools.exception.SystemException;
import com.nuliji.tools.mybatis.Example;
import com.qxgmat.data.constants.enums.status.DirectionStatus;
import com.qxgmat.data.dao.QuestionNoMapper;
import com.qxgmat.data.dao.entity.Question;
import com.qxgmat.data.dao.entity.QuestionNo;
import com.qxgmat.data.dao.entity.UserQuestion;
import com.qxgmat.data.inline.PaperStat;
import com.qxgmat.data.relation.QuestionNoRelationMapper;
import com.qxgmat.data.relation.entity.QuestionNoRelation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 QuestionNoService extends AbstractService {
    private static final Logger logger = LoggerFactory.getLogger(QuestionNoService.class);
    protected boolean SOFT_FLAG = true;

    @Resource
    private QuestionNoMapper questionNoMapper;

    @Resource
    private QuestionNoRelationMapper questionNoRelationMapper;

    @Resource
    private QuestionService questionService;

//    private List<String> stops = new ArrayList<String>(){{
//       add(".");
//       add(",");
//       add("!");
//       add(":");
//       add(";");
//       add("?");
//    }};

    /**
     * 根据题干搜索相似题目: 相似度80%
     * @param page
     * @param size
     * @param stem
     * @return
     */
    public PageResult<QuestionNoRelation> searchStem(int page, int size, String stem){
//        String[] stems = stem.replaceAll("\\.?,?!?:?;?\\??", "").split(" ");

        Page<QuestionNo> p = page(()->{
            questionNoRelationMapper.searchStem(stem);
        }, page, size);

        Collection ids = Transform.getIds(p, QuestionNo.class, "id");

        // 获取详细数据
        List<QuestionNo> list = select(ids);
        return new PageResult<>(relation(list), p.getTotal());
    }

    /**
     * 根据题目编号搜索相似题目
     * @param page
     * @param size
     * @param no
     * @param module
     * @return
     */
    public PageResult<QuestionNoRelation> searchNo(int page, int size, String no, String module){
        Example example = new Example(QuestionNo.class);
        example.and(
                example.createCriteria()
                        .andLike("no", no)
        );
        if (module != null)
            example.and(
                    example.createCriteria()
                            .andEqualTo("module", module)
            );
        example.orderBy("id").asc();
        Page<QuestionNo> p = page(()->select(questionNoMapper, example), page, size);
        return new PageResult<>(relation(p), p.getTotal());
    }

    /**
     * 根据题目标号列表获取题目
     * @param nos
     * @param module
     * @return
     */
    public List<QuestionNoRelation> listWithRelationByNos(String[] nos, String module){
        if (nos.length == 0) return new ArrayList<>();
        Example example = new Example(QuestionNo.class);
        example.and(
                example.createCriteria()
                        .andIn("no", Arrays.stream(nos).collect(Collectors.toList()))
        );
        if (module != null)
            example.and(
                    example.createCriteria()
                            .andEqualTo("module", module)
            );
        List<QuestionNo> p = select(questionNoMapper, example);
        return relation(p);
    }

    /**
     * 根据题目获取关联的题目编号
     * @param questionId
     * @return
     */
    public List<QuestionNo> listByQuestion(Number questionId){
        Example example = new Example(QuestionNo.class);
        example.and(
                example.createCriteria()
                        .andEqualTo("questionId", questionId)
        );
        return select(questionNoMapper, example);
    }

    /**
     * 根据题目编号id列表获取关联题目
     * @param ids
     * @return
     */
    public List<QuestionNoRelation> listWithRelationByIds(Number[] ids){
        List<QuestionNo> p = select(questionNoMapper, ids);
        return relation(p);
    }

    /**
     * 根据题目编号id获取关联题目
     * @param id
     * @return
     */
    public QuestionNoRelation getWithRelation(Number id){
        QuestionNo questionNo = get(id);
        return relation(questionNo);
    }

    /**
     * 绑定no和question
     * @param ids
     * @param questionId
     * @return
     */
    public Boolean bindQuestion(Integer[] ids, Integer questionId){
        if (ids.length == 0) return false;
        Example example = new Example(QuestionNo.class);
        example.and(
                example.createCriteria()
                        .andIn("id", Arrays.stream(ids).collect(Collectors.toList()))
        );
        int result = update(questionNoMapper, example, QuestionNo.builder().questionId(questionId).deleteTime(null).build());
        return result > 0;
    }

    /**
     * 根据题目获取总试卷统计信息
     * @param questionNoList
     * @return
     */
    public PaperStat statPaper(List<QuestionNo> questionNoList){
        PaperStat stat = new PaperStat();
        Integer totalTime = 0;
        Integer totalNumber = 0;
        Integer totalCorrect = 0;
        for(QuestionNo questionNo : questionNoList){
            totalTime += questionNo.getTotalTime();
            totalNumber += questionNo.getTotalNumber();
            totalCorrect += questionNo.getTotalCorrect();
        }
        stat.setTotalCorrect(totalCorrect);
        stat.setTotalNumber(totalNumber);
        stat.setTotalTime(totalTime);
        return stat;
    }

    /**
     * 累加做题记录到questionNo
     * @param question
     */
    public void accumulation(UserQuestion question){
        questionNoRelationMapper.accumulation(question.getQuestionNoId(), 1, question.getTime(), question.getIsCorrect());
    }

    /**
     * 根据试卷分组获取统计信息
     * @param questionNoIdsMap
     * @return
     */
    public Map<Integer, PaperStat> statPaperMap(Map<Integer, Integer[]> questionNoIdsMap){
        Map<Integer, PaperStat> relationMap = new HashMap<>();
        List<Integer> ids = new ArrayList<>();
        for(Integer[] questionNoIds : questionNoIdsMap.values()){
            ids.addAll(Arrays.stream(questionNoIds).collect(Collectors.toList()));
        }
        List<QuestionNo> questionNoList = select(ids);
        Map questionNoMap = Transform.getMap(questionNoList, QuestionNo.class, "id");
        List<QuestionNo> l = new ArrayList<>();
        for(Integer k: questionNoIdsMap.keySet()){
            l.clear();
            for (Integer questionNoId : questionNoIdsMap.get(k)){
                l.add((QuestionNo)questionNoMap.get(questionNoId));
            }
            relationMap.put(k, statPaper(l));
        }

        return relationMap;
    }

    private List<QuestionNoRelation> relation(List<QuestionNo> p){
        List<QuestionNoRelation> relationList = Transform.convert(p, QuestionNoRelation.class);

        Collection questionIds = Transform.getIds(p, QuestionNo.class, "questionId");
        List<Question> questions = questionService.select(questionIds);
        Transform.combine(relationList, questions, QuestionNoRelation.class, "questionId", "question", Question.class, "id");
        return relationList;
    }

    private QuestionNoRelation relation(QuestionNo p){
        QuestionNoRelation relation = Transform.convert(p, QuestionNoRelation.class);

        Question question = questionService.get(p.getQuestionId());
        relation.setQuestion(question);
        return relation;
    }

    /**
     * 通过题目编号获取
     * @param no
     * @return
     */
    public QuestionNo getByNo(String no, String module){
        return one(questionNoMapper, QuestionNo.builder().no(no).module(module).build());
    }

    @Transactional
    public QuestionNo add(QuestionNo question){
        QuestionNo in = getByNo(question.getNo(), question.getModule());
        if (in != null){
            return in;
        }
        int result = insert(questionNoMapper, question);
        question = one(questionNoMapper, question.getId());
        if(question == null){
            throw new SystemException("题目添加失败");
        }
        return question;
    }

    @Deprecated
    public QuestionNo edit(QuestionNo question){
        QuestionNo in = one(questionNoMapper, question.getId());
        if(in == null){
            throw new ParameterException("题目不存在");
        }
        int result = update(questionNoMapper, question);
        return question;
    }

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

    public QuestionNo get(Number id){
        QuestionNo in = one(questionNoMapper, id);

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

    public Page<QuestionNo> select(int page, int pageSize){
        return select(questionNoMapper, page, pageSize);
    }

    public List<QuestionNo> select(Collection ids){
        return select(questionNoMapper, ids);
    }

}
