package jnpf.cultivate.v2.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jnpf.cultivate.mapper.*;
import jnpf.cultivate.service.CultivateIdentifyApplyService;
import jnpf.cultivate.service.CultivateIdentifyTableService;
import jnpf.cultivate.service.impl.FtbCultivatePositionCourceChapterLearningService;
import jnpf.cultivate.v2.service.V2CultivateBatchQueryService;
import jnpf.entity.cultivate.CultivateIdentifyApply;
import jnpf.entity.cultivate.CultivateIdentifyTable;
import jnpf.entity.cultivate.TeachingRecord;
import jnpf.entity.cultivate.TeachingSkill;
import jnpf.model.cultivate.dto.learn.BatchCommonCountDto;
import jnpf.model.cultivate.po.certificate.FtbCertificateEntity;
import jnpf.model.cultivate.po.certificate.FtbCertificateUserEntity;
import jnpf.model.cultivate.po.course.FtbCultivateCourse;
import jnpf.model.cultivate.po.course.FtbCultivateCourseChapter;
import jnpf.model.cultivate.po.exam.FtbCultivateExam;
import jnpf.model.cultivate.po.exam.FtbCultivateExamUser;
import jnpf.model.cultivate.po.position.*;
import jnpf.model.cultivate.po.promotion.FtbCultivatePromotionPostNew;
import jnpf.model.cultivate.v2.course.vo.app.V2ChapterVo;
import jnpf.model.cultivate.v2.position.req.FtbCultivatePositionCoursePracticeReq;
import jnpf.model.cultivate.v2.position.req.FtbCultivatePositionCourseReq;
import jnpf.model.cultivate.v2.position.req.FtbCultivatePositionSaveReq;
import jnpf.model.cultivate.v2.promotion.vo.PositionProgressVo;
import jnpf.model.cultivate.v2.statistics.V2BatchQueryResult;
import jnpf.model.cultivate.v2.task.req.V2CultivateTaskSaveReq;
import jnpf.model.cultivate.v2.task.vo.V2CultivateLearnTaskCourseVo;
import jnpf.model.cultivate.v2.task.vo.V2CultivateLearnTaskPhaseVo;
import jnpf.model.cultivate.v2.task.vo.V2CultivateLearnTaskPracticeVo;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * V2培养模块批量查询服务实现类
 * 提供根据ID列表批量查询课程、考试、鉴定、证书、练习技能信息的功能
 */
@Service
public class V2CultivateBatchQueryServiceImpl implements V2CultivateBatchQueryService {


    @Autowired
    private CultivateIdentifyTableService cultivateIdentifyTableService;

    @Autowired
    private CultivateIdentifyApplyService cultivateIdentifyApplyService;

    @Autowired
    private CultivateIdentifyApplyMapper cultivateIdentifyApplyMapper;

    @Autowired
    private FtbCultivatePositionCourceChapterLearningService chapterLearningService;

    @Autowired
    private FtbCultivateCertificateUserMapper ftbCertificateUserMapper;

    @Autowired
    private TeachingRecordMapper teachingRecordMapper;

    @Autowired
    private FtbCultivatePositionCourseMapper ftbCultivatePositionCourseMapper;

    @Autowired
    private FtbCultivatePositionCourseExamMapper ftbCultivatePositionCourseExamMapper;

    @Autowired
    private FtbCultivatePositionCourseIdentityMapper ftbCultivatePositionCourseIdentityMapper;

    @Autowired
    private FtbCultivatePositionCoursePracticeMapper ftbCultivatePositionCoursePracticeMapper;

    @Autowired
    private FtbCultivatePositionMapper ftbCultivatePositionMapper;

    @Autowired
    private TeachingSkillMapper teachingSkillMapper;

    @Autowired
    private FtbCultivateCourseMapper ftbCultivateCourseMapper;


    @Autowired
    private FtbCultivateCourseChapterMapper ftbCultivateCourseChapterMapper;

    @Autowired
    private FtbCultivateExamMapper ftbCultivateExamMapper;

    @Autowired
    private FtbCultivateCertificateMapper ftbCultivateCertificateMapper;


    @Autowired
    private FtbCultivateExamUserMapper ftbCultivateExamUserMapper;

    @Autowired
    private FtbCultivatePositionCourceLearningMapper ftbCultivatePositionCourceLearningMapper;

    @Autowired
    private FtbCultivatePositionCourceChapterLearningMapper ftbCultivatePositionCourceChapterLearningMapper;

    /**
     * 根据课程ID列表批量查询课程信息
     *
     * @param courseIds        课程ID列表
     * @param isSelectNoDelete 0-查询有效的 1-查询删除的  null 查询全部
     * @return 以课程ID为键，课程对象为值的映射表
     */
    @Override
    public Map<String, FtbCultivateCourse> batchQueryCoursesByIds(List<String> courseIds, Integer isSelectNoDelete) {
        if (CollUtil.isEmpty(courseIds)) {
            return new HashMap<>();
        }

        LambdaQueryWrapper<FtbCultivateCourse> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbCultivateCourse::getId, courseIds)
                .eq(FtbCultivateCourse::getIsGroundIng, 1)
                .eq(isSelectNoDelete != null, FtbCultivateCourse::getEnableMark, isSelectNoDelete); // 只查询有效的课程

