package jnpf.cultivate.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.FtbCultivateTestPaperMapper;
import jnpf.cultivate.service.*;
import jnpf.cultivate.utils.UserApiV2Util;
import jnpf.model.cultivate.po.exam.FtbCultivateExam;
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.FtbCultivateQuestionBank;
import jnpf.model.cultivate.po.question.FtbCultivateQuestionOption;
import jnpf.model.cultivate.req.paper.PaperConfigReq;
import jnpf.model.cultivate.req.paper.QueryPaperReq;
import jnpf.model.cultivate.req.paper.SavePaperReq;
import jnpf.model.cultivate.resp.*;
import jnpf.model.enums.CourseEnums;
import jnpf.model.enums.ExamUpdateStatus;
import jnpf.model.enums.SelfrowingEnum;
import jnpf.permission.vo.v2.position.PositionVO;
import jnpf.util.SelfGrowthUtil;
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.function.Function;
import java.util.stream.Collectors;

@Service
public class FtbCultivateTestPaperServiceImpl extends ServiceImpl<FtbCultivateTestPaperMapper, FtbCultivateTestPaper> implements FtbCultivateTestPaperService {

    /**
     * 题目选项服务
     */
    @Autowired
    private FtbCultivateQuestionOptionService questionOptionService;
    /**
     * 试卷和题目关联 服务
     */
    @Autowired
    private FtbCultivateTestPaperQuestionService paperQuestionService;

    /**
     * 题目服务
     */
    @Autowired
    private FtbCultivateQuestionService questionService;

    /**
     * 题库服务
     */
    @Autowired
    private FtbCultivateQuestionBankService questionBankService;

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

    @Autowired
    private UserApiV2Util userApiV2Util;


    /**
     * 分页查询试卷列表
     *
     * @param req
     * @return
     */
    @Override
    public PageInfo<PaperListVo> getPageList(QueryPaperReq req) {
        //构建分页
        if (StringUtils.isNotEmpty(req.getKeyword())) {
            req.setKeyword(StringUtils.trim(req.getKeyword()));
        }

        Page<FtbCultivateTestPaper> page = Page.of(req.getCurrentPage(), req.getPageSize());
        //构建查询
        LambdaQueryWrapper<FtbCultivateTestPaper> wrapper = new LambdaQueryWrapper<FtbCultivateTestPaper>()
                .like(!StringUtils.isEmpty(req.getKeyword()), FtbCultivateTestPaper::getName, req.getKeyword())
                .like(!StringUtils.isEmpty(req.getQuestionBankId()), FtbCultivateTestPaper::getRelationQuestionBankId, req.getQuestionBankId())
                .eq(req.getStatus() != null, FtbCultivateTestPaper::getStatus, req.getStatus())
                .eq(req.getIsDraft() != null, FtbCultivateTestPaper::getIsDraft, req.getIsDraft())
                .eq(FtbCultivateTestPaper::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode())
                .orderByDesc(FtbCultivateTestPaper::getCreatorTime);
        if (req.getNeedUpdate() != null) {
            if (req.getNeedUpdate().equals(ExamUpdateStatus.NO_UPDATE.getCode()) || req.getNeedUpdate().equals(ExamUpdateStatus.NEED_UPDATE.getCode())) {
                wrapper.eq(FtbCultivateTestPaper::getNeedUpdate, req.getNeedUpdate());
            }
        }
        Page<FtbCultivateTestPaper> queryPage = baseMapper.selectPage(page, wrapper);
        List<FtbCultivateTestPaper> records = queryPage.getRecords();
        //转换查询对象
        List<PaperListVo> list = new ArrayList<>();
        records.forEach(entity -> {
            PaperListVo vo = new PaperListVo();
            vo.setId(entity.getId());
            vo.setName(entity.getName());
            vo.setPaperId(entity.getPaperId());
            vo.setType(entity.getType());
            vo.setPaperType(entity.getPaperType());
            vo.setQuestionNumber(entity.getQuestionNumber());
            vo.setTotalScore(entity.getTotalScore());
            vo.setLastModifyTime(entity.getLastModifyTime());
            vo.setStatus(entity.getStatus());
            vo.setIsDraft(entity.getIsDraft());
            vo.setNeedUpdate(entity.getNeedUpdate());
            list.add(vo);
        });
        //构建分页返回数据
        PageInfo<PaperListVo> pageInfo = new PageInfo<>();
        pageInfo.setList(list);
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setTotal((int) queryPage.getTotal());
        return pageInfo;
    }

