package jnpf.cultivate.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import jnpf.cultivate.mapper.FtbCultivateQuestionMapper;
import jnpf.cultivate.service.*;
import jnpf.cultivate.utils.AsyncExamQuestionUtils;
import jnpf.model.cultivate.po.FtbCultivateAssessmentPoints;
import jnpf.model.cultivate.po.paper.FtbCultivateTestPaper;
import jnpf.model.cultivate.po.paper.FtbCultivateTestPaperQuestion;
import jnpf.model.cultivate.po.question.FtbCultivateQuestion;
import jnpf.model.cultivate.po.question.FtbCultivateQuestionOption;
import jnpf.model.cultivate.po.question.FtbCultivateQuestionPoints;
import jnpf.model.cultivate.req.questionbank.AddQuestionReq;
import jnpf.model.cultivate.req.questionbank.EditQuestionReq;
import jnpf.model.cultivate.req.questionbank.QueryQuestionReq;
import jnpf.model.cultivate.req.questionbank.QuestionOptionReq;
import jnpf.model.cultivate.resp.*;
import jnpf.model.enums.CourseEnums;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
public class FtbCultivateQuestionServiceImpl extends ServiceImpl<FtbCultivateQuestionMapper, FtbCultivateQuestion> implements FtbCultivateQuestionService {

    /**
     * 题目选项服务
     */
    @Autowired
    private FtbCultivateQuestionOptionService questionOptionService;

    /**
     * 题目考点关系
     */
    @Autowired
    private FtbCultivateQuestionPointsService questionPointsService;

    /**
     * 考点服务
     */
    @Autowired
    private FtbCultivateAssessmentPointsService assessmentPointsService;

    /**
     * 试卷题目关联
     */
    @Autowired
    private FtbCultivateTestPaperQuestionService paperQuestionService;
    /**
     * 试卷
     */
    @Autowired
    private FtbCultivateTestPaperService testPaperService;

    /**
     * 考试
     */
    @Autowired
    private FtbCultivateExamService examService;

    @Autowired
    private AsyncExamQuestionUtils asyncExamQuestionUtils;

    /**
     * 分页列出题库中题目列表【根据题库ID】
     *
     * @param req
     * @return
     */
    @Override
    public PageInfo<QuestionVo> getPageList(QueryQuestionReq req) {
        if(StringUtils.isNotEmpty(req.getKeyword())){
            req.setKeyword(StringUtils.trim(req.getKeyword()));
        }
        //构建分页
        Page<FtbCultivateQuestion> page = new Page(req.getCurrentPage(), req.getPageSize());
        //构建查询
        LambdaQueryWrapper<FtbCultivateQuestion> wrapper = new LambdaQueryWrapper<FtbCultivateQuestion>()
                .eq(FtbCultivateQuestion::getClassifyId, req.getQuestionBankId())
                .like(!StringUtils.isEmpty(req.getKeyword()), FtbCultivateQuestion::getContent, req.getKeyword())
                .eq(req.getType() != null, FtbCultivateQuestion::getType, req.getType())
                .eq(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode())
                .orderByDesc(FtbCultivateQuestion::getLastModifyTime);
        Page<FtbCultivateQuestion> queryPage = baseMapper.selectPage(page, wrapper);
        List<FtbCultivateQuestion> records = queryPage.getRecords();
        //转换查询对象
        List<QuestionVo> list = new ArrayList<>();
        records.forEach(entity -> {
            QuestionVo vo = BeanUtil.copyProperties(entity, QuestionVo.class);
            list.add(vo);
        });
        //构建分页返回数据
        PageInfo<QuestionVo> pageInfo = new PageInfo<>();
        pageInfo.setList(list);
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setTotal((int) queryPage.getTotal());
        return pageInfo;
    }

