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.FtbCultivateQuestionBankMapper;
import jnpf.cultivate.service.FtbCultivatePositionExamCourseService;
import jnpf.cultivate.service.FtbCultivateQuestionBankCourseService;
import jnpf.cultivate.service.FtbCultivateQuestionBankService;
import jnpf.cultivate.service.FtbCultivateQuestionService;
import jnpf.model.cultivate.bo.FtbCultivateCourseBO;
import jnpf.model.cultivate.po.question.FtbCultivateQuestion;
import jnpf.model.cultivate.po.question.FtbCultivateQuestionBank;
import jnpf.model.cultivate.po.question.FtbCultivateQuestionBankCourse;
import jnpf.model.cultivate.req.paper.PaperConfigReq;
import jnpf.model.cultivate.req.questionbank.AddQuestionBankReq;
import jnpf.model.cultivate.req.questionbank.EditQuestionBankReq;
import jnpf.model.cultivate.req.questionbank.QueryQuestionBankReq;
import jnpf.model.cultivate.req.questionbank.UnbindQuestionBankReq;
import jnpf.model.cultivate.resp.CanDeleteMsg;
import jnpf.model.cultivate.resp.QuestionBankVo;
import jnpf.model.cultivate.resp.QuestionCountDto;
import jnpf.model.enums.CourseEnums;
import jnpf.model.enums.SelfrowingEnum;
import jnpf.util.QuestionAnalysisUtil;
import jnpf.util.SelfGrowthUtil;
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;

@Service
@Slf4j
public class FtbCultivateQuestionBankServiceImpl extends ServiceImpl<FtbCultivateQuestionBankMapper, FtbCultivateQuestionBank> implements FtbCultivateQuestionBankService {

    /**
     * 题库课程关联服务
     */
    @Autowired
    private FtbCultivateQuestionBankCourseService questionBankCourseService;

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

    @Autowired
    private FtbCultivatePositionExamCourseService positionExamCourseService;

