package com.ynfy.buss.practice.userpractice.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ynfy.buss.exam.exam.dto.ExamAnswerDTO;
import com.ynfy.buss.exam.exam.service.IExamService;
import com.ynfy.buss.exam.question.entity.Question;
import com.ynfy.buss.exam.question.enums.QuestionType;
import com.ynfy.buss.exam.question.service.IQuestionService;
import com.ynfy.buss.practice.userpractice.entity.UserPractice;
import com.ynfy.buss.practice.userpractice.entity.dto.PracticeQuestionDTO;
import com.ynfy.buss.practice.userpractice.entity.dto.UserPracticeDTO;
import com.ynfy.buss.practice.userpractice.entity.dto.UserPracticeResultDTO;
import com.ynfy.buss.practice.userpractice.enums.PracticeMode;
import com.ynfy.buss.practice.userpractice.mapper.UserPracticeMapper;
import com.ynfy.buss.practice.userpractice.service.IUserPracticeService;
import com.ynfy.buss.practice.userpracticequestion.entity.UserPracticeQuestion;
import com.ynfy.buss.practice.userpracticequestion.service.IUserPracticeQuestionService;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserPracticeServiceImpl extends ServiceImpl<UserPracticeMapper, UserPractice> implements IUserPracticeService {

    @Autowired
    private IUserPracticeQuestionService userPracticeQuestionService;

    @Autowired
    private IQuestionService questionService;

    @Autowired
    private IExamService examService;

    @Autowired
    private UserPracticeMapper userPracticeMapper;

    /**
     * 获取用户最近的练习
     *
     * @return
     */
    @Override
    public List<UserPractice> getRecentPractice(String repositoryId) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        Page<UserPractice> page = new Page<UserPractice>(1, 5);

        LambdaQueryWrapper<UserPractice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPractice::getUserId, user.getId()).eq(UserPractice::getRepositoryId, repositoryId)
                .orderByDesc(UserPractice::getCommitTime);
        IPage<UserPractice> pageList = page(page, wrapper);
        return pageList.getRecords();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String submitPractice(UserPracticeDTO dto) {
        if (CollectionUtils.isEmpty(dto.getQuestionList())) {
            throw new JeecgBootException("练习题目为空");
        }
        UserPractice userPractice = new UserPractice();
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        userPractice.setUserId(user.getId());
        userPractice.setType(1);
        userPractice.setRepositoryId(dto.getRepositoryId());
        userPractice.setMode(dto.getMode());
        userPractice.setQuestionType(dto.getQuestionType());
        StringBuilder name = new StringBuilder();
        name.append(PracticeMode.getByCode(dto.getMode()).getValue());
        if (!Objects.isNull(dto.getQuestionType())) {
            name.append("-").append(QuestionType.getByCode(dto.getQuestionType()).getValue());
        }
        userPractice.setPracticeName(name.toString());
        userPractice.setCommitTime(new Date());
        List<PracticeQuestionDTO> questionList = dto.getQuestionList();
        Long count = questionList.stream().filter(q -> !Objects.isNull(q.getIsRight()) && q.getIsRight()).count();
        userPractice.setRightNumber(count.intValue());
        userPractice.setTotalNumber(questionList.size());
        //正确率
        userPractice.setAccuracy(NumberUtil.div(NumberUtil.mul(count.intValue(), 100), questionList.size(), 2));
        save(userPractice);
        String userPracticeId = userPractice.getId();
        List<ExamAnswerDTO> answerList = dto.getAnswers();
        int sort = 1;
        List<UserPracticeQuestion> userPracticeQuestionList = new ArrayList<>();
        for (PracticeQuestionDTO item : questionList) {
            UserPracticeQuestion upq = new UserPracticeQuestion();
            upq.setUserPracticeId(userPracticeId);
            upq.setQuestionId(item.getId());
            upq.setQuestionType(item.getType());
            upq.setAnswered(item.getAnswered());
            upq.setIsRight(item.getIsRight());
            upq.setSort(sort);
            ExamAnswerDTO answerDTO = answerList.stream().filter(a -> a.getIndex().equals(item.getQuestionIndex())).findFirst().orElse(null);
            if (!Objects.isNull(answerDTO)) {
                String[] answers = answerDTO.getAnswers();
                if (!item.getType().equals(QuestionType.BLANK.getCode())) { //单选，多选，判断
                    if (!Objects.isNull(answers) && answers.length > 0) {
                        upq.setAnswer(String.join(",", answers));
                    }
                } else {//填空题
                    upq.setAnswer(item.getBlankAnswer());
                }
            }
            userPracticeQuestionList.add(upq);
            sort++;
        }
        if (!CollectionUtils.isEmpty(userPracticeQuestionList)) {
            userPracticeQuestionService.saveBatch(userPracticeQuestionList);
        }
        return userPracticeId;
    }

    /**
     * 获取练习结果
     *
     * @return
     */
    @Override
    public UserPracticeResultDTO getPracticeResult(String id) {
        UserPracticeResultDTO dto = new UserPracticeResultDTO();
        UserPractice userPractice = getById(id);
        dto.setUserPractice(userPractice);
        List<UserPracticeQuestion> userPracticeQuestionList = userPracticeQuestionService.listByUserPracticeId(id);
        List<String> questionIdList = userPracticeQuestionList.stream().map(UserPracticeQuestion::getQuestionId).collect(Collectors.toList());
        List<Question> questionList = questionService.listByIds(questionIdList);
        questionService.setQuestionAnswer(questionList);
        Map<String, Question> questionMap = questionList.stream().collect(Collectors.toMap(Question::getId, a -> a, (k1, k2) -> k1));
        for (UserPracticeQuestion userPracticeQuestion : userPracticeQuestionList) {
            if (!Objects.isNull(questionMap.get(userPracticeQuestion.getQuestionId()))) {
                Question question = questionMap.get(userPracticeQuestion.getQuestionId());
                //渲染填空题的题干，填充进答案
                if (QuestionType.BLANK.getCode().equals(userPracticeQuestion.getQuestionType())) {
                    examService.renderBlank(question, userPracticeQuestion.getAnswer());
                }
                userPracticeQuestion.setQuestion(question);
                userPracticeQuestion.setQuestionTypeName(QuestionType.getByCode(userPracticeQuestion.getQuestionType()).getValue());
            }
            //生成单选，单选，填空答案tag
            userPracticeQuestion.setAnswer(examService.generateQuestionAnswerTag(userPracticeQuestion.getAnswer(), userPracticeQuestion.getQuestion()));
        }
        dto.setQuestionList(userPracticeQuestionList);
        return dto;
    }

    @Override
    public IPage<UserPractice> selectPageList(IPage<UserPractice> page, UserPractice userPractice){
        return userPracticeMapper.selectPageList(page, userPractice);
    }
}