    public QuestionVo getQuestionAndOption(String questionId) {
        //1、检测题目信息
        FtbCultivateQuestion question = baseMapper.selectById(questionId);
        if (null == question) {
            throw new RuntimeException("题目不存在");
        }
        if (question.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
            throw new RuntimeException("题目已经被删除，不能操作");
        }
        //2、题目po转vo
        QuestionVo vo = BeanUtil.copyProperties(question, QuestionVo.class);
        //3、查询题目的选项信息
        if (!CourseEnums.QuestionType.INPUT.getCode().equals(question.getType())
                && !CourseEnums.QuestionType.COMBINE.getCode().equals(question.getType())) {
            List<FtbCultivateQuestionOption> questionOptionList = queryOptionListForQuestionId(questionId);
            if (CollectionUtil.isNotEmpty(questionOptionList)) {
                vo.setQuestionOptionVoList(BeanUtil.copyToList(questionOptionList, QuestionOptionVo.class));
            }
        }
        return vo;
    }

    @Override
    public QuestionVo getInfo(String questionId) {
        //1、查询题目和选项
        QuestionVo QuestionVo = getQuestionAndOption(questionId);
        //2、查询题目的考点信息
        List<AssessmentPointsVo> assessmentPointsVoList = queryQuestionAssessmentPoints(questionId);
        QuestionVo.setAssessmentPointsVoList(assessmentPointsVoList);
        return QuestionVo;
    }

    /**
     * 查询题目ID查询考点列表
     *
     * @param questionId 题目ID
     * @return
     */

    private List<AssessmentPointsVo> queryQuestionAssessmentPoints(String questionId) {

        //1、查询题目关联的考点
        QueryWrapper<FtbCultivateQuestionPoints> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbCultivateQuestionPoints::getQuestionId, questionId);
        List<FtbCultivateQuestionPoints> questionPointsList = questionPointsService.list(wrapper);
        if (CollectionUtil.isEmpty(questionPointsList)) {
            return CollectionUtil.newArrayList();
        }
        //2、根据考点Ids查询考点列表
        List<String> assessmentPointsIds = questionPointsList.stream().map(FtbCultivateQuestionPoints::getPointsId).collect(Collectors.toList());
        QueryWrapper<FtbCultivateAssessmentPoints> assessmentPointsQueryWrapper = new QueryWrapper<>();
        assessmentPointsQueryWrapper.lambda()
                .in(FtbCultivateAssessmentPoints::getId, assessmentPointsIds)
                .eq(FtbCultivateAssessmentPoints::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateAssessmentPoints> assessmentPointsList = assessmentPointsService.list(assessmentPointsQueryWrapper);
        if (CollectionUtil.isEmpty(assessmentPointsList)) {
            return CollectionUtil.newArrayList();
        }
        return BeanUtil.copyToList(assessmentPointsList, AssessmentPointsVo.class);
    }

    /**
     * 新增题目
     *
     * @param questionBankId 题库ID
     * @param req            题目信息
     */
    @Override
    @Transactional
    public void insertData(String questionBankId, AddQuestionReq req) {
        //1、添加题目信息
        FtbCultivateQuestion question = new FtbCultivateQuestion();
        question.setClassifyId(questionBankId);
        question.setType(req.getType());
        question.setDifficulty(req.getDifficulty());
        question.setContent(req.getContent());
        question.setAnalysis(req.getAnalysis());
        question.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
        question.setCreatorTime(new Date());
        question.setLastModifyTime(new Date());
        baseMapper.insert(question);
        //2、添加题目选项信息
        if (CourseEnums.QuestionType.INPUT.getCode().equals(question.getType()) || CourseEnums.QuestionType.COMBINE.getCode().equals(question.getType())) {
            return;
        }
        List<QuestionOptionReq> optionList = req.getOptionList();
        if (CollectionUtil.isEmpty(optionList)) {
            return;
        }
        List<FtbCultivateQuestionOption> questionOptionList = new ArrayList<>();
        for (QuestionOptionReq option : optionList) {
            FtbCultivateQuestionOption questionOption = new FtbCultivateQuestionOption();
            questionOption.setQuestionId(question.getId());
            questionOption.setContent(option.getContent());
            questionOption.setImage(option.getImage());
            questionOption.setDescription(option.getDescription());
            questionOption.setSortCode(option.getSortCode());
            questionOption.setIsRightOption(option.getIsRightOption());
            questionOption.setRightAnswer(option.getRightAnswer());
            questionOption.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
            questionOptionList.add(questionOption);
        }
        questionOptionService.saveBatch(questionOptionList);
        log.info(questionOptionList.toString());

        //3、写入正确答案
        writeRightAnswer(question, questionOptionList);
        //4、写入关联的考点信息
        String pointIds = req.getQuestionPointIds();
        if (StringUtils.isEmpty(pointIds)) {
            return;
        }
        List<String> pointLists = Arrays.asList(pointIds.split(","));
        if (CollectionUtil.isEmpty(pointLists)) {
            return;
        }
        saveQuestionPoint(question.getId(), pointLists);
    }