    /**
     * 获取试卷详情
     *
     * @param paperId 试卷id
     * @return
     */
    @Override
    public PaperDetailVo getInfo(String paperId) {
        //1、查询和检测试卷是否存在
        FtbCultivateTestPaper paper = getById(paperId);
        if (paper == null) {
            throw new RuntimeException("试卷不存在");
        }
        if (CourseEnums.EnabledMarkType.INVALID.getCode().equals(paper.getEnabledMark())) {
            throw new RuntimeException("试卷已删除");
        }
        PaperDetailVo vo = convertPaperDetailVo(paper);

        //如果是随机回填一下题库的名称
        if (CourseEnums.PaperType.RANDOM.getCode().equals(vo.getType())) {
            PaperConfigReq paperConfig = vo.getPaperConfig();
            if (null != paperConfig) {
                Map<String, Map<String, PaperConfigReq.QuestionNum>> questionConfig = paperConfig.getQuestionConfig();
                if (MapUtil.isNotEmpty(questionConfig)) {
                    List<String> questionBankIdList = questionConfig.keySet().stream().map(String::valueOf).collect(Collectors.toList());
                    QueryWrapper<FtbCultivateQuestionBank> wrapper = new QueryWrapper<>();
                    wrapper.lambda()
                            .in(FtbCultivateQuestionBank::getId, questionBankIdList)
                            .eq(FtbCultivateQuestionBank::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
                    List<FtbCultivateQuestionBank> questionBankList = questionBankService.list(wrapper);
                    if (CollectionUtil.isNotEmpty(questionBankList)) {
                        List<QuestionBankVo> questionBankVoList = BeanUtil.copyToList(questionBankList, QuestionBankVo.class);
                        vo.setQuestionBankMap(questionBankVoList.stream().collect(Collectors.toMap(QuestionBankVo::getId, Function.identity())));
                    }
                }
            }
        }


        //查询试卷中的题目
        List<AppQuestionVo> questionList = queryQuestionList(paperId);
        if (CollectionUtil.isNotEmpty(questionList)) {
            vo.setQuestionList(questionList);
        }

        return vo;
    }

    /**
     * 转换试卷详情
     *
     * @param paper
     * @return
     */
    private PaperDetailVo convertPaperDetailVo(FtbCultivateTestPaper paper) {
        PaperDetailVo vo = new PaperDetailVo();
        vo.setId(paper.getId());
        vo.setName(paper.getName());
        vo.setPaperId(paper.getPaperId());
        vo.setTotalScore(paper.getTotalScore());
        vo.setPaperType(paper.getPaperType());
        vo.setType(paper.getType());
        if (StringUtils.isNotEmpty(paper.getPaperConfig())) {
            vo.setPaperConfig(JSONUtil.toBean(paper.getPaperConfig(), PaperConfigReq.class));
        }

        if (StringUtils.isNotEmpty(paper.getPostConfig())) {
            vo.setPostAndPositionList(JSONUtil.toList(paper.getPostConfig(), PostAndPosition.class));
        } else {
            vo.setPostAndPositionList(CollectionUtil.newArrayList());
        }
        vo.setPostId(paper.getPostId());
        vo.setQuestionNumber(paper.getQuestionNumber());
        vo.setTotalScore(paper.getTotalScore());
        vo.setIsDraft(paper.getIsDraft());
        vo.setNeedUpdate(paper.getNeedUpdate());
        return vo;
    }

    /**
     * 新增试卷
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertData(SavePaperReq req) {
        if (null == req.getIsDraft()) {
            req.setIsDraft(0);
        }
        //1、检测名称是否重复
        QueryWrapper<FtbCultivateTestPaper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbCultivateTestPaper::getName, req.getName())
                .eq(FtbCultivateTestPaper::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        Long count = baseMapper.selectCount(wrapper);
        if (null != count && count > 0) {
            throw new RuntimeException("试卷名称已经存在");
        }
        //2、添加试卷
        if (req.getPaperType() != 0 && req.getPaperType() != 1) {
            throw new RuntimeException("试卷类型错误");
        }
        FtbCultivateTestPaper paper = new FtbCultivateTestPaper();
        paper.setName(req.getName()); //试卷名称
        paper.setPaperType(req.getPaperType());//试卷类型
        paper.setType(req.getType()); //抽题类型
        paper.setPaperId(generatePaperId());
        paper.setStatus(CourseEnums.PaperStatus.ENABLED.getCode());
        paper.setCreatorTime(new Date());
        paper.setLastModifyTime(new Date());
        paper.setIsDraft(req.getIsDraft());
        if (req.getPaperConfig() != null) {
            paper.setPaperConfig(JSONUtil.toJsonStr(req.getPaperConfig()));
        }
        if (CollectionUtil.isNotEmpty(req.getPostAndPositionList())) {
            paper.setPostConfig(JSONUtil.toJsonStr(req.getPostAndPositionList()));
            List<String> postIdList = new ArrayList<>();
            for (PostAndPosition postAndPosition : req.getPostAndPositionList()) {
                postIdList.add(postAndPosition.getId());
            }
            paper.setPostId(postIdList.stream().collect(Collectors.joining(",")));
        }
        paper.setNeedUpdate(ExamUpdateStatus.NO_UPDATE.getCode());
        baseMapper.insert(paper);
        //2、批量添加试卷关联题目
        List<FtbCultivateTestPaperQuestion> paperQuestionList = new ArrayList<>();
        //2.1 新增固定题目
        CourseEnums.PaperType paperType = CourseEnums.PaperType.fromCode(req.getType());
        switch (paperType) {
            case FIX:
                //固定试卷
                List<SavePaperReq.PaperQuestionItem> questionItemList = req.getQuestionItemList();
                if (CollectionUtil.isNotEmpty(questionItemList)) {
                    //写入试卷题目关联表
                    paperQuestionList = saveFixPaperQuestionRelation(paper.getId(), questionItemList);
                }
                break;
            case RANDOM:
                //随机试卷
                PaperConfigReq paperConfig = req.getPaperConfig();
                if (null == paperConfig) {
                    throw new RuntimeException("试卷配置信息为空");
                }
                if (MapUtil.isEmpty(paperConfig.getQuestionConfig())) {
                    throw new RuntimeException("试卷题目配置信息为空");
                }
                if (MapUtil.isEmpty(paperConfig.getScoreConfig())) {
                    throw new RuntimeException("试卷分数配置信息为空");
                }
                paperQuestionList = saveRandomPaperQuestionRelation(paper.getId(), req.getPaperConfig());
                break;
        }

        //3、修改题卷总分和总题目数量，冗余试卷关联的题库
        paper.setQuestionNumber(paperQuestionList.size());
        int totleScore = paperQuestionList.stream()
                .mapToInt(FtbCultivateTestPaperQuestion::getScore)
                .sum();
        paper.setTotalScore(totleScore);
        paper.setLastModifyTime(new Date());
        Set<String> paperIdSet = paperQuestionList.stream()
                .map(FtbCultivateTestPaperQuestion::getBankId)
                .collect(Collectors.toSet());
        paper.setRelationQuestionBankId(paperIdSet.stream()
                .collect(Collectors.joining(",")));
        baseMapper.updateById(paper);
    }

    /**
     * 保存随机试卷的题目关联
     *
     * @param paperId     试卷id
     * @param paperConfig 随机选题配置信息
     * @return
     */
    private List<FtbCultivateTestPaperQuestion> saveRandomPaperQuestionRelation(String paperId, PaperConfigReq paperConfig) {

        //1、根据配置随机生成题目
        Map<String, Map<String, PaperConfigReq.QuestionNum>> questionConfig = paperConfig.getQuestionConfig();
        Map<String, PaperConfigReq.QuestionScore> scoreConfig = paperConfig.getScoreConfig();

        // 根据题库ID 查询题目列表
        List<String> questionBankIdList = new ArrayList<>(questionConfig.keySet());
        List<FtbCultivateQuestionBank> ftbCultivateQuestionBanks = questionBankService.listByIds(questionBankIdList);
        Map<String, FtbCultivateQuestionBank> ftbCultivateQuestionBanksMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(ftbCultivateQuestionBanks)) {
            ftbCultivateQuestionBanksMap = ftbCultivateQuestionBanks.stream().collect(Collectors.toMap(FtbCultivateQuestionBank::getId, ftbCultivateQuestionBank -> ftbCultivateQuestionBank));
        }
        Map<String, List<FtbCultivateQuestion>> questionMap = BatchQueryQuestionForQuestionBankIds(questionBankIdList);
        //检查所配置的题库中题目是否为0
        for (String outerKey : questionConfig.keySet()) {
            //outerKey题库ID
            Map<String, PaperConfigReq.QuestionNum> innerMap = questionConfig.get(outerKey);
            int needQuestionNum = 0;
            for (String innerKey : innerMap.keySet()) {
                //innerKey题型id
                PaperConfigReq.QuestionNum questionNum = innerMap.get(innerKey);
                needQuestionNum += questionNum.getSimpleNum() + questionNum.getGeneralNum() + questionNum.getHardNum();
            }
            if (needQuestionNum > 0) {
                List<FtbCultivateQuestion> questionList = questionMap.get(outerKey);
                if (CollectionUtil.isEmpty(questionList)) {
                    FtbCultivateQuestionBank ftbCultivateQuestionBank = ftbCultivateQuestionBanksMap.get(outerKey);
                    throw new RuntimeException("抽题失败:" + ftbCultivateQuestionBank.getBankContent() + "题目数量为0");
                }
                if (needQuestionNum > questionList.size()) {
                    FtbCultivateQuestionBank ftbCultivateQuestionBank = ftbCultivateQuestionBanksMap.get(outerKey);
                    throw new RuntimeException("抽题失败:" + ftbCultivateQuestionBank.getBankContent() + "题目数量不足");
                }

                Map<String, List<FtbCultivateQuestion>> questionTypeMap = questionList.stream()
                        .collect(Collectors.groupingBy(ftbCultivateQuestion -> String.valueOf(ftbCultivateQuestion.getType())));
                for (String innerKey : innerMap.keySet()) {
                    //innerKey题型id
                    int needQuestionType = 0;
                    PaperConfigReq.QuestionNum questionNum = innerMap.get(innerKey);
                    needQuestionType += questionNum.getSimpleNum() + questionNum.getGeneralNum() + questionNum.getHardNum();
                    if (needQuestionType > 0) {
                        List<FtbCultivateQuestion> questionListType = questionTypeMap.get(innerKey);
                        if (CollectionUtil.isEmpty(questionListType)) {
                            FtbCultivateQuestionBank ftbCultivateQuestionBank = ftbCultivateQuestionBanksMap.get(outerKey);
                            CourseEnums.QuestionType questionType = CourseEnums.QuestionType.fromCode(Integer.valueOf(innerKey));
                            throw new RuntimeException("抽题失败:" + ftbCultivateQuestionBank.getBankContent() + "题型:" + questionType.getDesc() + "题目数量不足");
                        }
                        if (needQuestionType > questionListType.size()) {
                            FtbCultivateQuestionBank ftbCultivateQuestionBank = ftbCultivateQuestionBanksMap.get(outerKey);
                            CourseEnums.QuestionType questionType = CourseEnums.QuestionType.fromCode(Integer.valueOf(innerKey));
                            throw new RuntimeException("抽题失败:" + ftbCultivateQuestionBank.getBankContent() + "题型:" + questionType.getDesc() + "题目数量不足");
                        }
                        Map<Integer, List<FtbCultivateQuestion>> difficultyMap = questionListType.stream().collect(Collectors.groupingBy(FtbCultivateQuestion::getDifficulty));
                        //1易，2中，3难
                        if (questionNum.getSimpleNum() > 0) {

                            List<FtbCultivateQuestion> questionListDiffulty1 = difficultyMap.get(1);
                            if (CollectionUtil.isEmpty(questionListDiffulty1) || questionNum.getSimpleNum() > questionListDiffulty1.size()) {
                                FtbCultivateQuestionBank ftbCultivateQuestionBank = ftbCultivateQuestionBanksMap.get(outerKey);
                                CourseEnums.QuestionType questionType = CourseEnums.QuestionType.fromCode(Integer.valueOf(innerKey));
                                throw new RuntimeException("抽题失败:" + ftbCultivateQuestionBank.getBankContent() + "题型:" + questionType.getDesc() + "难度为简单" + "题目数量不足");
                            }
                        }
                        if (questionNum.getGeneralNum() > 0) {

                            List<FtbCultivateQuestion> questionListDiffulty2 = difficultyMap.get(2);
                            if (CollectionUtil.isEmpty(questionListDiffulty2) || questionNum.getGeneralNum() > questionListDiffulty2.size()) {
                                FtbCultivateQuestionBank ftbCultivateQuestionBank = ftbCultivateQuestionBanksMap.get(outerKey);
                                CourseEnums.QuestionType questionType = CourseEnums.QuestionType.fromCode(Integer.valueOf(innerKey));
                                throw new RuntimeException("抽题失败:" + ftbCultivateQuestionBank.getBankContent() + "题型:" + questionType.getDesc() + "难度为中" + "题目数量不足");
                            }
                        }
                        if (questionNum.getHardNum() > 0) {
                            List<FtbCultivateQuestion> questionListDiffulty3 = difficultyMap.get(3);
                            if (CollectionUtil.isEmpty(questionListDiffulty3) || questionNum.getHardNum() > questionListDiffulty3.size()) {
                                FtbCultivateQuestionBank ftbCultivateQuestionBank = ftbCultivateQuestionBanksMap.get(outerKey);
                                CourseEnums.QuestionType questionType = CourseEnums.QuestionType.fromCode(Integer.valueOf(innerKey));
                                throw new RuntimeException("抽题失败:" + ftbCultivateQuestionBank.getBankContent() + "题型:" + questionType.getDesc() + "难度为复杂" + "题目数量不足");
                            }
                        }
                    }

                }

            }
        }


        List<FtbCultivateTestPaperQuestion> randomList = new ArrayList<>();
        questionMap.forEach((questionBankId, questionList) -> {
            //获取该题库题型对应的题目列表 Map
            Map<String, List<FtbCultivateQuestion>> questionTypeMap = questionList.stream()
                    .collect(Collectors.groupingBy(ftbCultivateQuestion -> String.valueOf(ftbCultivateQuestion.getType())));
            //获取该题库随机选题的配置
            Map<String, PaperConfigReq.QuestionNum> questionNumMap = questionConfig.get(questionBankId);
            //随机选题
            questionNumMap.forEach((questionType, questionNum) -> {
                //题型 的题目列表
                List<FtbCultivateQuestion> tempList = questionTypeMap.get(questionType);
                if (CollectionUtil.isEmpty(tempList)) {
                    return;
                }
                //题型难度列表
                Map<Integer, List<FtbCultivateQuestion>> difficultyMap = tempList.stream().collect(Collectors.groupingBy(FtbCultivateQuestion::getDifficulty));
                //简单
                Integer simpleNum = questionNum.getSimpleNum();
                List<FtbCultivateQuestion> simpleQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.EASY.getCode());
                //一般
                Integer generalNum = questionNum.getGeneralNum();
                List<FtbCultivateQuestion> generalQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.MIDDLE.getCode());
                //难
                Integer hardNum = questionNum.getHardNum();
                List<FtbCultivateQuestion> hardQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.MAX.getCode());
                randomList.addAll(randomGetQuestion(paperId, simpleQuestion, simpleNum, scoreConfig.get(questionType).getSimpleScore()));
                randomList.addAll(randomGetQuestion(paperId, generalQuestion, generalNum, scoreConfig.get(questionType).getGeneralScore()));
                randomList.addAll(randomGetQuestion(paperId, hardQuestion, hardNum, scoreConfig.get(questionType).getHardSore()));
            });
        });

        //2、批量保存
        paperQuestionService.saveBatch(randomList);
        return randomList;
    }

    /**
     * 随机获取题目
     *
     * @param paperId      试卷ID
     * @param questionList 题目列表
     * @param randomSize   抽取数量
     * @param score        分数
     * @return
     */
    private List<FtbCultivateTestPaperQuestion> randomGetQuestion(String paperId, List<FtbCultivateQuestion> questionList, Integer randomSize, Integer score) {
        if (CollectionUtil.isEmpty(questionList) || randomSize <= 0) {
            return new ArrayList<>();
        }
        List<FtbCultivateQuestion> random = new ArrayList<>();
        if (questionList.size() <= randomSize) {
            random = questionList;
        } else {
            // 打乱列表
            Collections.shuffle(questionList);
            // 抽取样本
            random = questionList.subList(0, randomSize);
        }

        return random.stream().map(question -> {
            FtbCultivateTestPaperQuestion paperQuestion = new FtbCultivateTestPaperQuestion();
            paperQuestion.setPaperId(paperId);
            paperQuestion.setQuestionId(question.getId());
            paperQuestion.setBankId(question.getClassifyId());
            paperQuestion.setScore(score);
            paperQuestion.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
            paperQuestion.setCreatorTime(new Date());
            return paperQuestion;
        }).collect(Collectors.toList());
    }

    /**
     * 批量查询题目
     *
     * @param questionBankIdList 题库ID列表
     * @return 题库id->题目列表
     */

    public Map<String, List<FtbCultivateQuestion>> BatchQueryQuestionForQuestionBankIds(List<String> questionBankIdList) {

        QueryWrapper<FtbCultivateQuestion> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .in(FtbCultivateQuestion::getClassifyId, questionBankIdList)
                .eq(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateQuestion> questionList = questionService.list(wrapper);
        if (CollectionUtil.isEmpty(questionList)) {
            return new HashMap<>();
        }
        return questionList.stream().collect(Collectors.groupingBy(FtbCultivateQuestion::getClassifyId));
    }


    /**
     * 保存固定试卷的题目关联
     *
     * @param paperId          试卷ID
     * @param questionItemList 题目配置列表，题目ID和分数
     * @return
     */
    private List<FtbCultivateTestPaperQuestion> saveFixPaperQuestionRelation(String paperId, List<SavePaperReq.PaperQuestionItem> questionItemList) {
        List<String> questionIdList = questionItemList.stream().map(SavePaperReq.PaperQuestionItem::getId).collect(Collectors.toList());
        //1、根据题目ID 查询题目信息
        LambdaQueryWrapper<FtbCultivateQuestion> wrapper = new LambdaQueryWrapper<FtbCultivateQuestion>()
                .in(FtbCultivateQuestion::getId, questionIdList)
                .eq(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateQuestion> questionList = questionService.list(wrapper);
        if (CollectionUtil.isEmpty(questionList)) {
            return CollectionUtil.newArrayList();
        }
        Map<String, FtbCultivateQuestion> questionMap = questionList.stream()
                .collect(Collectors.toMap(FtbCultivateQuestion::getId, question -> question));
        //2、批量写入
        List<FtbCultivateTestPaperQuestion> list = new ArrayList<>();
        for (SavePaperReq.PaperQuestionItem item : questionItemList) {
            FtbCultivateQuestion question = questionMap.get(item.getId());
            if (question == null) {
                continue;
            }
            FtbCultivateTestPaperQuestion testPaperQuestion = new FtbCultivateTestPaperQuestion();
            testPaperQuestion.setQuestionId(question.getId());
            testPaperQuestion.setPaperId(paperId);
            testPaperQuestion.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
            testPaperQuestion.setBankId(question.getClassifyId());
            testPaperQuestion.setScore(item.getScore());
            testPaperQuestion.setCreatorTime(new Date());
            list.add(testPaperQuestion);
        }
        paperQuestionService.saveBatch(list);
        return list;
    }

    /**
     * 生成业务试卷ID
     *
     * @return
     */
    private String generatePaperId() {
        return SelfGrowthUtil.provideACustomIDBasedOnTheModule(SelfrowingEnum.TEST_PAPER);
    }

    /**
     * 修改试卷
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateData(SavePaperReq req) {
        //兼容老的试卷
        if (null == req.getIsDraft()) {
            req.setIsDraft(0);
        }
        //1、检测名称是否重复  试卷是否存在
        QueryWrapper<FtbCultivateTestPaper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbCultivateTestPaper::getName, req.getName())
                .ne(FtbCultivateTestPaper::getId, req.getId())
                .eq(FtbCultivateTestPaper::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        Long count = baseMapper.selectCount(wrapper);
        if (null != count && count > 0) {
            throw new RuntimeException("试卷名称已经存在");
        }

        FtbCultivateTestPaper paper = getById(req.getId());
        if (null == paper) {
            throw new RuntimeException("试卷不存在");
        }
        if (CourseEnums.EnabledMarkType.INVALID.getCode().equals(paper.getEnabledMark())) {
            throw new RuntimeException("试卷已删除");
        }
        if (CourseEnums.DraftStatus.NO.getCode().equals(paper.getIsDraft())) {
            throw new RuntimeException("试卷已经定稿,不能修改");
        }
        if (req.getPaperType() != 0 && req.getPaperType() != 1) {
            throw new RuntimeException("试卷类型错误");
        }

        //修改试卷
        FtbCultivateTestPaper updatePaper = new FtbCultivateTestPaper();
        updatePaper.setId(paper.getId());
        updatePaper.setName(req.getName()); //试卷名称
        updatePaper.setPaperType(req.getPaperType());//试卷类型
//        updatePaper.setType(req.getType()); //抽题类型
        updatePaper.setLastModifyTime(new Date());
        updatePaper.setIsDraft(req.getIsDraft());

        if (CollectionUtil.isNotEmpty(req.getPostAndPositionList())) {
            updatePaper.setPostConfig(JSONUtil.toJsonStr(req.getPostAndPositionList()));
            List<String> postIdList = new ArrayList<>();
            for (PostAndPosition postAndPosition : req.getPostAndPositionList()) {
                postIdList.add(postAndPosition.getId());
            }
            updatePaper.setPostId(postIdList.stream().collect(Collectors.joining(",")));
        }
        //3、修改题卷总分和总题目数量，冗余试卷关联的题库
        updatePaper.setLastModifyTime(new Date());
        baseMapper.updateById(updatePaper);

    }

    /**
     * 修改试卷
     *
     * @param req
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePaperAndQuestion(SavePaperReq req) {
        //兼容老的试卷
        if (null == req.getIsDraft()) {
            req.setIsDraft(0);
        }
        //1、检测名称是否重复  试卷是否存在
        QueryWrapper<FtbCultivateTestPaper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbCultivateTestPaper::getName, req.getName())
                .ne(FtbCultivateTestPaper::getId, req.getId())
                .eq(FtbCultivateTestPaper::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        Long count = baseMapper.selectCount(wrapper);
        if (null != count && count > 0) {
            throw new RuntimeException("试卷名称已经存在");
        }

        FtbCultivateTestPaper paper = getById(req.getId());
        if (null == paper) {
            throw new RuntimeException("试卷不存在");
        }
        if (CourseEnums.EnabledMarkType.INVALID.getCode().equals(paper.getEnabledMark())) {
            throw new RuntimeException("试卷已删除");
        }
        if (paper.getNeedUpdate().equals(ExamUpdateStatus.NO_UPDATE.getCode())) {
            if (CourseEnums.DraftStatus.NO.getCode().equals(paper.getIsDraft())) {
                throw new RuntimeException("试卷已经定稿,不能修改");
            }
        }
        if (req.getPaperType() != 0 && req.getPaperType() != 1) {
            throw new RuntimeException("试卷类型错误");
        }

        //删除试卷题目关系
        LambdaQueryWrapper<FtbCultivateTestPaperQuestion> paperQuestionWrapper = new LambdaQueryWrapper<FtbCultivateTestPaperQuestion>()
                .eq(FtbCultivateTestPaperQuestion::getPaperId, paper.getId());
        paperQuestionService.remove(paperQuestionWrapper);

        //修改试卷
        FtbCultivateTestPaper updatePaper = new FtbCultivateTestPaper();
        updatePaper.setId(paper.getId());
        updatePaper.setName(req.getName()); //试卷名称
        updatePaper.setPaperType(req.getPaperType());//试卷类型
        updatePaper.setType(req.getType()); //抽题类型
        updatePaper.setLastModifyTime(new Date());
        updatePaper.setIsDraft(req.getIsDraft());
        if (req.getPaperConfig() != null) {
            updatePaper.setPaperConfig(JSONUtil.toJsonStr(req.getPaperConfig()));
        }
        if (CollectionUtil.isNotEmpty(req.getPostAndPositionList())) {
            updatePaper.setPostConfig(JSONUtil.toJsonStr(req.getPostAndPositionList()));
            List<String> postIdList = new ArrayList<>();
            for (PostAndPosition postAndPosition : req.getPostAndPositionList()) {
                postIdList.add(postAndPosition.getId());
            }
            updatePaper.setPostId(postIdList.stream().collect(Collectors.joining(",")));
        }
        //2、批量添加试卷关联题目
        List<FtbCultivateTestPaperQuestion> paperQuestionList = new ArrayList<>();
        //2.1 新增固定题目
        CourseEnums.PaperType paperType = CourseEnums.PaperType.fromCode(req.getType());
        switch (paperType) {
            case FIX:
                //固定试卷
                List<SavePaperReq.PaperQuestionItem> questionItemList = req.getQuestionItemList();
                if (CollectionUtil.isNotEmpty(questionItemList)) {
                    //写入试卷题目关联表
                    paperQuestionList = saveFixPaperQuestionRelation(updatePaper.getId(), questionItemList);
                }
                break;
            case RANDOM:
                //随机试卷
                PaperConfigReq paperConfig = req.getPaperConfig();
                if (null == paperConfig) {
                    throw new RuntimeException("试卷配置信息为空");
                }
                if (MapUtil.isEmpty(paperConfig.getQuestionConfig())) {
                    throw new RuntimeException("试卷题目配置信息为空");
                }
                if (MapUtil.isEmpty(paperConfig.getScoreConfig())) {
                    throw new RuntimeException("试卷分数配置信息为空");
                }
                paperQuestionList = saveRandomPaperQuestionRelation(updatePaper.getId(), req.getPaperConfig());
                break;
        }

        //3、修改题卷总分和总题目数量，冗余试卷关联的题库
        updatePaper.setQuestionNumber(paperQuestionList.size());
        int totleScore = paperQuestionList.stream()
                .mapToInt(FtbCultivateTestPaperQuestion::getScore)
                .sum();
        updatePaper.setTotalScore(totleScore);
        updatePaper.setLastModifyTime(new Date());
        Set<String> paperIdSet = paperQuestionList.stream()
                .map(FtbCultivateTestPaperQuestion::getBankId)
                .collect(Collectors.toSet());
        updatePaper.setRelationQuestionBankId(paperIdSet.stream()
                .collect(Collectors.joining(",")));
        updatePaper.setNeedUpdate(ExamUpdateStatus.NO_UPDATE.getCode());
        baseMapper.updateById(updatePaper);

    }


    /**
     * 删除试卷
     *
     * @param paperId 试卷id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteData(String paperId) {
        //1、检测试卷
        FtbCultivateTestPaper paper = getById(paperId);
        if (paper == null) {
            throw new RuntimeException("试卷不存在");
        }
        if (CourseEnums.EnabledMarkType.INVALID.getCode().equals(paper.getEnabledMark())) {
            return;
        }
        if (paper.getIsDraft() == 0) {
            if (CourseEnums.PaperStatus.ENABLED.getCode().equals(paper.getStatus())) {
                throw new RuntimeException("试卷启用中,请先禁用在删除");
            }

            //根据试卷ID查询是否有考试关联了该试卷
            List<ExamVo> examVoList = examService.queryExamListByPaperId(paperId);
            if (CollectionUtil.isNotEmpty(examVoList)) {
                throw new RuntimeException("该试卷绑定了考试，请解除绑定关系后再进行删除");
            }
        }

        //2、删除试卷
        FtbCultivateTestPaper updatePaper = new FtbCultivateTestPaper();
        updatePaper.setId(paper.getId());
        updatePaper.setEnabledMark(CourseEnums.EnabledMarkType.INVALID.getCode());
        updatePaper.setDeleteTime(new Date());
        baseMapper.updateById(updatePaper);
        //3、删除试卷题目关系
        LambdaUpdateWrapper<FtbCultivateTestPaperQuestion> paperQuestionWrapper = new LambdaUpdateWrapper<FtbCultivateTestPaperQuestion>()
                .set(FtbCultivateTestPaperQuestion::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
                .set(FtbCultivateTestPaperQuestion::getDeleteTime, new Date())
                .eq(FtbCultivateTestPaperQuestion::getPaperId, paperId)
                .eq(FtbCultivateTestPaperQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        paperQuestionService.update(paperQuestionWrapper);

        //给考试打一个标记
        UpdateWrapper<FtbCultivateExam> examWrapper = new UpdateWrapper<>();
        examWrapper.lambda()
                .set(FtbCultivateExam::getNeedUpdate, ExamUpdateStatus.NEED_UPDATE.getCode())
                .eq(FtbCultivateExam::getPaperId, paperId);
        examService.update(examWrapper);
    }

    /**
     * 检查试卷是否可以删除
     *
     * @param paperId 试卷id
     * @return
     */
    @Override
    public CanDeleteMsg checkPaperCanDelete(String paperId) {
        FtbCultivateTestPaper paper = getById(paperId);
        if (paper == null) {
            throw new RuntimeException("试卷不存在");
        }
        if (CourseEnums.EnabledMarkType.INVALID.getCode().equals(paper.getEnabledMark())) {
            throw new RuntimeException("试卷已删除");
        }
        if (paper.getIsDraft() == 0) {
            if (CourseEnums.PaperStatus.ENABLED.getCode().equals(paper.getStatus())) {
                throw new RuntimeException("试卷启用中，请先禁用在删除");
            }

            //根据试卷ID查询是否有考试关联了该试卷
            List<ExamVo> examVoList = examService.queryExamListByPaperId(paperId);
            if (CollectionUtil.isNotEmpty(examVoList)) {
                List<DeleteAlertExamVo> alertList = new ArrayList<>();
                examVoList.forEach(examVo -> {
                    DeleteAlertExamVo alertExamVo = new DeleteAlertExamVo();
                    alertExamVo.setId(examVo.getId());
                    alertExamVo.setExamId(examVo.getExamId());
                    alertExamVo.setExamName(examVo.getExamName());
                    alertExamVo.setExamType(examVo.getExamType());
                    //根据岗位ID查询岗位名称
                    if (StringUtils.isNotEmpty(examVo.getPostId())) {
//                        List<PositionEntity> entityList = positionApi.getPositionName(Arrays.asList(examVo.getPostId().split(",")));
                        List<PositionVO> entityList = userApiV2Util.listPositionDetailInfoByIds(Arrays.asList(examVo.getPostId().split(",")), null);
                        if (CollectionUtil.isNotEmpty(entityList)) {
                            List<String> collect = entityList.stream().map(PositionVO::getFullName).collect(Collectors.toList());
                            alertExamVo.setPositionList(collect);
                        }
                    }
                    alertList.add(alertExamVo);
                });
                return new CanDeleteMsg(false, "有考试和该试卷关联", alertList);
            }
        }
        return new CanDeleteMsg(true, "没有考试和该试卷关联");


    }

    /**
     * 切换试卷状态
     *
     * @param paperId 试卷id
     * @param status  状态 0-启用 1-禁用
     */

    @Override
    public void switchEnabledMark(String paperId, Integer status) {
        FtbCultivateTestPaper paper = getById(paperId);
        if (paper == null) {
            throw new RuntimeException("试卷不存在");
        }
        if (CourseEnums.EnabledMarkType.INVALID.getCode().equals(paper.getEnabledMark())) {
            throw new RuntimeException("试卷已删除");
        }
        if (!CourseEnums.PaperStatus.DISABLED.getCode().equals(status)
                && !CourseEnums.PaperStatus.ENABLED.getCode().equals(status)) {
            throw new RuntimeException("status参数异常,只能是[0-启用 1-禁用]");
        }
        if (CourseEnums.PaperStatus.DISABLED.getCode().equals(status)) {
            if (CourseEnums.PaperStatus.DISABLED.getCode().equals(paper.getStatus())) {
                throw new RuntimeException("试卷已禁用,请不要重复操作");
            }
        }

        if (CourseEnums.PaperStatus.ENABLED.getCode().equals(status)) {
            if (CourseEnums.PaperStatus.ENABLED.getCode().equals(paper.getStatus())) {
                throw new RuntimeException("试卷已经启用,请不要重复操作");
            }
        }

        FtbCultivateTestPaper updatePaper = new FtbCultivateTestPaper();
        updatePaper.setId(paper.getId());
        updatePaper.setStatus(status);
        baseMapper.updateById(updatePaper);

    }

    /**
     * 获取试卷信息和试题列表
     *
     * @param paperId 试卷ID
     * @return
     */
    @Override
    public PaperDetailVo queryPaperInfoAndQuestionList(String paperId) {
        //1、查询试卷基本信息
        PaperDetailVo vo = getInfo(paperId);
        //2、查询试卷中的题目列表
        List<FtbCultivateTestPaperQuestion> paperQuestionRelationList = queryPaperQuestionRelationList(paperId);
        Map<String, FtbCultivateTestPaperQuestion> testQuestionMap = paperQuestionRelationList.stream().collect(Collectors.toMap(FtbCultivateTestPaperQuestion::getQuestionId, Function.identity()));

        //3、根据关联的试卷题目ID，查询题目列表
        if (CollectionUtil.isNotEmpty(paperQuestionRelationList)) {
            List<String> questionIdList = paperQuestionRelationList.stream().map(FtbCultivateTestPaperQuestion::getQuestionId).collect(Collectors.toList());
            List<FtbCultivateQuestion> questionList = questionService.listByIds(questionIdList);
            if (CollectionUtil.isNotEmpty(questionList)) {
                List<AppQuestionVo> questionVoList = BeanUtil.copyToList(questionList, AppQuestionVo.class);
                fillQuestionOption(questionVoList);
                Map<String, List<AppQuestionVo>> map = new HashMap<>();
                for (AppQuestionVo questionVo : questionVoList) {
                    FtbCultivateTestPaperQuestion paperQuestion = testQuestionMap.get(questionVo.getId());
                    questionVo.setQuestionScore(paperQuestion.getScore());
                    String type = String.valueOf(questionVo.getType());
                    List<AppQuestionVo> list = map.get(type);
                    if (CollectionUtil.isEmpty(list)) {
                        list = new ArrayList<>();
                    }
                    list.add(questionVo);
                    map.put(type, list);
                }
                vo.setQuestionMap(map);
            }
        }

        return vo;
    }

    /**
     * 根据试卷id查询，试题列表
     *
     * @param paperId 试卷ID
     * @return
     */

    @Override
    public List<FtbCultivateQuestion> queryQuestionListForPaperId(String paperId) {
        //1、查询试卷中的题目列表
        List<FtbCultivateTestPaperQuestion> paperQuestionRelationList = queryPaperQuestionRelationList(paperId);
        //2、根据关联的试卷题目ID，查询题目列表
        if (CollectionUtil.isNotEmpty(paperQuestionRelationList)) {
            List<String> questionIdList = paperQuestionRelationList.stream().map(FtbCultivateTestPaperQuestion::getQuestionId).collect(Collectors.toList());
            List<FtbCultivateQuestion> questionList = questionService.listByIds(questionIdList);
            if (CollectionUtil.isNotEmpty(questionList)) {
                return questionList;
            }
        }
        return Collections.emptyList();
    }

    /**
     * 查询试卷中配置的题目
     * @param paperId 试卷id
     * @return 题目列表
     */
    @Override
    public List<ExamQuestionBakVo> queryConfigQuestionList(String paperId) {
        //1、查询试卷中的题目列表
        List<FtbCultivateTestPaperQuestion> paperQuestionRelationList = queryPaperQuestionRelationList(paperId);
        //2、根据关联的试卷题目ID，查询题目列表
        if (CollectionUtil.isEmpty(paperQuestionRelationList)) {
            Collections.emptyList();
        }
        return BeanUtil.copyToList(paperQuestionRelationList, ExamQuestionBakVo.class);
    }

    /**
     * 根据试卷id查询试卷完整的题目信息（题目内容 题目选项 题目分数）
     *
     * @param paperId 试卷id
     * @return
     */
    public List<AppQuestionVo> queryQuestionList(String paperId) {
        List<AppQuestionVo> questionVoList = new ArrayList<>();
        //1、查询试卷中的题目列表
        List<FtbCultivateTestPaperQuestion> paperQuestionRelationList = queryPaperQuestionRelationList(paperId);
        //2、根据关联的试卷题目ID，查询题目列表
        if (CollectionUtil.isNotEmpty(paperQuestionRelationList)) {
            List<String> questionIdList = paperQuestionRelationList.stream().map(FtbCultivateTestPaperQuestion::getQuestionId).collect(Collectors.toList());
            List<FtbCultivateQuestion> questionList = questionService.listByIds(questionIdList);
            if (CollectionUtil.isNotEmpty(questionList)) {
                Map<String, FtbCultivateQuestion> questionMap = questionList.stream().collect(Collectors.toMap(FtbCultivateQuestion::getId, Function.identity()));
                for (FtbCultivateTestPaperQuestion testPaperQuestion : paperQuestionRelationList) {
                    FtbCultivateQuestion ftbCultivateQuestion = questionMap.get(testPaperQuestion.getQuestionId());
                    if (null != ftbCultivateQuestion && ftbCultivateQuestion.getEnabledMark().equals(1)) {
                        AppQuestionVo vo = BeanUtil.copyProperties(ftbCultivateQuestion, AppQuestionVo.class);
                        vo.setQuestionId(ftbCultivateQuestion.getId());
                        vo.setQuestionScore(testPaperQuestion.getScore());
                        questionVoList.add(vo);
                    }
                }
            }
        }
        return questionVoList;
    }

    /**
     * 填充题目选项
     *
     * @param questionVoList
     */
    @Override
    public void fillQuestionOption(List<AppQuestionVo> questionVoList) {
        //根据题目ID 批量查询题目选项
        List<String> questionIdList = questionVoList.stream().map(AppQuestionVo::getId).collect(Collectors.toList());
        List<FtbCultivateQuestionOption> questionOptionList = questionOptionService.list(new LambdaQueryWrapper<FtbCultivateQuestionOption>()
                .in(FtbCultivateQuestionOption::getQuestionId, questionIdList)
                .eq(FtbCultivateQuestionOption::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode()));
        if (CollectionUtil.isEmpty(questionOptionList)) {
            return;
        }
        //转换问题选项 vo
        List<QuestionOptionVo> optionVoList = BeanUtil.copyToList(questionOptionList, QuestionOptionVo.class);
        //安装题目ID分组
        Map<String, List<QuestionOptionVo>> optionMap = optionVoList.stream()
                .collect(Collectors.groupingBy(QuestionOptionVo::getQuestionId, Collectors.toList()));

        //根据题目ID回填选项
        for (AppQuestionVo questionVo : questionVoList) {
            questionVo.setQuestionOptionVoList(optionMap.get(questionVo.getId()));
        }

    }

    /**
     * 根据试卷id查询试卷的题目列表（题目id 和 题目的分数）
     *
     * @param paperId 试卷ID
     * @return
     */
    @Override
    public List<FtbCultivateTestPaperQuestion> queryPaperQuestionRelationList(String paperId) {
        LambdaQueryWrapper<FtbCultivateTestPaperQuestion> wrapper = new LambdaQueryWrapper<FtbCultivateTestPaperQuestion>()
                .eq(FtbCultivateTestPaperQuestion::getPaperId, paperId);
        return paperQuestionService.list(wrapper);
    }

    /**
     * 设置为正式试卷
     *
     * @param id 试卷id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setFormalPaper(String id) {
        FtbCultivateTestPaper paper = getById(id);
        if (null == paper) {
            throw new RuntimeException("试卷不存在");
        }
        if (CourseEnums.EnabledMarkType.INVALID.getCode().equals(paper.getEnabledMark())) {
            throw new RuntimeException("试卷已删除");
        }
        if (CourseEnums.DraftStatus.NO.getCode().equals(paper.getIsDraft())) {
            throw new RuntimeException("试卷已经定稿,不能修改为正式试卷");
        }

        if (paper.getNeedUpdate().equals(ExamUpdateStatus.NEED_UPDATE.getCode())) {
            throw new RuntimeException("试卷异常,不能修改为正式试卷");
        }
        FtbCultivateTestPaper updatePaper = new FtbCultivateTestPaper();
        updatePaper.setId(paper.getId());
        updatePaper.setIsDraft(CourseEnums.DraftStatus.NO.getCode());
        updatePaper.setLastModifyTime(new Date());
        baseMapper.updateById(updatePaper);

    }

    /**
     * 从试卷中删除题目
     *
     * @param paperId    试卷id
     * @param questionId 题目id
     */
    @Override
    @Transactional
    public void deleteQuestionFormPaper(String paperId, String questionId) {
        List<ExamVo> examVoList = examService.queryExamListByPaperId(paperId);
        if (CollectionUtil.isNotEmpty(examVoList)) {
            //试卷关联考试
            return;
        }
        //试卷未关联考试 从试卷中提出题目 重新计算题目数量和分数
        LambdaQueryWrapper<FtbCultivateTestPaperQuestion> paperQuestionWrapper = new LambdaQueryWrapper<FtbCultivateTestPaperQuestion>()
                .eq(FtbCultivateTestPaperQuestion::getQuestionId, questionId)
                .eq(FtbCultivateTestPaperQuestion::getPaperId, paperId);
        paperQuestionService.remove(paperQuestionWrapper);

        //查询试卷中的题目列表
        List<FtbCultivateTestPaperQuestion> paperQuestionRelationList = queryPaperQuestionRelationList(paperId);
        Integer score = 0;
        Integer sum = 0;
        if (CollectionUtil.isNotEmpty(paperQuestionRelationList)) {
            sum = paperQuestionRelationList.size();
            for (FtbCultivateTestPaperQuestion paperQuestion : paperQuestionRelationList) {
                score += paperQuestion.getScore();
            }
        }
        //修改试卷题目数量和分数
        FtbCultivateTestPaper updatePaper = new FtbCultivateTestPaper();
        updatePaper.setQuestionNumber(sum);
        updatePaper.setTotalScore(score);
        updatePaper.setId(paperId);
        baseMapper.updateById(updatePaper);
        //给考试打一个标记
        UpdateWrapper<FtbCultivateExam> examWrapper = new UpdateWrapper<>();
        examWrapper.lambda()
                .set(FtbCultivateExam::getNeedUpdate, ExamUpdateStatus.NEED_UPDATE.getCode())
                .eq(FtbCultivateExam::getPaperId, paperId);
        examService.update(examWrapper);
    }

    /**
     * 批量删除题目
     *
     * @param paperId     试卷ID
     * @param questionIds 题目集合
     */
    @Override
    @Transactional
    public void batchDeleteQuestionFormPaper(String paperId, List<String> questionIds) {

        //试卷未关联考试 从试卷中提出题目 重新计算题目数量和分数
        LambdaQueryWrapper<FtbCultivateTestPaperQuestion> paperQuestionWrapper = new LambdaQueryWrapper<FtbCultivateTestPaperQuestion>()
                .in(FtbCultivateTestPaperQuestion::getQuestionId, questionIds)
                .eq(FtbCultivateTestPaperQuestion::getPaperId, paperId);
        paperQuestionService.remove(paperQuestionWrapper);

        //查询试卷中的题目列表
        List<FtbCultivateTestPaperQuestion> paperQuestionRelationList = queryPaperQuestionRelationList(paperId);
        Integer score = 0;
        Integer sum = 0;
        if (CollectionUtil.isNotEmpty(paperQuestionRelationList)) {
            sum = paperQuestionRelationList.size();
            for (FtbCultivateTestPaperQuestion paperQuestion : paperQuestionRelationList) {
                score += paperQuestion.getScore();
            }
        }

        //修改试卷题目数量和分数
        FtbCultivateTestPaper updatePaper = new FtbCultivateTestPaper();
        updatePaper.setQuestionNumber(sum);
        updatePaper.setTotalScore(score);
        updatePaper.setId(paperId);
        //检测试卷是否异常
        updatePaper.setNeedUpdate(checkIsRandomNeedUpdate(paperId));
        baseMapper.updateById(updatePaper);

        List<ExamVo> examVoList = examService.queryExamListByPaperId(paperId);
        if (CollectionUtil.isEmpty(examVoList)) {
            //试卷关联考试
            return;
        }
        //给考试打一个标记
        UpdateWrapper<FtbCultivateExam> examWrapper = new UpdateWrapper<>();
        examWrapper.lambda()
                .set(FtbCultivateExam::getNeedUpdate, ExamUpdateStatus.NEED_UPDATE.getCode())
                .eq(FtbCultivateExam::getPaperId, paperId);
        examService.update(examWrapper);
    }

    /**
     * 检测试卷是否需要更新
     *
     * @param paperId 试卷id
     * @return
     */
    private Integer checkIsRandomNeedUpdate(String paperId) {
        FtbCultivateTestPaper paper = baseMapper.selectById(paperId);
        if (paper == null) {
            return ExamUpdateStatus.NO_UPDATE.getCode();
        }
        if (paper.getType().equals(1)) {
            return ExamUpdateStatus.NO_UPDATE.getCode();
        }
        //只要删除了题目 就要异常 所有不需要管他是否能够抽题
        return ExamUpdateStatus.NEED_UPDATE.getCode();

//        if (StringUtils.isEmpty(paper.getPaperConfig())) {
//            return ExamUpdateStatus.NEED_UPDATE.getCode();
//        }
//        PaperConfigReq paperConfig = JSONUtil.toBean(paper.getPaperConfig(), PaperConfigReq.class);
//        List<FtbCultivateQuestion> im = imitateRandom(paperConfig);
//        if (CollectionUtil.isEmpty(im)) {
//            return ExamUpdateStatus.NEED_UPDATE.getCode();
//        }
//
//        //2、初始化返回值
//        Map<String, PaperConfigReq.QuestionNum> imAnalyMap = QuestionAnalysisUtil.initAnalysQuestionCount();
//
//        QuestionAnalysisUtil.analysQuestionCount(imAnalyMap, im);
//
//
//        Map<String, PaperConfigReq.QuestionNum> oldAnalyMap = QuestionAnalysisUtil.initAnalysQuestionCount();
//        Map<String, Map<String, PaperConfigReq.QuestionNum>> questionConfig = paperConfig.getQuestionConfig();
//        //遍历 questionConfig
//        for (Map.Entry<String, Map<String, PaperConfigReq.QuestionNum>> entry : questionConfig.entrySet()) {
//            String questionType = entry.getKey();//题库id
//            Map<String, PaperConfigReq.QuestionNum> questionNumMap = entry.getValue();
//            //遍历 questionNumMap
//            for (Map.Entry<String, PaperConfigReq.QuestionNum> entry2 : questionNumMap.entrySet()) {
//                String questionLevel = entry2.getKey();//题型
//                PaperConfigReq.QuestionNum questionNum = entry2.getValue();
//                PaperConfigReq.QuestionNum tmp = oldAnalyMap.get(questionLevel);
//                tmp.setSimpleNum(questionNum.getSimpleNum() + tmp.getSimpleNum());
//                tmp.setHardNum(questionNum.getHardNum() + tmp.getHardNum());
//                tmp.setGeneralNum(questionNum.getGeneralNum() + tmp.getGeneralNum());
//            }
//        }
//
//        //遍历 oldAnalyMap
//        for (Map.Entry<String, PaperConfigReq.QuestionNum> entry : oldAnalyMap.entrySet()) {
//            String questionLevel = entry.getKey();//题型
//            PaperConfigReq.QuestionNum old = entry.getValue();
//            PaperConfigReq.QuestionNum tmp = imAnalyMap.get(questionLevel);
//            if (tmp == null) {
//                return ExamUpdateStatus.NEED_UPDATE.getCode();
//            }
//            if (!tmp.getSimpleNum().equals(old.getSimpleNum()) || !tmp.getGeneralNum().equals(old.getGeneralNum()) || !tmp.getHardNum().equals(old.getHardNum())) {
//                return ExamUpdateStatus.NEED_UPDATE.getCode();
//            }
//        }
//
//        return ExamUpdateStatus.NO_UPDATE.getCode();

    }


    /**
     * 模拟抽题
     *
     * @param paperConfig 随机选题配置信息
     * @return
     */
    private List<FtbCultivateQuestion> imitateRandom(PaperConfigReq paperConfig) {

        //1、根据配置随机生成题目
        Map<String, Map<String, PaperConfigReq.QuestionNum>> questionConfig = paperConfig.getQuestionConfig();
        Map<String, PaperConfigReq.QuestionScore> scoreConfig = paperConfig.getScoreConfig();

        // 根据题库ID 查询题目列表
        List<String> questionBankIdList = new ArrayList<>(questionConfig.keySet());
        Map<String, List<FtbCultivateQuestion>> questionMap = BatchQueryQuestionForQuestionBankIds(questionBankIdList);

        List<FtbCultivateQuestion> randomList = new ArrayList<>();
        questionMap.forEach((questionBankId, questionList) -> {
            //获取该题库题型对应的题目列表 Map
            Map<String, List<FtbCultivateQuestion>> questionTypeMap = questionList.stream()
                    .collect(Collectors.groupingBy(ftbCultivateQuestion -> String.valueOf(ftbCultivateQuestion.getType())));
            //获取该题库随机选题的配置
            Map<String, PaperConfigReq.QuestionNum> questionNumMap = questionConfig.get(questionBankId);
            //随机选题
            questionNumMap.forEach((questionType, questionNum) -> {
                //题型 的题目列表
                List<FtbCultivateQuestion> tempList = questionTypeMap.get(questionType);
                if (CollectionUtil.isEmpty(tempList)) {
                    return;
                }
                //题型难度列表
                Map<Integer, List<FtbCultivateQuestion>> difficultyMap = tempList.stream().collect(Collectors.groupingBy(FtbCultivateQuestion::getDifficulty));
                //简单
                Integer simpleNum = questionNum.getSimpleNum();
                List<FtbCultivateQuestion> simpleQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.EASY.getCode());
                //一般
                Integer generalNum = questionNum.getGeneralNum();
                List<FtbCultivateQuestion> generalQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.MIDDLE.getCode());
                //难
                Integer hardNum = questionNum.getHardNum();
                List<FtbCultivateQuestion> hardQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.MAX.getCode());
                randomList.addAll(imitateRandomGetQuestion(simpleQuestion, simpleNum, scoreConfig.get(questionType).getSimpleScore()));
                randomList.addAll(imitateRandomGetQuestion(generalQuestion, generalNum, scoreConfig.get(questionType).getGeneralScore()));
                randomList.addAll(imitateRandomGetQuestion(hardQuestion, hardNum, scoreConfig.get(questionType).getHardSore()));
            });
        });
        return randomList;
    }

    /**
     * 模拟从题目列表中抽取一定数量的题目
     * @param questionList 题目列表
     * @param randomSize 抽取数量
     * @param score
     * @return
     */
    private List<FtbCultivateQuestion> imitateRandomGetQuestion(List<FtbCultivateQuestion> questionList, Integer randomSize, Integer score) {
        if (CollectionUtil.isEmpty(questionList) || randomSize <= 0) {
            return new ArrayList<>();
        }
        if (questionList.size() <= randomSize) {
            return questionList;
        }
        // 打乱列表
        Collections.shuffle(questionList);
        // 抽取样本
        return questionList.subList(0, randomSize);
    }
}
