package com.dora.service.impl;

import com.dora.dto.CourseCategoryDto;
import com.dora.dto.CourseDetailDto;
import com.dora.dto.CourseListItemDto;
import com.dora.dto.CourseUpdateDto;
import com.dora.dto.CourseVideoDetailDto;
import com.dora.dto.CourseVideoPlayDto;
import com.dora.dto.PageResultDto;
import com.dora.dto.CategoryDto;
import com.dora.dto.VodDto;
import com.dora.entity.Category;
import com.dora.entity.Course;
import com.dora.entity.CourseChapter;
import com.dora.entity.CourseVideo;
import com.dora.entity.User;
import com.dora.entity.Video;
import com.dora.exception.BusinessException;
import com.dora.mapper.CourseMapper;
import com.dora.mapper.CourseChapterMapper;
import com.dora.mapper.CourseLikeMapper;
import com.dora.mapper.CourseVideoMapper;
import com.dora.mapper.UserMapper;
import com.dora.mapper.VideoMapper;
import com.dora.service.CategoryService;
import com.dora.service.CourseService;
import com.dora.service.VodService;
import com.dora.service.VideoPermissionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 课程服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CourseServiceImpl implements CourseService {

    private final CourseMapper courseMapper;
    private final CourseChapterMapper courseChapterMapper;
    private final CourseVideoMapper courseVideoMapper;
    private final CourseLikeMapper courseLikeMapper;
    private final VideoMapper videoMapper;
    private final UserMapper userMapper;
    private final VodService vodService;
    private final VideoPermissionService videoPermissionService;
    private final CategoryService categoryService;

    @Override
    public List<CourseCategoryDto> getCategories() {
        try {
            // 构建分类DTO列表
            List<CourseCategoryDto> categories = new ArrayList<>();
            
            // 添加热门推荐（默认分类）
            CourseCategoryDto hotCategory = new CourseCategoryDto();
            hotCategory.setId("hot");
            hotCategory.setName("热门推荐");
            // 热门推荐的数量是所有已审核课程的总数
            Long totalCount = courseMapper.countAllCourses();
            hotCategory.setCount(totalCount != null ? totalCount.intValue() : 0);
            hotCategory.setIsDefault(true);
            categories.add(hotCategory);
            
            // 从新的category表获取课程分类
            List<CategoryDto> courseCategoryDtos = categoryService.getEnabledCategoriesByType(Category.TYPE_COURSE);
            
            // 转换为CourseCategoryDto并计算每个分类下的课程数量
            for (CategoryDto categoryDto : courseCategoryDtos) {
                CourseCategoryDto courseCategoryDto = new CourseCategoryDto();
                courseCategoryDto.setId(categoryDto.getId().toString()); // 使用分类ID作为字符串
                courseCategoryDto.setName(categoryDto.getName());
                courseCategoryDto.setIsDefault(false);
                
                // 查询该分类下的课程数量
                Long count = courseMapper.countCoursesByCategoryId(categoryDto.getId());
                courseCategoryDto.setCount(count != null ? count.intValue() : 0);
                
                // 只有有课程的分类才显示
                if (courseCategoryDto.getCount() > 0) {
                    categories.add(courseCategoryDto);
                }
            }
            
            // 按数量降序排序（热门推荐除外）
            categories.sort((c1, c2) -> {
                if ("hot".equals(c1.getId())) return -1;
                if ("hot".equals(c2.getId())) return 1;
                return Integer.compare(c2.getCount(), c1.getCount());
            });
            
            // 限制最多返回10个分类
            if (categories.size() > 10) {
                categories = categories.subList(0, 10);
                log.info("课程分类数量超过10个，已限制为前10个分类");
            }
            
            return categories;
        } catch (Exception e) {
            log.error("获取课程分类列表失败", e);
            throw new BusinessException("获取课程分类列表失败");
        }
    }

    @Override
    public PageResultDto<CourseListItemDto> getHotCourses(int page, int size) {
        try {
            int offset = (page - 1) * size;
            
            // 获取热门课程列表
            List<Course> courses = courseMapper.selectHotCourses(offset, size);
            Long total = courseMapper.countAllCourses();
            
            // 转换为DTO
            List<CourseListItemDto> courseDtos = convertToCourseListDto(courses);
            
            return new PageResultDto<>(total, (long) page, (long) size, courseDtos);
        } catch (Exception e) {
            log.error("获取热门课程列表失败", e);
            throw new BusinessException("获取热门课程列表失败");
        }
    }

    @Override
    public PageResultDto<CourseListItemDto> getCoursesByCategory(String category, int page, int size) {
        try {
            int offset = (page - 1) * size;
            
            // 获取指定分类的课程列表
            List<Course> courses = courseMapper.selectCoursesByCategory(category, offset, size);
            Long total = courseMapper.countCoursesByCategory(category);
            
            // 转换为DTO
            List<CourseListItemDto> courseDtos = convertToCourseListDto(courses);
            
            return new PageResultDto<>(total, (long) page, (long) size, courseDtos, category);
        } catch (Exception e) {
            log.error("获取分类课程列表失败 - category: {}", category, e);
            throw new BusinessException("获取分类课程列表失败");
        }
    }

    @Override
    public Course getCourseById(Long id) {
        try {
            Course course = courseMapper.selectApprovedById(id);
            if (course == null) {
                throw new BusinessException("课程不存在或未通过审核");
            }
            return course;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("获取课程详情失败 - id: {}", id, e);
            throw new BusinessException("获取课程详情失败");
        }
    }

    @Override
    public CourseDetailDto getCourseDetail(Long id, Long userId) {
        try {
            // 获取课程信息（不过滤审核状态）
            Course course = courseMapper.selectById(id);
            if (course == null) {
                throw new BusinessException("课程不存在");
            }

            // 检查课程审核状态 - 只有通过审核或者是创作者本人可以查看
            if (course.getAuditStatus() != 1 && (userId == null || !userId.equals(course.getUserId()))) {
                throw new BusinessException("课程不存在或未通过审核");
            }

            return buildCourseDetailDto(course);
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("获取课程详情失败 - id: {}, userId: {}", id, userId, e);
            throw new BusinessException("获取课程详情失败");
        }
    }

    /**
     * 内部使用：获取课程详情（不过滤审核状态）
     */
    private CourseDetailDto getCourseDetailInternal(Long id) {
        try {
            Course course = courseMapper.selectById(id);
            if (course == null) {
                throw new BusinessException("课程不存在");
            }
            return buildCourseDetailDto(course);
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("获取课程详情失败 - id: {}", id, e);
            throw new BusinessException("获取课程详情失败");
        }
    }

    /**
     * 构建课程详情DTO
     */
    private CourseDetailDto buildCourseDetailDto(Course course) {
        CourseDetailDto detail = new CourseDetailDto();
        detail.setId(course.getId());
        detail.setTitle(valueOrEmpty(course.getTitle()));
        detail.setDescription(valueOrEmpty(course.getDescription()));
        detail.setCoverUrl(course.getCoverUrl());
        detail.setDetailGallery(course.getDetailGallery());
        detail.setPrice(course.getPrice());
        detail.setLevel(course.getLevel());
        detail.setCategory(course.getCategory());
        detail.setIsFree(course.getIsFree() != null && course.getIsFree() == 1);
        detail.setCreateTime(course.getCreateTime());
        detail.setUpdateTime(course.getUpdateTime());

        // 创建者信息（用户ID转字符串返回）
        if (course.getUserId() != null) {
            User creator = userMapper.selectById(course.getUserId());
            if (creator != null) {
                CourseDetailDto.CreatorDto creatorDto = new CourseDetailDto.CreatorDto();
                creatorDto.setId(String.valueOf(creator.getId()));
                creatorDto.setUsername(creator.getUsername());
                creatorDto.setAvatarUrl(creator.getAvatarUrl());
                detail.setCreator(creatorDto);
            }
        }

        // 查询章节
        List<CourseChapter> chapters = courseChapterMapper.selectByCourseId(course.getId());
        if (chapters == null || chapters.isEmpty()) {
            detail.setChapters(new ArrayList<>());
            return detail;
        }

        // 组装章节DTO映射
        Map<Long, CourseDetailDto.ChapterDto> chapterIdToDto = new LinkedHashMap<>();
        for (CourseChapter chapter : chapters) {
            CourseDetailDto.ChapterDto cd = new CourseDetailDto.ChapterDto();
            cd.setId(chapter.getId());
            cd.setTitle(valueOrEmpty(chapter.getTitle()));
            cd.setDescription(valueOrEmpty(chapter.getDescription()));
            cd.setOrderNum(chapter.getOrderNum());
            cd.setVideos(new ArrayList<>());
            chapterIdToDto.put(chapter.getId(), cd);
        }

        // 批量查询视频
        List<Long> chapterIds = new ArrayList<>(chapterIdToDto.keySet());
        if (!chapterIds.isEmpty()) {
            List<CourseVideo> videos = courseVideoMapper.selectByChapterIds(chapterIds);
            if (videos != null && !videos.isEmpty()) {
                // 批量查询Video获取阿里云VOD视频ID
                List<Long> videoPkIds = videos.stream()
                        .map(CourseVideo::getVideoId)
                        .filter(Objects::nonNull)
                        .distinct()
                        .collect(Collectors.toList());
                Map<Long, Video> videoMap = Collections.emptyMap();
                if (!videoPkIds.isEmpty()) {
                    List<Video> videoEntities = videoMapper.selectByIds(videoPkIds);
                    videoMap = videoEntities.stream().collect(Collectors.toMap(Video::getId, v -> v, (a,b)->a));
                }
                for (CourseVideo v : videos) {
                    CourseDetailDto.VideoDto vd = new CourseDetailDto.VideoDto();
                    vd.setId(v.getId());
                    vd.setChapterId(v.getChapterId());
                    vd.setTitle(valueOrEmpty(v.getTitle()));
                    // 设置阿里云VOD视频ID（字符串）
                    String vodId = null;
                    if (v.getVideoId() != null) {
                        Video ve = videoMap.get(v.getVideoId());
                        if (ve != null) {
                            vodId = ve.getVodVideoId();
                        }
                    }
                    vd.setVideoId(vodId);
                    vd.setDurationSec(v.getDurationSec());
                    vd.setOrderNum(v.getOrderNum());

                    CourseDetailDto.ChapterDto parent = chapterIdToDto.get(v.getChapterId());
                    if (parent != null) {
                        parent.getVideos().add(vd);
                    }
                }
            }
        }

        // 设置章节列表，保持原有顺序
        detail.setChapters(new ArrayList<>(chapterIdToDto.values()));
        return detail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CourseDetailDto updateCourse(Long courseId, Long userId, CourseUpdateDto updateDto) {
        try {
            // 1. 验证课程存在性和权限
            Course course = courseMapper.selectById(courseId);
            if (course == null) {
                throw new BusinessException("课程不存在");
            }
            if (!Objects.equals(course.getUserId(), userId)) {
                throw new BusinessException("无权限修改此课程");
            }

            // 2. 更新课程基本信息
            boolean hasStructuralChanges = updateCourseBasicInfo(course, updateDto);

            // 3. 处理章节和视频更新
            if (updateDto.getChapters() != null) {
                hasStructuralChanges = updateChaptersAndVideos(courseId, updateDto.getChapters(), userId) || hasStructuralChanges;
            }

            // 4. 处理删除缺失的章节和视频
            if (Boolean.TRUE.equals(updateDto.getDeleteMissing())) {
                deleteMissingChaptersAndVideos(courseId, updateDto.getChapters());
            }

            // 5. 无条件重置审核状态（业务要求：更新完就要重新审核）
            courseMapper.submitForAudit(courseId, userId, course.getTitle(), course.getDescription(), course.getIsFree(), course.getLevel());
            log.info("课程 {} 更新后已重置为待审核状态", courseId);

            // 6. 返回更新后的课程详情（内部调用，不过滤审核状态）
            return getCourseDetailInternal(courseId);
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新课程失败 - courseId: {}, userId: {}", courseId, userId, e);
            throw new BusinessException("更新课程失败");
        }
    }

    /**
     * 更新课程基本信息
     */
    private boolean updateCourseBasicInfo(Course course, CourseUpdateDto updateDto) {
        boolean hasChanges = false;
        
        if (updateDto.getTitle() != null && !updateDto.getTitle().equals(course.getTitle())) {
            course.setTitle(updateDto.getTitle());
            hasChanges = true;
        }
        if (updateDto.getDescription() != null && !updateDto.getDescription().equals(course.getDescription())) {
            course.setDescription(updateDto.getDescription());
            hasChanges = true;
        }
        if (updateDto.getCoverUrl() != null && !updateDto.getCoverUrl().equals(course.getCoverUrl())) {
            course.setCoverUrl(updateDto.getCoverUrl());
            hasChanges = true;
        }
        if (updateDto.getDetailGallery() != null && !updateDto.getDetailGallery().equals(course.getDetailGallery())) {
            course.setDetailGallery(updateDto.getDetailGallery());
            hasChanges = true;
        }
        if (updateDto.getPrice() != null && !updateDto.getPrice().equals(course.getPrice())) {
            course.setPrice(updateDto.getPrice());
            hasChanges = true;
        }
        if (updateDto.getLevel() != null && !updateDto.getLevel().equals(course.getLevel())) {
            course.setLevel(updateDto.getLevel());
            hasChanges = true;
        }
        if (updateDto.getCategory() != null && !updateDto.getCategory().equals(course.getCategory())) {
            course.setCategory(updateDto.getCategory());
            hasChanges = true;
        }
        if (updateDto.getIsFree() != null) {
            Integer newIsFree = updateDto.getIsFree() ? 1 : 0;
            if (!newIsFree.equals(course.getIsFree())) {
                course.setIsFree(newIsFree);
                hasChanges = true;
            }
        }

        if (hasChanges) {
            courseMapper.updateById(course);
        }
        
        return hasChanges;
    }

    /**
     * 更新章节和视频
     */
    private boolean updateChaptersAndVideos(Long courseId, List<CourseUpdateDto.ChapterUpdateDto> chapterDtos, Long userId) {
        boolean hasStructuralChanges = false;
        
        for (int i = 0; i < chapterDtos.size(); i++) {
            CourseUpdateDto.ChapterUpdateDto chapterDto = chapterDtos.get(i);
            
            // 设置章节排序号（如果未提供）
            if (chapterDto.getOrderNum() == null) {
                chapterDto.setOrderNum(i + 1);
            }
            
            CourseChapter chapter;
            if (chapterDto.getId() != null) {
                // 更新现有章节
                chapter = updateExistingChapter(chapterDto);
            } else {
                // 创建新章节
                chapter = createNewChapter(courseId, chapterDto);
                hasStructuralChanges = true;
            }
            
            // 处理视频
            if (chapterDto.getVideos() != null) {
                boolean videoChanges = updateVideosInChapter(chapter.getId(), chapterDto.getVideos(), userId);
                hasStructuralChanges = videoChanges || hasStructuralChanges;
            }
        }
        
        return hasStructuralChanges;
    }

    /**
     * 更新现有章节
     */
    private CourseChapter updateExistingChapter(CourseUpdateDto.ChapterUpdateDto chapterDto) {
        CourseChapter chapter = new CourseChapter();
        chapter.setId(chapterDto.getId());
        chapter.setTitle(chapterDto.getTitle());
        chapter.setDescription(chapterDto.getDescription());
        chapter.setOrderNum(chapterDto.getOrderNum());
        
        courseChapterMapper.updateById(chapter);
        return chapter;
    }

    /**
     * 创建新章节
     */
    private CourseChapter createNewChapter(Long courseId, CourseUpdateDto.ChapterUpdateDto chapterDto) {
        CourseChapter chapter = new CourseChapter();
        chapter.setCourseId(courseId);
        chapter.setTitle(chapterDto.getTitle());
        chapter.setDescription(chapterDto.getDescription());
        chapter.setOrderNum(chapterDto.getOrderNum());
        
        courseChapterMapper.insert(chapter);
        return chapter;
    }

    /**
     * 更新章节内的视频
     */
    private boolean updateVideosInChapter(Long chapterId, List<CourseUpdateDto.VideoUpdateDto> videoDtos, Long userId) {
        boolean hasChanges = false;
        
        for (int i = 0; i < videoDtos.size(); i++) {
            CourseUpdateDto.VideoUpdateDto videoDto = videoDtos.get(i);
            
            // 设置视频排序号（如果未提供）
            if (videoDto.getOrderNum() == null) {
                videoDto.setOrderNum(i + 1);
            }
            
            // 验证视频信息
            validateVideoDto(videoDto);
            
            if (videoDto.getId() != null) {
                // 更新现有视频
                updateExistingVideo(chapterId, videoDto, userId);
            } else {
                // 创建新视频
                createNewVideo(chapterId, videoDto, userId);
                hasChanges = true;
            }
        }
        
        return hasChanges;
    }

    /**
     * 验证视频DTO
     */
    private void validateVideoDto(CourseUpdateDto.VideoUpdateDto videoDto) {
        if (videoDto.getVideoId() == null && videoDto.getVodVideoId() == null) {
            throw new BusinessException("视频必须提供videoId或vodVideoId");
        }
        if (videoDto.getVideoId() != null && videoDto.getVodVideoId() != null) {
            throw new BusinessException("videoId和vodVideoId不能同时提供");
        }
    }

    /**
     * 将传入的视频绑定参数解析为Video主键ID：
     * - 如果提供的是数字字符串，按video主键处理
     * - 如果提供的是非数字字符串，按vodVideoId处理（自动创建或复用Video）
     */
    private Long resolveVideoPrimaryId(CourseUpdateDto.VideoUpdateDto videoDto, Long userId) {
        if (videoDto.getVideoId() != null) {
            String raw = videoDto.getVideoId().trim();
            if (raw.matches("^\\d+$")) {
                return Long.parseLong(raw);
            }
            return getOrCreateVideoByVodId(raw, userId);
        }
        return getOrCreateVideoByVodId(videoDto.getVodVideoId(), userId);
    }

    /**
     * 更新现有视频
     */
    private CourseVideo updateExistingVideo(Long chapterId, CourseUpdateDto.VideoUpdateDto videoDto, Long userId) {
        CourseVideo video = new CourseVideo();
        video.setId(videoDto.getId());
        video.setTitle(videoDto.getTitle());
        video.setOrderNum(videoDto.getOrderNum());
        video.setDurationSec(videoDto.getDurationSec());

        // 统一解析并设置video主键
        Long resolvedVideoId = resolveVideoPrimaryId(videoDto, userId);
        video.setVideoId(resolvedVideoId);

        courseVideoMapper.updateById(video);
        return video;
    }

    /**
     * 创建新视频
     */
    private CourseVideo createNewVideo(Long chapterId, CourseUpdateDto.VideoUpdateDto videoDto, Long userId) {
        CourseVideo video = new CourseVideo();
        video.setChapterId(chapterId);
        video.setTitle(videoDto.getTitle());
        video.setOrderNum(videoDto.getOrderNum());
        video.setDurationSec(videoDto.getDurationSec());

        // 统一解析并设置video主键
        Long resolvedVideoId = resolveVideoPrimaryId(videoDto, userId);
        video.setVideoId(resolvedVideoId);

        courseVideoMapper.insert(video);
        return video;
    }

    /**
     * 根据VOD视频ID获取或创建Video记录
     */
    private Long getOrCreateVideoByVodId(String vodVideoId, Long userId) {
        // 先查找是否已存在
        Video existingVideo = videoMapper.selectByVodVideoId(vodVideoId);
        if (existingVideo != null) {
            // 验证权限
            if (!Objects.equals(existingVideo.getOwnerId(), userId)) {
                throw new BusinessException("无权使用此视频资源");
            }
            return existingVideo.getId();
        }
        
        // 创建新的Video记录
        Video newVideo = new Video();
        newVideo.setOwnerId(userId);
        newVideo.setVodVideoId(vodVideoId);
        newVideo.setTitle("课程视频");
        newVideo.setIsPublic(0); // 0表示不公开
        newVideo.setAuditStatus(0); // 待审核
        
        videoMapper.insert(newVideo);
        return newVideo.getId();
    }

    /**
     * 删除缺失的章节和视频
     */
    private void deleteMissingChaptersAndVideos(Long courseId, List<CourseUpdateDto.ChapterUpdateDto> chapterDtos) {
        if (chapterDtos == null) {
            return;
        }
        
        // 收集提交的章节ID
        Set<Long> submittedChapterIds = chapterDtos.stream()
                .map(CourseUpdateDto.ChapterUpdateDto::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        
        // 收集提交的视频ID
        Set<Long> submittedVideoIds = new HashSet<>();
        for (CourseUpdateDto.ChapterUpdateDto chapterDto : chapterDtos) {
            if (chapterDto.getVideos() != null) {
                submittedVideoIds.addAll(chapterDto.getVideos().stream()
                        .map(CourseUpdateDto.VideoUpdateDto::getId)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet()));
            }
        }
        
        // 获取现有的章节和视频
        List<CourseChapter> existingChapters = courseChapterMapper.selectByCourseId(courseId);
        List<Long> existingChapterIds = existingChapters.stream()
                .map(CourseChapter::getId)
                .collect(Collectors.toList());
        
        List<CourseVideo> existingVideos = courseVideoMapper.selectByChapterIds(existingChapterIds);
        List<Long> existingVideoIds = existingVideos.stream()
                .map(CourseVideo::getId)
                .collect(Collectors.toList());
        
        // 删除缺失的章节
        for (Long chapterId : existingChapterIds) {
            if (!submittedChapterIds.contains(chapterId)) {
                courseChapterMapper.softDelete(chapterId, courseId);
                log.info("软删除章节: {}", chapterId);
            }
        }
        
        // 删除缺失的视频
        for (Long videoId : existingVideoIds) {
            if (!submittedVideoIds.contains(videoId)) {
                CourseVideo video = existingVideos.stream()
                        .filter(v -> Objects.equals(v.getId(), videoId))
                        .findFirst()
                        .orElse(null);
                if (video != null) {
                    courseVideoMapper.softDelete(videoId, video.getChapterId());
                    log.info("软删除视频: {}", videoId);
                }
            }
        }
    }

    private String valueOrEmpty(String s) {
        return s == null ? "" : s;
    }

    /**
     * 将Course实体转换为CourseListItemDto
     */
    private List<CourseListItemDto> convertToCourseListDto(List<Course> courses) {
        if (courses == null || courses.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 获取所有创建者ID
        List<Long> creatorIds = courses.stream()
                .map(Course::getUserId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        
        // 批量获取创建者信息
        final Map<Long, User> userMap;
        if (!creatorIds.isEmpty()) {
            List<User> users = userMapper.selectByIds(creatorIds);
            userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user, (existing, replacement) -> existing));
        } else {
            userMap = new HashMap<>();
        }
        
        return courses.stream().map(course -> {
            CourseListItemDto dto = new CourseListItemDto();
            
            // 基本信息
            dto.setId(course.getId());
            dto.setTitle(course.getTitle() != null ? course.getTitle() : "");
            dto.setDescription(course.getDescription() != null ? course.getDescription() : "");
            dto.setCoverUrl(course.getCoverUrl());
            dto.setPrice(course.getPrice());
            dto.setLevel(course.getLevel() != null ? course.getLevel() : 0);
            dto.setCategory(course.getCategory());
            dto.setCreateTime(course.getCreateTime());
            dto.setUpdateTime(course.getUpdateTime());
            
            // 从数据库获取真实数据
            // 计算课程总时长
            Integer totalDurationSec = courseVideoMapper.sumDurationByCourseId(course.getId());
            dto.setDuration(formatDuration(totalDurationSec != null ? totalDurationSec : 0));
            
            // 获取课程观看数（来自视频观看统计）
            Integer viewCount = videoMapper.sumViewCountByCourseId(course.getId());
            dto.setViewCount(viewCount != null ? viewCount : 0);
            
            // 获取课程点赞数
            int likeCount = courseLikeMapper.countByCourseId(course.getId());
            dto.setLikeCount(likeCount);
            
            // 评论数暂时设为0（数据库中没有评论表）
            dto.setCommentCount(0);
            dto.setIsFree(course.getIsFree() != null && course.getIsFree() == 1);
            dto.setVipType(getVipType(course.getLevel()));
            
            // 设置创建者信息
            if (course.getUserId() != null) {
                User creator = userMap.get(course.getUserId());
                if (creator != null) {
                    CourseListItemDto.CreatorDto creatorDto = new CourseListItemDto.CreatorDto();
                    creatorDto.setId(String.valueOf(creator.getId()));
                    creatorDto.setUsername(creator.getUsername() != null ? creator.getUsername() : "");
                    creatorDto.setAvatarUrl(creator.getAvatarUrl());
                    dto.setCreator(creatorDto);
                }
            }
            
            return dto;
        }).collect(Collectors.toList());
    }

    /**
     * 根据课程级别获取VIP类型
     * @deprecated 使用 CoursePermissionUtil.getVipType() 替代，确保全局一致性
     */
    @Deprecated
    private String getVipType(Integer level) {
        return com.dora.util.CoursePermissionUtil.getVipType(level);
    }

    @Override
    public CourseVideoDetailDto getCourseVideoDetail(Long courseId, Long userId) {
        try {
            // 获取课程信息（不过滤审核状态）
            Course course = courseMapper.selectById(courseId);
            if (course == null) {
                throw new BusinessException("课程不存在");
            }

            // 检查课程审核状态 - 只有通过审核或者是创作者本人可以查看
            if (course.getAuditStatus() != 1 && (userId == null || !userId.equals(course.getUserId()))) {
                throw new BusinessException("课程不存在或未通过审核");
            }

            CourseVideoDetailDto result = new CourseVideoDetailDto();

            // 设置课程基本信息
            result.setCourse(buildCourseInfo(course));

            // 设置章节和视频信息
            result.setChapters(buildChapterInfoList(course.getId(), userId, course.getLevel()));

            // 设置用户权限信息
            result.setUserPermission(buildUserPermission(userId, course.getLevel()));

            return result;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("获取课程视频详情失败 - courseId: {}, userId: {}", courseId, userId, e);
            throw new BusinessException("获取课程视频详情失败");
        }
    }

    @Override
    public CourseVideoPlayDto.PlayAuthResponse getCourseVideoPlayAuth(CourseVideoPlayDto.GetPlayAuthRequest request, Long userId) {
        try {
            // 验证用户权限
            if (!videoPermissionService.hasCourseVideoPermission(userId, request.getCourseId(), request.getChapterId())) {
                User user = userMapper.selectById(userId);
                Course course = courseMapper.selectById(request.getCourseId());
                
                String userRoleName = getRoleNameByLevel(user != null ? user.getRole() : 0);
                String requiredRoleName = getRoleNameByLevel(course != null ? course.getLevel() : 1);
                
                throw new BusinessException(String.format("权限不足：您当前是%s用户，该课程需要%s及以上权限", userRoleName, requiredRoleName));
            }

            // 获取视频信息
            CourseVideo courseVideo = courseVideoMapper.selectById(request.getVideoId());
            if (courseVideo == null) {
                throw new BusinessException("视频不存在");
            }

            // 验证章节关系
            if (!courseVideo.getChapterId().equals(request.getChapterId())) {
                throw new BusinessException("视频与章节不匹配");
            }

            // 获取对应的Video记录
            Video video = videoMapper.selectById(courseVideo.getVideoId());
            if (video == null || video.getVodVideoId() == null) {
                throw new BusinessException("视频资源不存在");
            }

            // 调用VOD服务获取播放凭证
            VodDto.GetVideoPlayAuthRequest vodRequest = new VodDto.GetVideoPlayAuthRequest();
            vodRequest.setVideoId(video.getVodVideoId());
            vodRequest.setCourseId(request.getCourseId());
            vodRequest.setChapterId(request.getChapterId());
            vodRequest.setAuthInfoTimeout(request.getAuthInfoTimeout());

            VodDto.VideoPlayAuthResponse vodResponse = vodService.getVideoPlayAuth(vodRequest, userId);

            // 构建响应
            CourseVideoPlayDto.PlayAuthResponse response = new CourseVideoPlayDto.PlayAuthResponse();
            response.setPlayAuth(vodResponse.getPlayAuth());
            response.setRequestId(vodResponse.getRequestId());

            // 设置视频元信息
            CourseVideoPlayDto.VideoMeta videoMeta = new CourseVideoPlayDto.VideoMeta();
            if (vodResponse.getVideoMeta() != null) {
                videoMeta.setVodVideoId(vodResponse.getVideoMeta().getVideoId());
                videoMeta.setTitle(courseVideo.getTitle());
                videoMeta.setDuration(vodResponse.getVideoMeta().getDuration());
                videoMeta.setCoverURL(vodResponse.getVideoMeta().getCoverURL());
                videoMeta.setStatus(vodResponse.getVideoMeta().getStatus());
                videoMeta.setSize(vodResponse.getVideoMeta().getSize());
            }
            response.setVideoMeta(videoMeta);

            // 设置用户权限信息
            User user = userMapper.selectById(userId);
            Course course = courseMapper.selectById(request.getCourseId());
            CourseVideoPlayDto.UserPermissionInfo permissionInfo = new CourseVideoPlayDto.UserPermissionInfo();
            permissionInfo.setUserRole(user != null ? user.getRole() : 0);
            permissionInfo.setUserRoleName(getRoleNameByLevel(user != null ? user.getRole() : 0));
            permissionInfo.setRequiredLevel(course != null ? course.getLevel() : 1);
            permissionInfo.setHasPermission(true);
            permissionInfo.setCheckTime(java.time.LocalDateTime.now());
            response.setUserPermission(permissionInfo);

            return response;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("获取课程视频播放凭证失败 - request: {}, userId: {}", request, userId, e);
            throw new BusinessException("获取播放凭证失败: " + e.getMessage());
        }
    }

    /**
     * 构建课程基本信息
     */
    private CourseVideoDetailDto.CourseInfo buildCourseInfo(Course course) {
        CourseVideoDetailDto.CourseInfo courseInfo = new CourseVideoDetailDto.CourseInfo();
        courseInfo.setId(course.getId());
        courseInfo.setTitle(valueOrEmpty(course.getTitle()));
        courseInfo.setDescription(valueOrEmpty(course.getDescription()));
        courseInfo.setCoverUrl(course.getCoverUrl());
        courseInfo.setDetailGallery(course.getDetailGallery());
        courseInfo.setPrice(course.getPrice());
        courseInfo.setLevel(course.getLevel());
        courseInfo.setCategory(course.getCategory());
        courseInfo.setIsFree(course.getIsFree() != null && course.getIsFree() == 1);
        courseInfo.setLevelName(getRoleNameByLevel(course.getLevel()));
        courseInfo.setCreateTime(course.getCreateTime());
        courseInfo.setUpdateTime(course.getUpdateTime());

        // 计算并设置总观看次数
        Integer totalViewCount = videoMapper.sumViewCountByCourseId(course.getId());
        courseInfo.setViewCount(totalViewCount != null ? totalViewCount : 0);

        // 设置创建者信息
        if (course.getUserId() != null) {
            User creator = userMapper.selectById(course.getUserId());
            if (creator != null) {
                CourseVideoDetailDto.CreatorInfo creatorInfo = new CourseVideoDetailDto.CreatorInfo();
                creatorInfo.setId(String.valueOf(creator.getId()));
                creatorInfo.setUsername(creator.getUsername());
                creatorInfo.setAvatarUrl(creator.getAvatarUrl());
                courseInfo.setCreator(creatorInfo);
            }
        }

        return courseInfo;
    }

    /**
     * 构建章节信息列表
     */
    private List<CourseVideoDetailDto.ChapterInfo> buildChapterInfoList(Long courseId, Long userId, Integer courseLevel) {
        List<CourseChapter> chapters = courseChapterMapper.selectByCourseId(courseId);
        if (chapters == null || chapters.isEmpty()) {
            return new ArrayList<>();
        }

        List<CourseVideoDetailDto.ChapterInfo> chapterInfoList = new ArrayList<>();
        
        // 获取用户权限信息
        User user = null;
        boolean hasAccess = false;
        if (userId != null) {
            user = userMapper.selectById(userId);
            hasAccess = user != null && user.getRole() >= courseLevel;
        }

        for (CourseChapter chapter : chapters) {
            CourseVideoDetailDto.ChapterInfo chapterInfo = new CourseVideoDetailDto.ChapterInfo();
            chapterInfo.setId(chapter.getId());
            chapterInfo.setTitle(valueOrEmpty(chapter.getTitle()));
            chapterInfo.setDescription(valueOrEmpty(chapter.getDescription()));
            chapterInfo.setOrderNum(chapter.getOrderNum());

            // 获取章节下的视频
            List<CourseVideo> videos = courseVideoMapper.selectByChapterIds(List.of(chapter.getId()));
            List<CourseVideoDetailDto.VideoInfo> videoInfoList = buildVideoInfoList(videos, hasAccess, courseLevel);
            chapterInfo.setVideos(videoInfoList);

            chapterInfoList.add(chapterInfo);
        }

        return chapterInfoList;
    }

    /**
     * 构建视频信息列表
     */
    private List<CourseVideoDetailDto.VideoInfo> buildVideoInfoList(List<CourseVideo> videos, boolean hasAccess, Integer courseLevel) {
        if (videos == null || videos.isEmpty()) {
            return new ArrayList<>();
        }

        List<CourseVideoDetailDto.VideoInfo> videoInfoList = new ArrayList<>();

        for (CourseVideo video : videos) {
            CourseVideoDetailDto.VideoInfo videoInfo = new CourseVideoDetailDto.VideoInfo();
            videoInfo.setId(video.getId());
            videoInfo.setChapterId(video.getChapterId());
            videoInfo.setTitle(valueOrEmpty(video.getTitle()));
            videoInfo.setDurationSec(video.getDurationSec());
            videoInfo.setDurationFormatted(formatDuration(video.getDurationSec()));
            videoInfo.setOrderNum(video.getOrderNum());

            // 获取VOD视频ID和封面URL
            if (video.getVideoId() != null) {
                Video vodVideo = videoMapper.selectById(video.getVideoId());
                if (vodVideo != null) {
                    videoInfo.setVodVideoId(vodVideo.getVodVideoId());
                    videoInfo.setCoverUrl(vodVideo.getCoverUrl());
                }
            }

            // 设置播放权限
            videoInfo.setCanPlay(hasAccess);
            if (!hasAccess) {
                String requiredRoleName = getRoleNameByLevel(courseLevel);
                videoInfo.setLockReason("需要" + requiredRoleName + "及以上权限");
            }

            videoInfoList.add(videoInfo);
        }

        return videoInfoList;
    }

    /**
     * 构建用户权限信息
     */
    private CourseVideoDetailDto.UserPermission buildUserPermission(Long userId, Integer courseLevel) {
        CourseVideoDetailDto.UserPermission permission = new CourseVideoDetailDto.UserPermission();
        permission.setRequiredLevel(courseLevel);
        permission.setRequiredLevelName(getRoleNameByLevel(courseLevel));

        if (userId != null) {
            User user = userMapper.selectById(userId);
            if (user != null) {
                permission.setUserRole(user.getRole());
                permission.setUserRoleName(getRoleNameByLevel(user.getRole()));
                permission.setHasAccess(user.getRole() >= courseLevel);
                permission.setMembershipExpiresAt(user.getMembershipExpiresAt());

                if (!permission.getHasAccess()) {
                    permission.setAccessDeniedReason("您当前是" + permission.getUserRoleName() + "用户，该课程需要" + permission.getRequiredLevelName() + "及以上权限");
                }
            } else {
                permission.setUserRole(0);
                permission.setUserRoleName("游客");
                permission.setHasAccess(courseLevel <= 0);
                permission.setAccessDeniedReason("用户不存在");
            }
        } else {
            permission.setUserRole(0);
            permission.setUserRoleName("游客");
            permission.setHasAccess(courseLevel <= 0);
            if (courseLevel > 0) {
                permission.setAccessDeniedReason("请先登录，该课程需要" + permission.getRequiredLevelName() + "及以上权限");
            }
        }

        return permission;
    }

    /**
     * 根据级别获取角色名称
     */
    private String getRoleNameByLevel(Integer level) {
        if (level == null || level <= 0) {
            return "游客";
        } else if (level == 1) {
            return "普通用户";
        } else if (level == 2) {
            return "VIP用户";
        } else {
            return "SVIP用户";
        }
    }

    /**
     * 格式化时长
     */
    private String formatDuration(Integer durationSec) {
        if (durationSec == null || durationSec <= 0) {
            return "00:00";
        }
        
        int hours = durationSec / 3600;
        int minutes = (durationSec % 3600) / 60;
        int seconds = durationSec % 60;
        
        if (hours > 0) {
            return String.format("%02d:%02d:%02d", hours, minutes, seconds);
        } else {
            return String.format("%02d:%02d", minutes, seconds);
        }
    }
} 