    /**
     * 写入正确答案
     *
     * @param question 题目信息
     * @param questionOptionList 题目选项信息
     */
    private void writeRightAnswer(FtbCultivateQuestion question, List<FtbCultivateQuestionOption> questionOptionList) {
        List<String> rightAnswerList = new ArrayList<>();
        if (CourseEnums.QuestionType.SINGLE.getCode().equals(question.getType())
                || CourseEnums.QuestionType.MULTI.getCode().equals(question.getType())
                || CourseEnums.QuestionType.JUDGE.getCode().equals(question.getType())
                || CourseEnums.QuestionType.FILL.getCode().equals(question.getType())
                || CourseEnums.QuestionType.ONE_OR_MULTI.getCode().equals(question.getType())
        ) {
            if (CollectionUtil.isEmpty(questionOptionList)) {
                throw new RuntimeException("单选、多选、判断题、填空题、不定项选择题的选项不能为空");
            }
            if (questionOptionList.size() > 8) {
                throw new RuntimeException("单选、多选、判断题、填空题、不定项选择题的选项数量不能大于8个");
            }
        }
        for (FtbCultivateQuestionOption questionOption : questionOptionList) {
            if (CourseEnums.QuestionType.SINGLE.getCode().equals(question.getType())
                    || CourseEnums.QuestionType.MULTI.getCode().equals(question.getType())
                    || CourseEnums.QuestionType.JUDGE.getCode().equals(question.getType())
                    || CourseEnums.QuestionType.ONE_OR_MULTI.getCode().equals(question.getType())
            ) {
                if (CourseEnums.IsRightAnswer.YES.getCode().equals(questionOption.getIsRightOption())) {
                    rightAnswerList.add(questionOption.getId());
                }
            } else if (CourseEnums.QuestionType.FILL.getCode().equals(question.getType())) {
                rightAnswerList.add(questionOption.getId());
            }
        }
        FtbCultivateQuestion updateQuestion = new FtbCultivateQuestion();
        updateQuestion.setAnswer(rightAnswerList.stream().collect(Collectors.joining(",")));
        updateQuestion.setId(question.getId());
        baseMapper.updateById(updateQuestion);
    }

    /**
     * 批量写入题目关联的考点信息
     *
     * @param questionId 题目ID
     * @param pointLists 考点列表
     */
    private void saveQuestionPoint(String questionId, List<String> pointLists) {
        List<FtbCultivateQuestionPoints> list = new ArrayList<>();
        for (String pointId : pointLists) {
            FtbCultivateQuestionPoints points = new FtbCultivateQuestionPoints();
            points.setQuestionId(questionId);
            points.setPointsId(pointId);
            list.add(points);
        }
        questionPointsService.saveBatch(list);
    }