    /**
     * 分页查询题库列表
     *
     * @param req
     * @return
     */
    @Override
    public PageInfo<QuestionBankVo> getPageList(QueryQuestionBankReq req) {
        if (StringUtils.isNotEmpty(req.getKeyword())) {
            req.setKeyword(StringUtils.trim(req.getKeyword()));
        }
        //构建分页
        Page<FtbCultivateQuestionBank> page = new Page(req.getCurrentPage(), req.getPageSize());
        //构建查询
        LambdaQueryWrapper<FtbCultivateQuestionBank> wrapper = new LambdaQueryWrapper<FtbCultivateQuestionBank>()
                .like(!StringUtils.isEmpty(req.getKeyword()), FtbCultivateQuestionBank::getBankContent, req.getKeyword())
                .eq(FtbCultivateQuestionBank::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode())
                .orderByDesc(FtbCultivateQuestionBank::getLastModifyTime);
        Page<FtbCultivateQuestionBank> queryPage = baseMapper.selectPage(page, wrapper);
        List<FtbCultivateQuestionBank> records = queryPage.getRecords();
        //转换查询对象
        List<QuestionBankVo> list = new ArrayList<>();
        Map<String, List<String>> map = new HashMap<>();
        Map<String, FtbCultivateCourseBO> courseNameMap = new HashMap<>();
        Map<String, QuestionCountDto> countMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(records)) {
            List<String> questionBankId = new ArrayList<>();
            for (FtbCultivateQuestionBank vo : records) {
                questionBankId.add(vo.getId());
            }
            List<QuestionCountDto> questionCountDtoList = questionService.countForClassifyId(questionBankId);
            if (CollectionUtil.isNotEmpty(questionCountDtoList)) {
                for (QuestionCountDto questionCountDto : questionCountDtoList) {
                    countMap.put(questionCountDto.getQuestionBankId(), questionCountDto);
                }
            }
            List<FtbCultivateQuestionBankCourse> ftbCultivateQuestionBankCourses = batchQueryQuestionBankCourse(questionBankId);
            Set<String> allCourseSet = new HashSet<>();
            if (CollectionUtil.isNotEmpty(ftbCultivateQuestionBankCourses)) {
                //题库id分组
                Map<String, List<FtbCultivateQuestionBankCourse>> ftbCultivateQuestionBankCourseMap = ftbCultivateQuestionBankCourses.stream().collect(Collectors.groupingBy(FtbCultivateQuestionBankCourse::getClassifyId));
                for (Map.Entry<String, List<FtbCultivateQuestionBankCourse>> entry : ftbCultivateQuestionBankCourseMap.entrySet()) {
                    String key = entry.getKey();  // 获取当前 entry 的 key
                    List<FtbCultivateQuestionBankCourse> value = entry.getValue();  // 获取当前 entry 的 value

                    List<String> courseList = new ArrayList<>();//已经存在的课程ID
                    if (CollectionUtil.isNotEmpty(value)) {
                        for (FtbCultivateQuestionBankCourse questionBankCourse : value) {
                            courseList.add(questionBankCourse.getCourseId());
                        }
                    }
                    map.put(key, courseList);
                    if (CollectionUtil.isNotEmpty(courseList)) {
                        allCourseSet.addAll(courseList);
                    }
                }
            }

            if (CollectionUtil.isNotEmpty(allCourseSet)) {
                List<FtbCultivateCourseBO> courseName = positionExamCourseService.getCourseName(new ArrayList<>(allCourseSet));
                if (CollectionUtil.isNotEmpty(courseName)) {
                    for (FtbCultivateCourseBO ftbCultivateCourseBO : courseName) {
                        courseNameMap.put(ftbCultivateCourseBO.getCourseId(), ftbCultivateCourseBO);
                    }
                }
            }
        }
        records.forEach(entity -> {
            QuestionBankVo vo = BeanUtil.copyProperties(entity, QuestionBankVo.class);

            //统计题库中题目数量
            QuestionCountDto questionCountDto = countMap.get(entity.getId());
            if(questionCountDto!=null){
                vo.setQuestionNum(questionCountDto.getNum());
            }else{
                vo.setQuestionNum(0L);
            }

            //查看题库关联的课程信息
            List<String> courseList = map.get(vo.getId());
            vo.setCourseList(courseList);
            //查询课程名称
            if (CollectionUtil.isNotEmpty(courseList)) {
                List<FtbCultivateCourseBO> courseDTOList = new ArrayList<>();
                for (String s : courseList) {
                    FtbCultivateCourseBO ftbCultivateCourseBO = courseNameMap.get(s);
                    if (ftbCultivateCourseBO != null) {
                        courseDTOList.add(ftbCultivateCourseBO);
                    }
                }
                vo.setCourseDTOList(courseDTOList);
            }
            list.add(vo);
        });
        //构建分页返回数据
        PageInfo<QuestionBankVo> pageInfo = new PageInfo<>();
        pageInfo.setList(list);
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setTotal((int) queryPage.getTotal());
        return pageInfo;
    }

    /**
     * 获取题库信息
     * @param id 题库ID
     * @return
     */
    @Override
    public QuestionBankVo getInfo(String id) {
        //1、查询题库信息
        FtbCultivateQuestionBank questionBank = baseMapper.selectById(id);
        if (null == questionBank) {
            throw new RuntimeException("题库不存在");
        }
        if (questionBank.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
            throw new RuntimeException("题库已经被删除");
        }
        QuestionBankVo vo = new QuestionBankVo();
        vo.setId(questionBank.getId());
        vo.setBankContent(questionBank.getBankContent());
        vo.setClassifyId(questionBank.getClassifyId());
        //2、查询题库关联的课程信息
        List<String> courseList = queryQuestionBankCourse(id);

        vo.setCourseList(courseList);
        return vo;
    }


    /**
     * 新增题库
     *
     * @param addQuestionBank
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertData(AddQuestionBankReq addQuestionBank) {
        //1、保存题库
        FtbCultivateQuestionBank questionBank = new FtbCultivateQuestionBank();
        questionBank.setBankContent(addQuestionBank.getBankContent());
        questionBank.setClassifyId(generateClassId());
        questionBank.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
        questionBank.setLastModifyTime(new Date());
        baseMapper.insert(questionBank);
        //2、保存题库和课程的关联
        String courseIds = addQuestionBank.getCourseIds();
        if (StringUtils.isEmpty(courseIds)) {
            return;
        }
        List<String> courseList = Arrays.asList(courseIds.split(","));
        if (CollectionUtil.isEmpty(courseList)) {
            return;
        }
        //3、保存题库和课程的关联关系
        saveQuestionBankAndCourseRelation(questionBank.getId(), courseList);
    }

    /**
     * 保存题库和课程的关联关系
     *
     * @param questionBankId
     * @param courseList
     */
    private void saveQuestionBankAndCourseRelation(String questionBankId, List<String> courseList) {
        List<FtbCultivateQuestionBankCourse> questionBankCourseList = new ArrayList<>();
        for (String courseId : courseList) {
            if (StringUtils.isEmpty(courseId)) {
                continue;
            }
            FtbCultivateQuestionBankCourse questionBankCourse = new FtbCultivateQuestionBankCourse();
            questionBankCourse.setClassifyId(questionBankId);
            questionBankCourse.setCourseId(courseId);
            questionBankCourse.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
            questionBankCourseList.add(questionBankCourse);
        }
        questionBankCourseService.saveBatch(questionBankCourseList);
    }

    /**
     * 删除已经存在的课程ID
     *
     * @param questionBankId 题库ID
     * @param courseIdList   课程ID列表
     */
    private void deleteQuestionBankCourses(String questionBankId, List<String> courseIdList) {
        UpdateWrapper<FtbCultivateQuestionBankCourse> questionBankCourseWrapper = new UpdateWrapper<>();
        questionBankCourseWrapper.lambda().set(FtbCultivateQuestionBankCourse::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
                .eq(FtbCultivateQuestionBankCourse::getClassifyId, questionBankId)
                .in(FtbCultivateQuestionBankCourse::getCourseId, courseIdList);
        questionBankCourseService.update(questionBankCourseWrapper);
    }

    /**
     * 生成题库ID
     *
     * @return
     */
    private String generateClassId() {
        return SelfGrowthUtil.provideACustomIDBasedOnTheModule(SelfrowingEnum.QUESTION_BANK);
    }


    /**
     * 修改题库
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateData(EditQuestionBankReq req) {
        //1、修改题库
        FtbCultivateQuestionBank questionBank = new FtbCultivateQuestionBank();
        questionBank.setBankContent(req.getBankContent());
        questionBank.setClassifyId(generateClassId());
        questionBank.setId(req.getId());
        baseMapper.updateById(questionBank);
        //获取整理前段传入的课程ID
        List<String> reqCourseList = new ArrayList<>();
        String reqCourseIds = req.getCourseIds();
        if (StringUtils.isNotEmpty(reqCourseIds)) {
            reqCourseList = Arrays.asList(reqCourseIds.split(","));
        }


        //2、查询题库已经存在课程
        List<String> exiestList = queryQuestionBankCourse(req.getId());//已经存在的课程ID
        //3、如果前段没有传入课程ID,就清楚所有的课程id
        if (CollectionUtil.isEmpty(reqCourseList) && CollectionUtil.isNotEmpty(exiestList)) {
            deleteQuestionBankCourses(req.getId(), exiestList);
            return;
        }
        //4、如果前段传入课程id，保存新增的课程ID
        if (CollectionUtil.isNotEmpty(reqCourseList)) {
            //需要添加的
            List<String> addCourseList = new ArrayList<>();
            Set<String> set = exiestList.stream().collect(Collectors.toSet());
            for (String courseId : reqCourseList) {
                if (!set.contains(courseId)) {
                    addCourseList.add(courseId);
                }
            }
            if (CollectionUtil.isNotEmpty(addCourseList)) {
                saveQuestionBankAndCourseRelation(req.getId(), addCourseList);
            }

            //需要删除的
            List<String> removeCourseList = new ArrayList<>();
            Set<String> reqSet = reqCourseList.stream().collect(Collectors.toSet());
            for (String courseId : exiestList) {
                if (!reqSet.contains(courseId)) {
                    removeCourseList.add(courseId);
                }
            }
            if (CollectionUtil.isNotEmpty(removeCourseList)) {
                deleteQuestionBankCourses(req.getId(), removeCourseList);
            }
        }

    }


    /**
     * 删除课程的时候，删除题库关联课程
     *
     * @param courseIds 课程ID列表
     */
    @Override
    public void deleteQuestionBankRelationCourse(List<String> courseIds) {
        if (CollectionUtil.isEmpty(courseIds)) {
            return;
        }
        //删除题库关联的课程
        UpdateWrapper<FtbCultivateQuestionBankCourse> wrapper = new UpdateWrapper<>();
        wrapper.lambda().set(FtbCultivateQuestionBankCourse::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
                .in(FtbCultivateQuestionBankCourse::getCourseId, courseIds)
                .eq(FtbCultivateQuestionBankCourse::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        questionBankCourseService.update(null, wrapper);
    }

    /**
     * 查询题库关联的课程id列表
     *
     * @param questionBankId 题库ID
     * @return
     */
    private List<String> queryQuestionBankCourse(String questionBankId) {
        QueryWrapper<FtbCultivateQuestionBankCourse> questionBankCourseWrapper = new QueryWrapper<>();
        questionBankCourseWrapper.lambda()
                .eq(FtbCultivateQuestionBankCourse::getClassifyId, questionBankId)
                .eq(FtbCultivateQuestionBankCourse::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateQuestionBankCourse> questionBankCoursesList = questionBankCourseService.list(questionBankCourseWrapper);
        List<String> courseList = new ArrayList<>();//已经存在的课程ID
        if (CollectionUtil.isEmpty(questionBankCoursesList)) {
            return courseList;
        }
        for (FtbCultivateQuestionBankCourse questionBankCourse : questionBankCoursesList) {
            courseList.add(questionBankCourse.getCourseId());
        }
        return courseList;
    }

    /**
     * 批量查询题库关联的课程
     * @param questionBankId 题库id集合
     * @return
     */
    private List<FtbCultivateQuestionBankCourse> batchQueryQuestionBankCourse(List<String> questionBankId) {
        QueryWrapper<FtbCultivateQuestionBankCourse> questionBankCourseWrapper = new QueryWrapper<>();
        questionBankCourseWrapper.lambda()
                .in(FtbCultivateQuestionBankCourse::getClassifyId, questionBankId)
                .eq(FtbCultivateQuestionBankCourse::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode());
        List<FtbCultivateQuestionBankCourse> questionBankCoursesList = questionBankCourseService.list(questionBankCourseWrapper);

        if (CollectionUtil.isEmpty(questionBankCoursesList)) {
            return new ArrayList<>();
        }

        return questionBankCoursesList;
    }


    /**
     * 删除题库
     * 1、检测题库是否存在
     * 2、检测题库中所有题目是否被试卷收录，如果有被试卷收录，则不能删除
     * 3、删除题库 和 题库的题目
     *
     * @param id 题库ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteData(String id) {
        FtbCultivateQuestionBank questionBank = baseMapper.selectById(id);
        if (null == questionBank) {
            throw new RuntimeException("题库不存在");
        }
        if (questionBank.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
            return;
        }


        //删除题库
        questionBank.setEnabledMark(CourseEnums.EnabledMarkType.INVALID.getCode());
        baseMapper.updateById(questionBank);
        //删除题库关联的课程
        UpdateWrapper<FtbCultivateQuestionBankCourse> questionBankCourseWrapper = new UpdateWrapper<>();
        questionBankCourseWrapper.lambda().set(FtbCultivateQuestionBankCourse::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
                .eq(FtbCultivateQuestionBankCourse::getClassifyId, id);
        questionBankCourseService.update(questionBankCourseWrapper);
    }

    /**
     * 解除题库和课程的绑定
     *
     * @param req
     */
    @Override
    public void unbind(UnbindQuestionBankReq req) {

        UpdateWrapper<FtbCultivateQuestionBankCourse> questionBankCourseWrapper = new UpdateWrapper<>();
        questionBankCourseWrapper.lambda().set(FtbCultivateQuestionBankCourse::getEnabledMark, CourseEnums.EnabledMarkType.INVALID.getCode())
                .eq(FtbCultivateQuestionBankCourse::getClassifyId, req.getId())
                .eq(FtbCultivateQuestionBankCourse::getCourseId, req.getCourseId());
        questionBankCourseService.update(questionBankCourseWrapper);

    }

    /**
     * 检测题库是否可以删除
     *
     * @param questionBankId 题库ID
     * @return
     */
    @Override
    public CanDeleteMsg checkQuestionBankCanDelete(String questionBankId) {
        return questionService.checkQuestionBankCanDelete(questionBankId);
    }

    /**
     * 统计题库中各题目类型数量
     *
     * @param questionBankId 题库ID
     * @return
     */
    @Override
    public Map<String, PaperConfigReq.QuestionNum> analysQuestionCount(String questionBankId) {

        FtbCultivateQuestionBank questionBank = baseMapper.selectById(questionBankId);
        if (null == questionBank) {
            throw new RuntimeException("题库不存在");
        }
        if (questionBank.getEnabledMark().equals(CourseEnums.EnabledMarkType.INVALID.getCode())) {
            throw new RuntimeException("题库已经被删除");
        }

        //初始化返回值
        Map<String, PaperConfigReq.QuestionNum> analyMap = QuestionAnalysisUtil.initAnalysQuestionCount();

        List<FtbCultivateQuestion> questionList = questionService.list(new QueryWrapper<FtbCultivateQuestion>().lambda().eq(FtbCultivateQuestion::getClassifyId, questionBankId).eq(FtbCultivateQuestion::getEnabledMark, CourseEnums.EnabledMarkType.VALID.getCode()));
        QuestionAnalysisUtil.analysQuestionCount(analyMap, questionList);
        return analyMap;
    }


}