        List<FtbCultivateCourse> courses = ftbCultivateCourseMapper.selectList(queryWrapper);
        return courses.stream().collect(Collectors.toMap(FtbCultivateCourse::getId, item -> item));
    }


    /**
     * 根据考试ID列表批量查询考试信息
     *
     * @param examIds          考试ID列表
     * @param isSelectNoDelete 0-查询有效的 1-查询删除的  null 查询全部
     * @return 以考试ID为键，考试对象为值的映射表
     */
    @Override
    public Map<String, FtbCultivateExam> batchQueryExamsByIds(List<String> examIds, Integer isSelectNoDelete) {
        if (CollUtil.isEmpty(examIds)) {
            return new HashMap<>();
        }
        if (isSelectNoDelete != null) {//考试和其他不一样 由于历史原因
            if (isSelectNoDelete == 0) {
                isSelectNoDelete = 1;
            } else {
                isSelectNoDelete = 0;
            }
        }
        LambdaQueryWrapper<FtbCultivateExam> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbCultivateExam::getId, examIds)
                .eq(isSelectNoDelete != null, FtbCultivateExam::getEnabledMark, isSelectNoDelete); // 只查询有效的考试

        List<FtbCultivateExam> exams = ftbCultivateExamMapper.selectList(queryWrapper);
        return exams.stream().collect(Collectors.toMap(FtbCultivateExam::getId, item -> item));
    }


    /**
     * 根据鉴定ID列表批量查询鉴定信息
     *
     * @param identityIds      鉴定ID列表
     * @param isSelectNoDelete 0-查询有效的 1-查询删除的  null 查询全部
     * @return 以鉴定ID为键，鉴定对象为值的映射表
     */
    @Override
    public Map<String, CultivateIdentifyTable> batchQueryIdentificationsByIds(List<String> identityIds, Integer isSelectNoDelete) {
        if (CollUtil.isEmpty(identityIds)) {
            return new HashMap<>();
        }

        LambdaQueryWrapper<CultivateIdentifyTable> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(CultivateIdentifyTable::getId, identityIds)
                .eq(isSelectNoDelete != null, CultivateIdentifyTable::getDeleteMark, isSelectNoDelete);//0-有效

        List<CultivateIdentifyTable> identities = cultivateIdentifyTableService.list(queryWrapper);
        return identities.stream().collect(Collectors.toMap(CultivateIdentifyTable::getId, item -> item));
    }


    /**
     * 根据证书ID列表批量查询证书信息
     *
     * @param certificateIds   证书ID列表
     * @param isSelectNoDelete 0-查询有效的 1-查询删除的  null 查询全部
     * @return 以证书ID为键，证书对象为值的映射表
     */
    @Override
    public Map<String, FtbCertificateEntity> batchQueryCertificatesByIds(List<String> certificateIds, Integer isSelectNoDelete) {
        if (CollUtil.isEmpty(certificateIds)) {
            return new HashMap<>();
        }

        LambdaQueryWrapper<FtbCertificateEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbCertificateEntity::getId, certificateIds)
                .eq(FtbCertificateEntity::getStatus, 1);
        if (isSelectNoDelete != null) {
            if (isSelectNoDelete == 0) {
                queryWrapper.eq(FtbCertificateEntity::getEnabledMark, 1); // 只查询有效的证书
            } else {
                queryWrapper.eq(FtbCertificateEntity::getEnabledMark, 0); // 只查询有效的证书
            }
        }


        List<FtbCertificateEntity> certificates = ftbCultivateCertificateMapper.selectList(queryWrapper);
        return certificates.stream().collect(Collectors.toMap(FtbCertificateEntity::getId, item -> item));
    }


    /**
     * 根据技能ID列表批量查询技能信息
     *
     * @param practiceSkillIds 技能ID列表
     * @param isSelectNoDelete 0-查询有效的 1-查询删除的  null 查询全部
     * @return 以技能ID为键，技能对象为值的映射表
     */
    @Override
    public Map<String, TeachingSkill> batchQuerySkillsByIds(List<String> practiceSkillIds, Integer isSelectNoDelete) {
        if (CollUtil.isEmpty(practiceSkillIds)) {
            return new HashMap<>();
        }

        LambdaQueryWrapper<TeachingSkill> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(TeachingSkill::getId, practiceSkillIds)
                .eq(isSelectNoDelete != null, TeachingSkill::getDeleteMark, isSelectNoDelete);//0-有效 1-删除

        List<TeachingSkill> skills = teachingSkillMapper.selectList(queryWrapper);
        return skills.stream().collect(Collectors.toMap(TeachingSkill::getId, item -> item));
    }

    /**
     * 批量查询所有信息
     *
     * @param courseIds        课程ID列表
     * @param examIds          考试ID列表
     * @param identityIds      鉴定ID列表
     * @param certificateIds   证书ID列表
     * @param practiceSkillIds 技能ID列表
     * @param isSelectNoDelete 0-查询有效的 1-查询删除的  null 查询全部
     * @return 批量查询结果
     */
    @Override
    public V2BatchQueryResult batchQueryAllByIds(List<String> courseIds, List<String> examIds, List<String> identityIds, List<String> certificateIds, List<String> practiceSkillIds, Integer isSelectNoDelete) {

        // 并行执行批量查询，提高性能
        Map<String, FtbCultivateCourse> courseMap = batchQueryCoursesByIds(courseIds, isSelectNoDelete);
        Map<String, FtbCultivateExam> examMap = batchQueryExamsByIds(examIds, isSelectNoDelete);
        Map<String, CultivateIdentifyTable> identityMap = batchQueryIdentificationsByIds(identityIds, isSelectNoDelete);
        Map<String, FtbCertificateEntity> certificateMap = batchQueryCertificatesByIds(certificateIds, isSelectNoDelete);
        Map<String, TeachingSkill> skillMap = batchQuerySkillsByIds(practiceSkillIds, isSelectNoDelete);

        return new V2BatchQueryResult(courseMap, examMap, identityMap, certificateMap, skillMap);
    }


    /**
     * 批量查询用户在指定课程中的学习状态
     *
     * @param userId    用户ID
     * @param courseIds 课程ID列表
     * @return 以课程ID为键，用户学习记录为值的映射表
     */
    @Override
    public Map<String, FtbCultivatePositionCourceLearning> batchQueryUserCourseLearnStatus(String userId, List<String> courseIds) {
        if (CollUtil.isEmpty(courseIds)) {
            return new HashMap<>();
        }

        // 构建查询条件，查询用户在指定课程中的学习情况
        LambdaQueryWrapper<FtbCultivatePositionCourceLearning> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(FtbCultivatePositionCourceLearning::getId,
                        FtbCultivatePositionCourceLearning::getUserId,
                        FtbCultivatePositionCourceLearning::getCourceId,
                        FtbCultivatePositionCourceLearning::getState,
                        FtbCultivatePositionCourceLearning::getLearnTime)
                .eq(FtbCultivatePositionCourceLearning::getUserId, userId)
                .in(FtbCultivatePositionCourceLearning::getCourceId, courseIds)
                .eq(FtbCultivatePositionCourceLearning::getEnabledMark, 0); // 有效标志为0表示有效

        List<FtbCultivatePositionCourceLearning> courseLearnings = ftbCultivatePositionCourceLearningMapper.selectList(queryWrapper);

        // 构建key为userId-courseId的映射
        Map<String, FtbCultivatePositionCourceLearning> resultMap = new HashMap<>();
        for (FtbCultivatePositionCourceLearning learning : courseLearnings) {
            resultMap.put(learning.getCourceId(), learning);
        }

        return resultMap;
    }


    /**
     * 批量查询用户在指定考试中的状态
     *
     * @param userId  用户ID
     * @param examIds 考试ID列表
     * @return 以考试ID为键，用户考试记录为值的映射表
     */
    @Override
    public Map<String, FtbCultivateExamUser> batchQueryUserExamStatus(String userId, List<String> examIds) {
        if (CollUtil.isEmpty(examIds)) {
            return new HashMap<>();
        }

        // 构建查询条件，查询用户在指定考试中的情况
        LambdaQueryWrapper<FtbCultivateExamUser> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(FtbCultivateExamUser::getId,
                        FtbCultivateExamUser::getExamId,
                        FtbCultivateExamUser::getStatus,
                        FtbCultivateExamUser::getScore,
                        FtbCultivateExamUser::getRanks,
                        FtbCultivateExamUser::getDuration,
                        FtbCultivateExamUser::getFinishTime)
                .eq(FtbCultivateExamUser::getUserId, userId)
                .in(FtbCultivateExamUser::getExamId, examIds)
                .eq(FtbCultivateExamUser::getEnabledMark, 1); // 有效标志为1表示有效

        List<FtbCultivateExamUser> examUsers = ftbCultivateExamUserMapper.selectList(queryWrapper);

        // 构建key为userId-examId的映射
        Map<String, FtbCultivateExamUser> resultMap = new HashMap<>();
        for (FtbCultivateExamUser examUser : examUsers) {
            resultMap.put(examUser.getExamId(), examUser);
        }

        return resultMap;
    }


    /**
     * 批量查询用户在指定鉴定中的状态
     *
     * @param userId      用户ID
     * @param identifyIds 鉴定ID列表
     * @return 以鉴定ID为键，用户鉴定记录为值的映射表
     */
    @Override
    public Map<String, CultivateIdentifyApply> batchQueryUserIdentificationStatus(String userId, List<String> identifyIds) {
        if (CollUtil.isEmpty(identifyIds)) {
            return new HashMap<>();
        }

        // 构建查询条件，查询用户在指定鉴定中的情况
        LambdaQueryWrapper<CultivateIdentifyApply> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(CultivateIdentifyApply::getTableId,
                        CultivateIdentifyApply::getName,
                        CultivateIdentifyApply::getBeIdentifyUserId,
                        CultivateIdentifyApply::getIdentifyUserId,
                        CultivateIdentifyApply::getResult,
                        CultivateIdentifyApply::getStatus)
                .eq(CultivateIdentifyApply::getBeIdentifyUserId, userId)
                .in(CultivateIdentifyApply::getTableId, identifyIds)
                .eq(CultivateIdentifyApply::getDeleteMark, 0); // 0是否删除标记

        List<CultivateIdentifyApply> identifies = cultivateIdentifyApplyService.list(queryWrapper);

        // 构建key为userId-identifyId的映射
        Map<String, CultivateIdentifyApply> resultMap = new HashMap<>();
        for (CultivateIdentifyApply identify : identifies) {
            resultMap.put(identify.getTableId(), identify);
        }

        return resultMap;
    }


    @Override
    public Map<String, CultivateIdentifyApply> batchQueryUserIdentificationStatus(String userId, List<String> identifyIds, Integer source, String sourceId) {
        if (CollUtil.isEmpty(identifyIds)) {
            return new HashMap<>();
        }

        // 构建查询条件，查询用户在指定鉴定中的情况
        List<CultivateIdentifyApply> identifies = cultivateIdentifyApplyService.queryIdentifyApply(userId, identifyIds, source, sourceId);
        // 构建key为userId-identifyId的映射
        Map<String, CultivateIdentifyApply> resultMap = new HashMap<>();
        for (CultivateIdentifyApply identify : identifies) {
            resultMap.put(identify.getTableId(), identify);
        }

        return resultMap;
    }


    /**
     * 批量查询用户在指定证书中的状态
     *
     * @param userId         用户ID
     * @param certificateIds 证书ID列表
     * @return 以证书ID为键，用户证书记录为值的映射表
     */
    @Override
    public Map<String, FtbCertificateUserEntity> batchQueryUserCertificateStatus(String userId, List<String> certificateIds) {
        if (CollUtil.isEmpty(certificateIds)) {
            return new HashMap<>();
        }

        // 构建查询条件，查询用户在指定证书中的情况
        LambdaQueryWrapper<FtbCertificateUserEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(FtbCertificateUserEntity::getId,
                        FtbCertificateUserEntity::getCertificateId,
                        FtbCertificateUserEntity::getUserId,
                        FtbCertificateUserEntity::getStatus,
                        FtbCertificateUserEntity::getReason,
                        FtbCertificateUserEntity::getNumber,
                        FtbCertificateUserEntity::getExpireTime,
                        FtbCertificateUserEntity::getEffectTime)
                .eq(FtbCertificateUserEntity::getUserId, userId)
                .in(FtbCertificateUserEntity::getCertificateId, certificateIds)
                .eq(FtbCertificateUserEntity::getEnabledMark, 1); // 有效标志为1表示有效

        List<FtbCertificateUserEntity> certificates = ftbCertificateUserMapper.selectList(queryWrapper);

        // 构建key为certificateId的映射
        Map<String, FtbCertificateUserEntity> resultMap = new HashMap<>();
        for (FtbCertificateUserEntity certificate : certificates) {
            resultMap.put(certificate.getCertificateId(), certificate);
        }

        return resultMap;
    }


    /**
     * 批量查询用户在指定技能中的状态（技能点数）
     *
     * @param userId   用户ID
     * @param skillIds 技能ID列表
     * @return 以技能ID为键，用户技能点数为值的映射表
     */
    @Override
    public Map<String, List<String>> batchQueryUserSkillStatus(String userId, List<String> skillIds) {
        if (CollUtil.isEmpty(skillIds)) {
            return new HashMap<>();
        }
        // 构建查询条件，查询用户在指定技能中的情况
        LambdaQueryWrapper<TeachingRecord> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(TeachingRecord::getId,
                        TeachingRecord::getSkillId,
                        TeachingRecord::getUserId,
                        TeachingRecord::getType)
                .eq(TeachingRecord::getUserId, userId)
                .in(TeachingRecord::getSkillId, skillIds)
                .eq(TeachingRecord::getType, 2)
                .eq(TeachingRecord::getDeleteMark, 0)
                .orderByDesc(TeachingRecord::getCreatorTime);

        // 查询并直接分组处理
        return teachingRecordMapper.selectList(queryWrapper).stream().collect(Collectors.groupingBy(TeachingRecord::getSkillId, Collectors.mapping(TeachingRecord::getId, Collectors.toList())));
    }

    /**
     * 检查一下 课程考试 鉴定 技能 证书是否存在且未删除
     *
     * @param req
     */
    @Override
    public void taskCheckAvailable(V2CultivateTaskSaveReq req) {
        if (CollUtil.isEmpty(req.getPhase())) {
            return;
        }
        // 收集所有需要检查的ID
        List<String> courseIds = new ArrayList<>();
        List<String> examIds = new ArrayList<>();
        List<String> identityIds = new ArrayList<>();
        List<String> practiceIds = new ArrayList<>();
        List<String> certificateIds = new ArrayList<>();

        for (V2CultivateLearnTaskPhaseVo phase : req.getPhase()) {
            // 检查课程
            if (phase.getCourseList() != null) {
                for (V2CultivateLearnTaskCourseVo course : phase.getCourseList()) {
                    if (course.getCourseId() != null) {
                        courseIds.add(course.getCourseId());
                    }
                }
            }

            // 检查考试
            if (phase.getExam() != null && phase.getExam().getExamId() != null) {
                examIds.add(phase.getExam().getExamId());
            }

            // 检查鉴定
            if (phase.getIdentification() != null && phase.getIdentification().getIdentityId() != null) {
                identityIds.add(phase.getIdentification().getIdentityId());
            }

            // 检查练习/技能
            if (phase.getPracticeList() != null) {
                for (V2CultivateLearnTaskPracticeVo practice : phase.getPracticeList()) {
                    if (practice.getBusinessId() != null) {
                        practiceIds.add(practice.getBusinessId());
                    }
                }
            }

            // 检查证书
            if (phase.getCertificate() != null && phase.getCertificate().getCertificateId() != null) {
                certificateIds.add(phase.getCertificate().getCertificateId());
            }
        }

        // 批量查询各类实体并验证是否存在及有效性
        checkCourse(courseIds);
        checkExam(examIds);
        checkIdentity(identityIds);
        checkPractice(practiceIds);
        checkCertificate(certificateIds);
    }

    private void checkPractice(List<String> practiceIds) {
        Map<String, TeachingSkill> practiceMap;
        if (CollUtil.isNotEmpty(practiceIds)) {
            List<TeachingSkill> practices = teachingSkillMapper.selectBatchIds(practiceIds);
            practiceMap = practices.stream().collect(Collectors.toMap(TeachingSkill::getId, item -> item));
            for (String practiceId : practiceIds) {
                TeachingSkill practice = practiceMap.get(practiceId);
                if (practice == null) {
                    throw new RuntimeException("技能【" + practiceId + "】不存在或已被删除");
                }
            }
        }
    }

    private void checkCertificate(List<String> certificateIds) {
        Map<String, FtbCertificateEntity> certificateMap;
        if (CollUtil.isNotEmpty(certificateIds)) {
            List<FtbCertificateEntity> certificates = ftbCultivateCertificateMapper.selectBatchIds(certificateIds);
            certificateMap = certificates.stream().collect(Collectors.toMap(FtbCertificateEntity::getId, item -> item));
            for (String certificateId : certificateIds) {
                FtbCertificateEntity certificate = certificateMap.get(certificateId);
                if (certificate == null || certificate.getEnabledMark() == null || certificate.getEnabledMark() == 0) {
                    throw new RuntimeException("证书【" + (certificate != null ? certificate.getName() : certificateId) + "】不存在或已被删除");
                }
            }
        }
    }

    private void checkIdentity(List<String> identityIds) {
        Map<String, CultivateIdentifyTable> identityMap;
        if (CollUtil.isNotEmpty(identityIds)) {
            List<CultivateIdentifyTable> identities = cultivateIdentifyTableService.listByIds(identityIds);
            identityMap = identities.stream().collect(Collectors.toMap(CultivateIdentifyTable::getId, item -> item));
            for (String identityId : identityIds) {
                CultivateIdentifyTable identity = identityMap.get(identityId);
                if (identity == null) {
                    throw new RuntimeException("鉴定【" + identityId + "】不存在或已被删除");
                }
            }
        }
    }

    private void checkExam(List<String> examIds) {
        Map<String, FtbCultivateExam> examMap;
        if (CollUtil.isNotEmpty(examIds)) {
            List<FtbCultivateExam> exams = ftbCultivateExamMapper.selectBatchIds(examIds);
            examMap = exams.stream().collect(Collectors.toMap(FtbCultivateExam::getId, item -> item));
            for (String examId : examIds) {
                FtbCultivateExam exam = examMap.get(examId);
                if (exam == null || exam.getEnabledMark() == 0) {
                    throw new RuntimeException("考试【" + (exam != null ? exam.getExamName() : examId) + "】不存在或已被删除");
                }
            }
        }
    }

    private void checkCourse(List<String> courseIds) {
        Map<String, FtbCultivateCourse> courseMap;
        if (CollUtil.isNotEmpty(courseIds)) {
            List<FtbCultivateCourse> courses = ftbCultivateCourseMapper.selectBatchIds(courseIds);
            courseMap = courses.stream().collect(Collectors.toMap(FtbCultivateCourse::getId, item -> item));
            for (String courseId : courseIds) {
                FtbCultivateCourse course = courseMap.get(courseId);
                if (course == null || course.getEnableMark() == 1 || course.getIsGroundIng() == 0) {
                    throw new RuntimeException("课程【" + (course != null ? course.getName() : courseId) + "】不存在或已被删除/下架");
                }
            }
        }
    }

    @Override
    public Map<String, FtbCultivatePositionCourceChapterLearning> batchQueryCourseChapterLearningState(String userId, List<String> chapterList) {

        Map<String, FtbCultivatePositionCourceChapterLearning> chapterLearningMap = new HashMap<>();
        LambdaQueryWrapper<FtbCultivatePositionCourceChapterLearning> queryChapterWrapper = Wrappers.lambdaQuery();
        queryChapterWrapper.in(FtbCultivatePositionCourceChapterLearning::getChapterId, chapterList)
                .eq(FtbCultivatePositionCourceChapterLearning::getUserId, userId)
                .eq(FtbCultivatePositionCourceChapterLearning::getEnabledMark, 0);
        List<FtbCultivatePositionCourceChapterLearning> list = chapterLearningService.list(queryChapterWrapper);
        if (CollUtil.isEmpty(list)) {
            return chapterLearningMap;
        }
        return list.stream().collect(Collectors.toMap(
                FtbCultivatePositionCourceChapterLearning::getChapterId,
                item -> item,
                (existing, replacement) -> replacement // 重复时直接覆盖，保留最后一条
        ));
    }


    /**
     * 检查入参的 课程、考试、鉴定、实践/练习 是否已经删除和下架
     *
     * @param ftbCultivatePosition 岗位学习对象
     */
    @Override
    public void positionCheckAvailable(FtbCultivatePositionSaveReq ftbCultivatePosition) {
        if (ftbCultivatePosition.getCourseList() == null || ftbCultivatePosition.getCourseList().isEmpty()) {
            return;
        }
        // 收集所有需要检查的ID
        List<String> courseIds = new ArrayList<>();
        List<String> examIds = new ArrayList<>();
        List<String> identityIds = new ArrayList<>();
        List<String> practiceIds = new ArrayList<>();
        List<String> certificateIds = new ArrayList<>();

        for (FtbCultivatePositionCourseReq courseReq : ftbCultivatePosition.getCourseList()) {
            // 收集课程ID
            if (courseReq.getCourseId() != null) {
                courseIds.add(courseReq.getCourseId());
            }

            // 收集考试ID
            if (courseReq.getExam() != null && courseReq.getExam().getExamId() != null) {
                examIds.add(courseReq.getExam().getExamId());
            }

            // 收集鉴定ID
            if (courseReq.getIdentity() != null && courseReq.getIdentity().getIdentityId() != null) {
                identityIds.add(courseReq.getIdentity().getIdentityId());
            }

            // 收集练习/实践ID
            if (courseReq.getPracticeList() != null) {
                for (FtbCultivatePositionCoursePracticeReq practiceReq : courseReq.getPracticeList()) {
                    if (practiceReq.getBusinessId() != null) {
                        practiceIds.add(practiceReq.getBusinessId());
                    }
                }
            }

            // 收集证书ID
            if (courseReq.getCertificate() != null && courseReq.getCertificate().getCertificateId() != null) {
                certificateIds.add(courseReq.getCertificate().getCertificateId());
            }
        }

        // 批量查询各类实体
        Map<String, FtbCultivateCourse> courseMap;
        checkCourse(courseIds);

        Map<String, FtbCultivateExam> examMap;
        checkExam(examIds);

        Map<String, CultivateIdentifyTable> identityMap;
        if (CollUtil.isNotEmpty(identityIds)) {
            List<CultivateIdentifyTable> identities = cultivateIdentifyTableService.listByIds(identityIds);
            identityMap = identities.stream().collect(Collectors.toMap(CultivateIdentifyTable::getId, item -> item));
            for (String identityId : identityIds) {
                CultivateIdentifyTable identity = identityMap.get(identityId);
                if (identity == null) {
                    throw new RuntimeException("添加了已经删除的鉴定表");
                }
            }
        }

        Map<String, TeachingSkill> practiceMap;
        if (CollUtil.isNotEmpty(practiceIds)) {
            List<TeachingSkill> practices = teachingSkillMapper.selectBatchIds(practiceIds);
            practiceMap = practices.stream().collect(Collectors.toMap(TeachingSkill::getId, item -> item));
            for (String practiceId : practiceIds) {
                TeachingSkill practice = practiceMap.get(practiceId);
                if (practice == null) {
                    throw new RuntimeException("添加了已经删除的技能");
                }
            }
        }

        Map<String, FtbCertificateEntity> certificateMap;
        checkCertificate(certificateIds);
    }

    /**
     * 批量查询课程学习人数
     *
     * @param courseIds 课程ID列表
     * @return 课程学习人数
     */
    @Override
    public Map<String, Long> batchQueryCourseLearningCount(List<String> courseIds) {
        if (CollUtil.isEmpty(courseIds)) {
            return new HashMap<>();
        }

        // 按课程ID分组并统计学习人数
        List<BatchCommonCountDto> groupedResult = ftbCultivatePositionCourceLearningMapper.countForCourseIds(courseIds);

        // 将结果转换为Map，按课程ID作为键，统计数量作为值
        Map<String, Long> courseLearningCountMap = new HashMap<>();
        if (CollUtil.isNotEmpty(groupedResult)) {
            courseLearningCountMap = groupedResult.stream().collect(Collectors.toMap(BatchCommonCountDto::getSelectKey, obj -> (long) obj.getNum(), (existing, replacement) -> existing // 如果有重复key，保留第一个值
            ));
        }

        return courseLearningCountMap;
    }

    /**
     * 批量查询岗位学习进度
     *
     * @param postList 岗位列表
     * @param userId   用户ID
     * @return 岗位学习进度
     */
    @Override
    public Map<String, PositionProgressVo> batchQueryPositionProgress(List<FtbCultivatePromotionPostNew> postList, String userId) {
        Set<String> postIds = new HashSet<>();
        for (FtbCultivatePromotionPostNew ftbCultivatePromotionPostNew : postList) {
            postIds.add(ftbCultivatePromotionPostNew.getPostId());
        }
        Map<String, PositionProgressVo> result = new HashMap<>();

        if (CollUtil.isEmpty(postIds)) {
            return result;
        }

        // 1. 查询岗位学习信息，获取岗位学习ID列表
        LambdaQueryWrapper<FtbCultivatePosition> positionQueryWrapper = Wrappers.lambdaQuery();
        positionQueryWrapper.select(FtbCultivatePosition::getId, FtbCultivatePosition::getPostId)
                .in(FtbCultivatePosition::getPostId, postIds)
                .eq(FtbCultivatePosition::getEnabledMark, 0); // 只查询有效的岗位
        List<FtbCultivatePosition> positions = ftbCultivatePositionMapper.selectList(positionQueryWrapper);

        if (CollUtil.isEmpty(positions)) {
            return result;
        }

        // 获取岗位学习ID列表
        List<String> positionLearnIds = positions.stream().map(FtbCultivatePosition::getId).collect(Collectors.toList());

        LambdaQueryWrapper<FtbCultivatePositionCourse> queryCourseWrapper = Wrappers.lambdaQuery();
        queryCourseWrapper.in(FtbCultivatePositionCourse::getPostLearnId, positionLearnIds);
        queryCourseWrapper.eq(FtbCultivatePositionCourse::getCompulsory, 0);
        queryCourseWrapper.eq(FtbCultivatePositionCourse::getEnabledMark, 0);
        List<FtbCultivatePositionCourse> courseList = ftbCultivatePositionCourseMapper.selectList(queryCourseWrapper);
        // 按照 postRankId 和 gradeId 字符串连接一次分组，gradeId为null时用"NULL"标识
        Map<String, List<FtbCultivatePositionCourse>> courseGroupMap = courseList.stream().collect(Collectors.groupingBy(item -> item.getPostRankId() + (item.getGradeId() == null ? "" : item.getGradeId())));

        LambdaQueryWrapper<FtbCultivatePositionCourseExam> queryCourseExamWrapper = Wrappers.lambdaQuery();
        queryCourseExamWrapper.in(FtbCultivatePositionCourseExam::getPostLearnId, positionLearnIds);
        queryCourseExamWrapper.eq(FtbCultivatePositionCourseExam::getEnabledMark, 0);
        List<FtbCultivatePositionCourseExam> exams = ftbCultivatePositionCourseExamMapper.selectList(queryCourseExamWrapper);
        // 按照 postRankId 和 gradeId 字符串连接一次分组，gradeId为null时用"NULL"标识
        Map<String, List<FtbCultivatePositionCourseExam>> examGroupMap = exams.stream().collect(Collectors.groupingBy(item -> item.getPostRankId() + (item.getGradeId() == null ? "" : item.getGradeId())));

        LambdaQueryWrapper<FtbCultivatePositionCourseIdentity> queryCourseIdentityWrapper = Wrappers.lambdaQuery();
        queryCourseIdentityWrapper.in(FtbCultivatePositionCourseIdentity::getPostLearnId, positionLearnIds);
        queryCourseIdentityWrapper.eq(FtbCultivatePositionCourseIdentity::getEnabledMark, 0);
        List<FtbCultivatePositionCourseIdentity> identities = ftbCultivatePositionCourseIdentityMapper.selectList(queryCourseIdentityWrapper);
        // 按照 postRankId 和 gradeId 字符串连接一次分组，gradeId为null时用"NULL"标识
        Map<String, List<FtbCultivatePositionCourseIdentity>> identityGroupMap = identities.stream().collect(Collectors.groupingBy(item -> item.getPostRankId() + (item.getGradeId() == null ? "" : item.getGradeId())));

        LambdaQueryWrapper<FtbCultivatePositionCoursePractice> queryCoursePracticesWrapper = Wrappers.lambdaQuery();
        queryCoursePracticesWrapper.in(FtbCultivatePositionCoursePractice::getPostLearnId, positionLearnIds);
        queryCoursePracticesWrapper.eq(FtbCultivatePositionCoursePractice::getEnabledMark, 0);
        List<FtbCultivatePositionCoursePractice> practices = ftbCultivatePositionCoursePracticeMapper.selectList(queryCoursePracticesWrapper);
        // 按照 postRankId 和 gradeId 字符串连接一次分组，gradeId为null时用"NULL"标识
        Map<String, List<FtbCultivatePositionCoursePractice>> practiceGroupMap = practices.stream().collect(Collectors.groupingBy(item -> item.getPostRankId() + (item.getGradeId() == null ? "" : item.getGradeId())));

        for (FtbCultivatePromotionPostNew postNew : postList) {
            PositionProgressVo vo = new PositionProgressVo();
            String key = postNew.getPostId() + (postNew.getGradeId() == null ? "" : postNew.getGradeId());

            List<FtbCultivatePositionCourse> itemCourseLists = courseGroupMap.get(key);
            if (CollUtil.isEmpty(itemCourseLists)) {
                itemCourseLists = new ArrayList<>();
            }
            List<FtbCultivatePositionCourseExam> itemCourseExamList = examGroupMap.get(key);
            if (CollUtil.isEmpty(itemCourseExamList)) {
                itemCourseExamList = new ArrayList<>();
            }
            List<FtbCultivatePositionCourseIdentity> itemCourseIdentityList = identityGroupMap.get(key);
            if (CollUtil.isEmpty(itemCourseIdentityList)) {
                itemCourseIdentityList = new ArrayList<>();
            }
            List<FtbCultivatePositionCoursePractice> itemCoursePracticeList = practiceGroupMap.get(key);
            if (CollUtil.isEmpty(itemCoursePracticeList)) {
                itemCoursePracticeList = new ArrayList<>();
            }
            Set<String> courseIds = itemCourseLists.stream().map(FtbCultivatePositionCourse::getCourseId).collect(Collectors.toSet());
            Set<String> courseExamIds = itemCourseExamList.stream().map(FtbCultivatePositionCourseExam::getExamId).collect(Collectors.toSet());
            Set<String> courseIdentityIds = itemCourseIdentityList.stream().map(FtbCultivatePositionCourseIdentity::getIdentityId).collect(Collectors.toSet());
            Set<String> coursePracticeIds = itemCoursePracticeList.stream().map(FtbCultivatePositionCoursePractice::getBusinessId).collect(Collectors.toSet());

            vo.setTotal(courseIds.size() + courseExamIds.size() + courseIdentityIds.size() + coursePracticeIds.size());
            vo.setCourseIds(courseIds);
            vo.setCourseExamIds(courseExamIds);
            vo.setCourseIdentityIds(courseIdentityIds);
            vo.setCoursePracticeIds(coursePracticeIds);
            //查询课程完成数量
            long courseCompleteNum = 0;
            if (CollUtil.isNotEmpty(courseIds)) {
                LambdaQueryWrapper<FtbCultivatePositionCourceLearning> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(FtbCultivatePositionCourceLearning::getUserId, userId)
                        .eq(FtbCultivatePositionCourceLearning::getState, 1)
                        .in(FtbCultivatePositionCourceLearning::getCourceId, courseIds)
                        .eq(FtbCultivatePositionCourceLearning::getEnabledMark, 0); // 有效标志为0表示有效

                courseCompleteNum = ftbCultivatePositionCourceLearningMapper.selectCount(queryWrapper);
            }
            // 构建查询条件，查询用户在指定考试中的情况
            long examCompleteNum = 0;
            if (CollUtil.isNotEmpty(courseExamIds)) {
                LambdaQueryWrapper<FtbCultivateExamUser> userExamWrapper = Wrappers.lambdaQuery();
                userExamWrapper.eq(FtbCultivateExamUser::getUserId, userId)
                        .ne(FtbCultivateExamUser::getStatus, List.of(0, 2))
                        .in(FtbCultivateExamUser::getExamId, courseExamIds)
                        .eq(FtbCultivateExamUser::getEnabledMark, 1); // 有效标志为1表示有效
                examCompleteNum = ftbCultivateExamUserMapper.selectCount(userExamWrapper);
            }
            //查询鉴定完成数量
            long identifyCompleteNum = 0;
            if (CollUtil.isNotEmpty(courseIdentityIds)) {
                // 使用 ftb_cultivate_identify_apply 和 ftb_cultivate_identify_apply_table_backups 关联查询
                identifyCompleteNum = cultivateIdentifyApplyMapper.countCompletedIdentifyByPost(
                        userId, 
                        courseIdentityIds, 
                        2,  // source: 岗位学习鉴定
                        itemCourseLists.get(0).getPostLearnId() // sourceId: 岗位ID
                );
            }
            //查询练习完成数量
            long practiceNum = 0;
            if (CollUtil.isNotEmpty(coursePracticeIds)) {
                LambdaQueryWrapper<TeachingRecord> queryTeachingWrapper = Wrappers.lambdaQuery();
                queryTeachingWrapper
                        .eq(TeachingRecord::getUserId, userId)
                        .in(TeachingRecord::getSkillId, coursePracticeIds)
                        .eq(TeachingRecord::getType, 2)
                        .eq(TeachingRecord::getDeleteMark, 0)
                        .orderByDesc(TeachingRecord::getCreatorTime);
                practiceNum = teachingRecordMapper.selectCount(queryTeachingWrapper);
            }
            vo.setComplete((int) (courseCompleteNum + examCompleteNum + practiceNum + identifyCompleteNum));
            result.put(postNew.getPostId(), vo);
        }
        return result;
    }

    private List<FtbCultivateCourseChapter> batchQueryCourseChapters(List<String> courseIds) {
        LambdaQueryWrapper<FtbCultivateCourseChapter> courseChapterWrapper = Wrappers.lambdaQuery();
        courseChapterWrapper.select(FtbCultivateCourseChapter::getId,
                        FtbCultivateCourseChapter::getCourseId,
                        FtbCultivateCourseChapter::getName,
                        FtbCultivateCourseChapter::getParentId,
                        FtbCultivateCourseChapter::getPath,
                        FtbCultivateCourseChapter::getSortCode)
                .in(FtbCultivateCourseChapter::getCourseId, courseIds)
                .eq(FtbCultivateCourseChapter::getEnableMark, 0);
        List<FtbCultivateCourseChapter> ftbCultivateCourseChapters = ftbCultivateCourseChapterMapper.selectList(courseChapterWrapper);
        if (CollUtil.isEmpty(ftbCultivateCourseChapters)) {
            return new ArrayList<>();
        }
        return ftbCultivateCourseChapters;
    }

    @Override
    public Map<String, List<V2ChapterVo>> batchQueryUserCourseChapterLearnStatus(String userId, List<String> courseIds) {
        if (CollUtil.isEmpty(courseIds)) {
            return new HashMap<>();
        }
        List<FtbCultivateCourseChapter> ftbCultivateCourseChapters = batchQueryCourseChapters(courseIds);
        if (CollUtil.isEmpty(ftbCultivateCourseChapters)) {
            return new HashMap<>();
        }
        //按照课程分组
        Map<String, List<FtbCultivateCourseChapter>> courseChapterMap = ftbCultivateCourseChapters.stream().collect(Collectors.groupingBy(FtbCultivateCourseChapter::getCourseId));


        List<FtbCultivatePositionCourceChapterLearning> courseLearnings = batchQueryCourseChapterLearning(userId, courseIds);
        Map<String, List<FtbCultivatePositionCourceChapterLearning>> courseLearningsMap = courseLearnings.stream().collect(Collectors.groupingBy(FtbCultivatePositionCourceChapterLearning::getCourceId));

        Map<String, List<V2ChapterVo>> ret = new HashMap<>();
        courseChapterMap.forEach((courseId, courseChapters) -> {
            List<V2ChapterVo> chapterVos = new ArrayList<>();
            List<FtbCultivatePositionCourceChapterLearning> chapterLearningList = courseLearningsMap.get(courseId);
            //转换成 章节map
            Map<String, FtbCultivatePositionCourceChapterLearning> chapterLearningMap = new HashMap<>();
            if (CollUtil.isNotEmpty(chapterLearningList)) {
                for (FtbCultivatePositionCourceChapterLearning chapterLearning : chapterLearningList) {
                    chapterLearningMap.put(chapterLearning.getChapterId(), chapterLearning);
                }
            }
            for (FtbCultivateCourseChapter courseChapter : courseChapters) {
                FtbCultivatePositionCourceChapterLearning chapterLearning = chapterLearningMap.get(courseChapter.getId());
                V2ChapterVo chapterVo = getV2ChapterVo(courseChapter, chapterLearning);
                chapterVos.add(chapterVo);
            }
            ret.put(courseId, chapterVos);
        });

        return ret;
    }


    @Override
    public Map<String, BigDecimal> batchQueryUserCourseLearnProgress(String userId, List<String> courseIds) {
        if (CollUtil.isEmpty(courseIds)) {
            return new HashMap<>();
        }
        List<FtbCultivateCourseChapter> ftbCultivateCourseChapters = batchQueryCourseChapters(courseIds);
        if (CollUtil.isEmpty(ftbCultivateCourseChapters)) {
            return new HashMap<>();
        }
        //按照课程分组
        Map<String, List<FtbCultivateCourseChapter>> courseChapterMap = ftbCultivateCourseChapters.stream().collect(Collectors.groupingBy(FtbCultivateCourseChapter::getCourseId));


        List<FtbCultivatePositionCourceChapterLearning> courseChapterLearnings = batchQueryCourseChapterLearning(userId, courseIds);
        Map<String, List<FtbCultivatePositionCourceChapterLearning>> courseLearningsMap = courseChapterLearnings.stream().collect(Collectors.groupingBy(FtbCultivatePositionCourceChapterLearning::getCourceId));
        Map<String, FtbCultivatePositionCourceLearning> courseLearnMap = batchQueryUserCourseLearnStatus(userId, courseIds);
        Map<String, BigDecimal> ret = new HashMap<>();
        courseChapterMap.forEach((courseId, courseChapters) -> {
            List<FtbCultivatePositionCourceChapterLearning> chapterLearningList = courseLearningsMap.get(courseId);
            if (CollUtil.isEmpty(chapterLearningList)) {
                ret.put(courseId, BigDecimal.ZERO);
                return;
            }
            FtbCultivatePositionCourceLearning ftbCultivatePositionCourceLearning = courseLearnMap.get(courseId);
            if(ftbCultivatePositionCourceLearning!=null && ftbCultivatePositionCourceLearning.getState()==1){
                ret.put(courseId, BigDecimal.ONE);
                return;
            }
            // 将已学习记录转换为 Map，key为章节ID
            Map<String, FtbCultivatePositionCourceChapterLearning> learningMap = new HashMap<>();
            if (CollUtil.isNotEmpty(chapterLearningList)) {
                for (FtbCultivatePositionCourceChapterLearning learning : chapterLearningList) {
                    learningMap.put(learning.getChapterId(), learning);
                }
            }

            // 计算进度：遍历所有需要学习的章节，检查是否在已学习记录中且状态为完成
            int totalChapters = courseChapters.size();
            long completedChapters = 0;

            completedChapters = courseChapters.stream()
                    .filter(chapter -> {
                        // 检查该章节是否有学习记录且状态为已完成（state=1）
                        FtbCultivatePositionCourceChapterLearning learning = learningMap.get(chapter.getId());
                        return learning != null && learning.getState() != null && learning.getState() == 1;
                    })
                    .count();

            // 计算进度百分比
            BigDecimal progress = new BigDecimal(completedChapters)
                    .divide(new BigDecimal(totalChapters), 4, RoundingMode.HALF_UP)
                    .setScale(2, RoundingMode.HALF_UP);
            ret.put(courseId, progress);

        });

        return ret;
    }


    @NotNull
    private static V2ChapterVo getV2ChapterVo(FtbCultivateCourseChapter courseChapter, FtbCultivatePositionCourceChapterLearning chapterLearning) {
        V2ChapterVo chapterVo = new V2ChapterVo();
        chapterVo.setId(courseChapter.getId());
        chapterVo.setParentId(courseChapter.getParentId());
        chapterVo.setPath(courseChapter.getPath());
        chapterVo.setChapterName(courseChapter.getName());
        chapterVo.setSortCode(courseChapter.getSortCode());
        chapterVo.setState(chapterLearning == null ? 0 : chapterLearning.getState());
        chapterVo.setChapterTime(chapterLearning == null ? 0 : chapterLearning.getChapterTime());
        return chapterVo;
    }

    private List<FtbCultivatePositionCourceChapterLearning> batchQueryCourseChapterLearning(String userId, List<String> courseIds) {
        LambdaQueryWrapper<FtbCultivatePositionCourceChapterLearning> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(FtbCultivatePositionCourceChapterLearning::getId,
                        FtbCultivatePositionCourceChapterLearning::getChapterId,
                        FtbCultivatePositionCourceChapterLearning::getUserId,
                        FtbCultivatePositionCourceChapterLearning::getCourceId,
                        FtbCultivatePositionCourceChapterLearning::getState,
                        FtbCultivatePositionCourceChapterLearning::getChapterTime)
                .eq(FtbCultivatePositionCourceChapterLearning::getUserId, userId)
                .in(FtbCultivatePositionCourceChapterLearning::getCourceId, courseIds)
                .eq(FtbCultivatePositionCourceChapterLearning::getEnabledMark, 0); // 有效标志为0表示有效
        List<FtbCultivatePositionCourceChapterLearning> courseLearnings = ftbCultivatePositionCourceChapterLearningMapper.selectList(queryWrapper);
        if (CollUtil.isEmpty(courseLearnings)) {
            return new ArrayList<>();
        }
        return courseLearnings;
    }

    /**
     * 根据用户ID查询所有已完成学习的课程ID列表
     *
     * @param userId 用户ID
     * @return 已完成课程ID列表
     */
    @Override
    public List<String> getUserCompletedCourseIds(String userId) {
        if (StringUtils.isEmpty(userId)) {
            return Collections.emptyList();
        }

        // 构建查询条件，查询用户在指定课程中的学习情况
        LambdaQueryWrapper<FtbCultivatePositionCourceLearning> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(FtbCultivatePositionCourceLearning::getId, FtbCultivatePositionCourceLearning::getUserId, FtbCultivatePositionCourceLearning::getCourceId, FtbCultivatePositionCourceLearning::getState, FtbCultivatePositionCourceLearning::getLearnTime).eq(FtbCultivatePositionCourceLearning::getUserId, userId).eq(FtbCultivatePositionCourceLearning::getState, 1).eq(FtbCultivatePositionCourceLearning::getEnabledMark, 0); // 有效标志为0表示有效

        List<FtbCultivatePositionCourceLearning> courseLearnings = ftbCultivatePositionCourceLearningMapper.selectList(queryWrapper);

        if (CollUtil.isEmpty(courseLearnings)) {
            return Collections.emptyList();
        }
        return courseLearnings.stream().map(FtbCultivatePositionCourceLearning::getCourceId).distinct().collect(Collectors.toList());
    }
}