    /**
     * 修改题目
     * 1、检测题目信息是否存咋存并修改题目信息
     * 2、处理题目选项信息
     * 3、处理题目的正确答案
     * 4、处理题目关联的考点信息
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateData(EditQuestionReq req) {

        //1、检测题目信息
        FtbCultivateQuestion question = baseMapper.selectById(req.getId());
        if (null == question) {
            throw new RuntimeException("题目不存在");
        }
        if (question.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
            throw new RuntimeException("题目已经被删除，不能操作");
        }
        //接口传入选项
        List<QuestionOptionReq> reqOptionList = req.getOptionList();
        //1、修改题目信息
        question.setType(req.getType());
        question.setDifficulty(req.getDifficulty());
        question.setContent(req.getContent());
        question.setAnalysis(req.getAnalysis());
        baseMapper.updateById(question);
        //2、查询题目选项
        List<FtbCultivateQuestionOption> questionOptionList = queryOptionListForQuestionId(req.getId());
        //3、获取已经存在
        List<String> exiestList = new ArrayList<>();//已经存在的选项
        for (FtbCultivateQuestionOption questionOption : questionOptionList) {
            exiestList.add(questionOption.getId());
        }
        List<FtbCultivateQuestionOption> allDealOptionList = new ArrayList<>();
        //4、处理题目选项信息
        if (CollectionUtil.isEmpty(reqOptionList) && CollectionUtil.isNotEmpty(exiestList)) {
            deleteQuestionOption(req.getId(), exiestList);
        } else {
            //处理新增和编辑题目选项
            List<QuestionOptionReq> addList = new ArrayList<>();//新增列表
            List<QuestionOptionReq> editList = new ArrayList<>();//编辑列表
            Set<String> reqSet = new HashSet<>();//提交的有选项ID的集合
            for (QuestionOptionReq optionReq : reqOptionList) {
                if (StringUtils.isEmpty(optionReq.getId())) {
                    addList.add(optionReq);
                } else {
                    editList.add(optionReq);
                    reqSet.add(optionReq.getId());
                }
            }

            if (CollectionUtil.isNotEmpty(addList)) {
                allDealOptionList.addAll(addQustionOption(req.getId(), addList));
            }
            if (CollectionUtil.isNotEmpty(editList)) {
                allDealOptionList.addAll(updateQustionOption(editList));
            }
            //处理删除选项
            List<String> removeList = new ArrayList<>();
            for (String optionId : exiestList) {
                if (!reqSet.contains(optionId)) {
                    removeList.add(optionId);
                }
            }
            if (CollectionUtil.isNotEmpty(removeList)) {
                deleteQuestionOption(req.getId(), removeList);
            }
        }

        //5、给题目写入正确答案
        writeRightAnswer(question, allDealOptionList);
        //6、写入关联的考点信息
        //6.1删除已经存在的考点
        removeQuestionPointRelation(question.getId());
        //6.2新增题目关联考点信息
        String pointIds = req.getQuestionPointIds();
        if (StringUtils.isEmpty(pointIds)) {
            return;
        }
        List<String> pointLists = Arrays.asList(pointIds.split(","));
        if (CollectionUtil.isEmpty(pointLists)) {
            return;
        }
        saveQuestionPoint(question.getId(), pointLists);
    }

    /**
     * 清除题目关联考点信息
     *
     * @param questionId 题目ID
     */
    private void removeQuestionPointRelation(String questionId) {
        QueryWrapper<FtbCultivateQuestionPoints> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbCultivateQuestionPoints::getQuestionId, questionId);
        questionPointsService.remove(wrapper);
    }

    /**
     * 给题目中增加选项
     *
     * @param questionId    题目ID
     * @param optionReqList 选项
     */
    private List<FtbCultivateQuestionOption> addQustionOption(String questionId, List<QuestionOptionReq> optionReqList) {
        List<FtbCultivateQuestionOption> optionList = new ArrayList<>();
        for (QuestionOptionReq optionReq : optionReqList) {
            FtbCultivateQuestionOption questionOption = new FtbCultivateQuestionOption();
            questionOption.setQuestionId(questionId);
            questionOption.setContent(optionReq.getContent());
            questionOption.setImage(optionReq.getImage());
            questionOption.setDescription(optionReq.getDescription());
            questionOption.setSortCode(optionReq.getSortCode());
            questionOption.setIsRightOption(optionReq.getIsRightOption());
            questionOption.setRightAnswer(optionReq.getRightAnswer());
            questionOption.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
            optionList.add(questionOption);
        }
        questionOptionService.saveBatch(optionList);
        return optionList;
    }

    /**
     * 修改题目选项
     *
     * @param optionReqList
     */
    private List<FtbCultivateQuestionOption> updateQustionOption(List<QuestionOptionReq> optionReqList) {
        List<FtbCultivateQuestionOption> optionList = new ArrayList<>();
        for (QuestionOptionReq optionReq : optionReqList) {
            FtbCultivateQuestionOption questionOption = new FtbCultivateQuestionOption();
            questionOption.setId(optionReq.getId());
            questionOption.setContent(optionReq.getContent());
            questionOption.setImage(optionReq.getImage());
            questionOption.setDescription(optionReq.getDescription());
            questionOption.setSortCode(optionReq.getSortCode());
            questionOption.setIsRightOption(optionReq.getIsRightOption());
            questionOption.setRightAnswer(optionReq.getRightAnswer());
            questionOption.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
            optionList.add(questionOption);
        }
        questionOptionService.saveOrUpdateBatch(optionList);
        return optionList;
    }

    /**
     * 删除问题选项
     *
     * @param questionId   问题ID
     * @param optionIdList 选项ID列表
     */
    private void deleteQuestionOption(String questionId, List<String> optionIdList) {
        UpdateWrapper<FtbCultivateQuestionOption> wrapper = new UpdateWrapper<>();
        wrapper.lambda().set(FtbCultivateQuestionOption::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
                .eq(FtbCultivateQuestionOption::getQuestionId, questionId)
                .in(FtbCultivateQuestionOption::getId, optionIdList);
        questionOptionService.update(wrapper);
    }

    /**
     * 根据题目ID查 题目选项列表
     *
     * @param questionId 题目ID
     */
    private List<FtbCultivateQuestionOption> queryOptionListForQuestionId(String questionId) {
        QueryWrapper<FtbCultivateQuestionOption> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbCultivateQuestionOption::getQuestionId, questionId)
                .eq(FtbCultivateQuestionOption::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode())
                .orderByAsc(FtbCultivateQuestionOption::getSortCode);
        return questionOptionService.list(wrapper);
    }

    /**
     * 删除题库
     *
     * @param id 题库ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteData(String id) {
        //1、查询题目信息
        FtbCultivateQuestion question = baseMapper.selectById(id);
        if (null == question) {
            throw new RuntimeException("题目不存在");
        }
        if (question.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
            return;
        }
        //2、删除题目
        question.setEnabledMark(CourseEnums.EnabledMarkType.INVALID.getCode());
        baseMapper.updateById(question);
//        UpdateWrapper<FtbCultivateQuestionOption> updateWrapper = new UpdateWrapper<>();
//        updateWrapper.lambda()
//                .set(FtbCultivateQuestionOption::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
//                .eq(FtbCultivateQuestionOption::getQuestionId, question.getId());
//        questionOptionService.update(updateWrapper);
        //删除考点
        removeQuestionPointRelation(question.getId());
        //删除题目后 异步处理试卷和考试
        asyncPaperQuestion(List.of(question.getId()));
    }

    /**
     * 批量删除题目
     * @param questionIds 题目id集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDel(List<String> questionIds) {
        List<String> needDelQuestionIds = new ArrayList<>();
        for (String questionId : questionIds) {
            FtbCultivateQuestion question = baseMapper.selectById(questionId);
            if (null == question) {
                continue;
            }
            if (question.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
                continue;
            }
            needDelQuestionIds.add(questionId);
        }
        if (CollectionUtil.isEmpty(needDelQuestionIds)) {
            return;
        }
        UpdateWrapper<FtbCultivateQuestion> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
                .in(FtbCultivateQuestion::getId, needDelQuestionIds);
        update(updateWrapper);
        asyncPaperQuestion(needDelQuestionIds);
    }

    /**
     * 根据题库ID查询题目列表
     * @param questionBankId 题库ID
     * @return
     */
    @Override
    public List<UserQuestionVo> queryAllQuestionByQuestionBankId(String questionBankId) {
        LambdaQueryWrapper<FtbCultivateQuestion> wrapper = new LambdaQueryWrapper<FtbCultivateQuestion>()
                .eq(FtbCultivateQuestion::getClassifyId, questionBankId)
                .eq(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode())
                .orderByDesc(FtbCultivateQuestion::getLastModifyTime);
        List<FtbCultivateQuestion> list = baseMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(list)) {
            throw new RuntimeException("题库中暂无题目");
        }

        List<UserQuestionVo> userQuestionVoList = BeanUtil.copyToList(list, UserQuestionVo.class);
        List<String> questionIds = list.stream().map(FtbCultivateQuestion::getId).collect(Collectors.toList());
        List<FtbCultivateQuestionOption> questionOptionList = questionOptionService.queryOptionListByQuestionIds(questionIds);
        Map<String, List<FtbCultivateQuestionOption>> questionOptionMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(questionOptionList)) {
            questionOptionMap = questionOptionList.stream().collect(Collectors.groupingBy(FtbCultivateQuestionOption::getQuestionId));
        }
        //填充题目选项
        for (UserQuestionVo userQuestionVo : userQuestionVoList) {
            List<FtbCultivateQuestionOption> questionOptionVoList = questionOptionMap.get(userQuestionVo.getId());
            if (CollectionUtil.isNotEmpty(questionOptionVoList)) {
                userQuestionVo.setQuestionOptionVoList(BeanUtil.copyToList(questionOptionVoList, QuestionOptionVo.class));
            }
        }
        return userQuestionVoList;
    }
    /**
     * 给题库中导入题目
     * @param questionBankId 题目ID
     * @param allQuestionList 题目数据
     * @return
     */
    @Override
    @Transactional
    public ImportQuestionResultVo realImportData(String questionBankId, List<ExcelImportQuestionResultReq> allQuestionList) {

        List<AddQuestionReq> failList = new ArrayList<>();
        List<AddQuestionReq> successList = new ArrayList<>();
        allQuestionList.forEach(req -> {
            AddQuestionReq addQuestionReq = BeanUtil.copyProperties(req, AddQuestionReq.class);
            try {
                insertData(questionBankId, addQuestionReq);
                successList.add(addQuestionReq);
            } catch (Exception e) {
                log.error("导入题目失败", e);
                failList.add(addQuestionReq);
            }
        });
        return ImportQuestionResultVo.builder().successList(successList).failList(failList).build();
    }
    /**
     * 根据题库id统计各题库的题目数量
     * @param ids 题库id集合
     * @return
     */
    @Override
    public List<QuestionCountDto> countForClassifyId(List<String> ids) {
        return baseMapper.countForClassifyId(ids);
    }

    /**
     * 异步处理题目删除 1、给试卷大更新标记  2、给考试打跟新标记  3、更新试卷的题目数量和分数
     * @param questionIds 题目ids
     */
    private void asyncPaperQuestion(List<String> questionIds) {
        String tenantId = asyncExamQuestionUtils.getTenantId();
        Map<String, String> headers = asyncExamQuestionUtils.getHeadersForLogin();
        // asyncExamQuestionUtils.asyncPaperQuestion(tenantId, questionIds, headers);
        asyncExamQuestionUtils.asyncExamQuestion(tenantId, questionIds, headers);
    }

    /**
     * 检测题库是否可以被删除
     * 1、查询题库的所有题目信息
     * 2、循环检测题目是否可以被删除
     *
     * @param questionBankId 题库ID
     * @return
     */
    @Override
    public CanDeleteMsg checkQuestionBankCanDelete(String questionBankId) {
        //1、查询题库所有题目
        QueryWrapper<FtbCultivateQuestion> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbCultivateQuestion::getClassifyId, questionBankId)
                .eq(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateQuestion> questionList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(questionList)) {
            return new CanDeleteMsg(true, "题库中没有题目");
        }
        //2、循环检测每个题目是否可以被删除
        for (FtbCultivateQuestion question : questionList) {
            QuestionCanDeleteMsg canDeleteMsg = checkQuestionCanDelete(question.getId());
            //不能删除直接返回了
            if (!canDeleteMsg.getCanDelete()) {
                return new CanDeleteMsg(false, canDeleteMsg.getMsg(), canDeleteMsg.getData());
            }
        }
        return new CanDeleteMsg(true, "可以删除");
    }

    /**
     * 检测题目是否可以被删除
     * <p>
     * 【判断一】判断该题目有无纳入试卷
     * 判断结果1：有-继续判断二
     * 判断结果2：无-删除该题目
     * 【判断二】判断纳入该题目的试卷有无纳入考试
     * 判断结果2：无-二次确认后删除，提示语：该题目纳入的试卷（***试卷名称**ID：***），直接删除题目不影响历史已有试卷，若需从考卷中剔除该题目须要重建试卷
     *
     * @param questionId 题目ID
     * @return
     */
    public QuestionCanDeleteMsg checkQuestionCanDelete(String questionId) {

        //1、查询题目信息
        FtbCultivateQuestion question = baseMapper.selectById(questionId);
        if (null == question) {

            return new QuestionCanDeleteMsg(false, "题目不存在");
        }
        if (question.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
            return new QuestionCanDeleteMsg(false, "题目已经被删除");
        }
        //查询题目收录的试卷列表
        QueryWrapper<FtbCultivateTestPaperQuestion> testPaperQuestionQueryWrapper = new QueryWrapper<>();
        testPaperQuestionQueryWrapper.lambda()
                .eq(FtbCultivateTestPaperQuestion::getQuestionId, questionId)
                .eq(FtbCultivateTestPaperQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateTestPaperQuestion> testPaperQuestionList = paperQuestionService.list(testPaperQuestionQueryWrapper);
        if (CollectionUtil.isEmpty(testPaperQuestionList)) {
            return new QuestionCanDeleteMsg(true, "无考试试卷收录该题目");
        }
        //查询题目收率的试卷列表
        List<String> paperIdList = testPaperQuestionList.stream().map(FtbCultivateTestPaperQuestion::getPaperId).collect(Collectors.toList());
        QueryWrapper<FtbCultivateTestPaper> testPaperQueryWrapper = new QueryWrapper<>();
        testPaperQueryWrapper.lambda()
                .in(FtbCultivateTestPaper::getId, paperIdList)
                .eq(FtbCultivateTestPaper::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateTestPaper> testPaperList = testPaperService.list(testPaperQueryWrapper);
        if (CollectionUtil.isEmpty(testPaperList)) {
            return new QuestionCanDeleteMsg(true, "无考试试卷收录该题目");
        }

        List<RecordPaperAndExam> voList = new ArrayList<>();
        for (FtbCultivateTestPaper paper : testPaperList) {
            RecordPaperAndExam record = new RecordPaperAndExam();
            record.setQuestionId(question.getId());
            record.setQuestionName(question.getContent());
            record.setPaperPrimaryId(paper.getId());
            record.setPaperId(paper.getPaperId());
            record.setPaperName(paper.getName());
            List<ExamVo> examList = examService.queryExamListByPaperId(paper.getId());
            record.setExamList(examList.stream().map(ExamVo::getExamName).collect(Collectors.toList()));
            voList.add(record);
        }
        return new QuestionCanDeleteMsg(false, "有考试试卷收录该题目", voList);
    }

    /**
     * 批量检测题目是否可以删除
     * @param questionIds 题目id集合
     * @return
     */
    @Override
    public QuestionCanDeleteMsg batchCheckCanDel(List<String> questionIds) {
        List<RecordPaperAndExam> voList = new ArrayList<>();
        for (String questionId : questionIds) {
            FtbCultivateQuestion question = baseMapper.selectById(questionId);
            if (null == question) {
                continue;
            }
            if (question.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
                continue;
            }
            //查询题目收录的试卷列表
            QueryWrapper<FtbCultivateTestPaperQuestion> testPaperQuestionQueryWrapper = new QueryWrapper<>();
            testPaperQuestionQueryWrapper.lambda()
                    .eq(FtbCultivateTestPaperQuestion::getQuestionId, questionId)
                    .eq(FtbCultivateTestPaperQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
            List<FtbCultivateTestPaperQuestion> testPaperQuestionList = paperQuestionService.list(testPaperQuestionQueryWrapper);
            if (CollectionUtil.isEmpty(testPaperQuestionList)) {
                continue;
            }
            //查询题目收率的试卷列表
            List<String> paperIdList = testPaperQuestionList.stream().map(FtbCultivateTestPaperQuestion::getPaperId).collect(Collectors.toList());
            QueryWrapper<FtbCultivateTestPaper> testPaperQueryWrapper = new QueryWrapper<>();
            testPaperQueryWrapper.lambda()
                    .in(FtbCultivateTestPaper::getId, paperIdList)
                    .eq(FtbCultivateTestPaper::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
            List<FtbCultivateTestPaper> testPaperList = testPaperService.list(testPaperQueryWrapper);
            if (CollectionUtil.isEmpty(testPaperList)) {
                continue;
            }

            for (FtbCultivateTestPaper paper : testPaperList) {
                RecordPaperAndExam record = new RecordPaperAndExam();
                record.setQuestionId(question.getId());
                record.setQuestionName(question.getContent());
                record.setPaperPrimaryId(paper.getId());
                record.setPaperId(paper.getPaperId());
                record.setPaperName(paper.getName());
                List<ExamVo> examList = examService.queryExamListByPaperId(paper.getId());
                record.setExamList(examList.stream().map(ExamVo::getExamName).collect(Collectors.toList()));
                voList.add(record);
            }
        }
        if (CollectionUtil.isEmpty(voList)) {
            return new QuestionCanDeleteMsg(true, "无考试试卷关联题目");
        } else {
            return new QuestionCanDeleteMsg(false, "有考试试卷关联题目", voList);
        }
    }


    /**
     * 导入题目
     *
     * @param questionBankId  题库ID
     * @param allQuestionList 题目列表
     */
    @Override
    @Transactional
    public ImportQuestionResultVo importData(String questionBankId, List<AddQuestionReq> allQuestionList) {
        if (CollectionUtil.isEmpty(allQuestionList)) {
            return ImportQuestionResultVo.builder().build();
        }
        List<AddQuestionReq> failList = new ArrayList<>();
        List<AddQuestionReq> successList = new ArrayList<>();
        allQuestionList.forEach(req -> {
            try {
                if (StringUtils.isEmpty(req.getContent())) {
                    failList.add(req);
                } else {
                    insertData(questionBankId, req);
                    successList.add(req);
                }
            } catch (Exception e) {
                log.error("导入题目失败", e);
                failList.add(req);
            }
        });
        return ImportQuestionResultVo.builder().successList(successList).failList(failList).build();
    }

    /**
     * 查询重复题目
     *
     * @param req
     * @return
     */
    @Override
    public PageInfo<QuestionVo> queryRepeatQuestion(QueryQuestionReq req) {
        PageInfo<QuestionVo> pageInfo = new PageInfo<>();

        //1、查询重复的题目名称
        List<FtbCultivateQuestion> repeatList = baseMapper.queryRepeatQuestion(req.getQuestionBankId());
        if (CollectionUtil.isEmpty(repeatList)) {
            pageInfo.setList(new ArrayList<>());
            pageInfo.setPageSize(req.getPageSize());
            pageInfo.setPageNum(req.getCurrentPage());
            pageInfo.setTotal(0);
            return pageInfo;
        }
        //转换 题目名称列表
        List<String> nameList = repeatList.stream().map(FtbCultivateQuestion::getContent).collect(Collectors.toList());

        Page<FtbCultivateQuestion> page = new Page(req.getCurrentPage(), req.getPageSize());
        //构建查询
        LambdaQueryWrapper<FtbCultivateQuestion> wrapper = new LambdaQueryWrapper<FtbCultivateQuestion>()
                .eq(FtbCultivateQuestion::getClassifyId, req.getQuestionBankId())
                .in(FtbCultivateQuestion::getContent, nameList)
                .eq(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode())
                .orderByDesc(FtbCultivateQuestion::getLastModifyTime);
        Page<FtbCultivateQuestion> queryPage = baseMapper.selectPage(page, wrapper);
        List<FtbCultivateQuestion> records = queryPage.getRecords();
        //转换查询对象
        List<QuestionVo> list = new ArrayList<>();
        records.forEach(entity -> {
            QuestionVo vo = BeanUtil.copyProperties(entity, QuestionVo.class);
            list.add(vo);
        });
        //构建分页返回数据
        pageInfo.setList(list);
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setTotal((int) queryPage.getTotal());
        return pageInfo;
    }
}
