package com.lesingle.edu.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.edu.common.enums.TenantPackageStatus;
import com.lesingle.edu.common.exception.BusinessException;
import com.lesingle.edu.entity.*;
import com.lesingle.edu.mapper.*;
import com.lesingle.edu.service.CourseLessonService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 课程环节服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CourseLessonServiceImpl extends ServiceImpl<CourseLessonMapper, CourseLesson> implements CourseLessonService {

    private final CourseLessonMapper courseLessonMapper;
    private final LessonStepMapper lessonStepMapper;
    private final LessonStepResourceMapper lessonStepResourceMapper;
    private final TenantCourseMapper tenantCourseMapper;
    private final TenantPackageMapper tenantPackageMapper;

    /**
     * 查询课程的所有环节
     */
    @Override
    public List<CourseLesson> findByCourseId(Long courseId) {
        log.info("查询课程的所有环节，courseId={}", courseId);
        List<CourseLesson> result = courseLessonMapper.selectList(
                new LambdaQueryWrapper<CourseLesson>()
                        .eq(CourseLesson::getCourseId, courseId)
                        .orderByAsc(CourseLesson::getSortOrder)
        );
        log.info("查询课程环节成功，courseId={}, count={}", courseId, result.size());
        return result;
    }

    /**
     * 查询课程环节详情
     */
    @Override
    public CourseLesson findById(Long id) {
        log.info("查询课程环节详情，id={}", id);
        CourseLesson lesson = courseLessonMapper.selectById(id);
        if (lesson == null) {
            log.warn("课程环节不存在，id={}", id);
            throw new BusinessException("课程环节不存在");
        }
        return lesson;
    }

    /**
     * 按 lessonType 查询包含该类型环节的课程 ID 列表
     * 兼容多种存储格式：SOCIAL/SOCIETY/DOMAIN_SOCIAL、INTRODUCTION/INTRO 等
     */
    @Override
    public List<Long> findCourseIdsByLessonType(String lessonType) {
        List<String> typesToMatch = resolveLessonTypeVariants(lessonType);
        if (typesToMatch.isEmpty()) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<CourseLesson> wrapper = new LambdaQueryWrapper<CourseLesson>()
                .select(CourseLesson::getCourseId);
        if (typesToMatch.size() == 1) {
            wrapper.eq(CourseLesson::getLessonType, typesToMatch.get(0));
        } else {
            wrapper.in(CourseLesson::getLessonType, typesToMatch);
        }
        return this.list(wrapper).stream()
                .map(CourseLesson::getCourseId)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 将前端传入的 lessonType 解析为数据库中可能存储的多种格式
     */
    private List<String> resolveLessonTypeVariants(String lessonType) {
        if (lessonType == null || lessonType.isBlank()) {
            return Collections.emptyList();
        }
        return switch (lessonType.toUpperCase()) {
            case "SOCIAL" -> Arrays.asList("SOCIAL", "SOCIETY", "DOMAIN_SOCIAL");
            case "SOCIETY" -> Arrays.asList("SOCIAL", "SOCIETY", "DOMAIN_SOCIAL");
            case "SCIENCE" -> Arrays.asList("SCIENCE", "DOMAIN_SCIENCE");
            case "LANGUAGE" -> Arrays.asList("LANGUAGE", "DOMAIN_LANGUAGE");
            case "HEALTH" -> Arrays.asList("HEALTH", "DOMAIN_HEALTH");
            case "ART" -> Arrays.asList("ART", "DOMAIN_ART");
            case "INTRODUCTION" -> Arrays.asList("INTRODUCTION", "INTRO");
            case "INTRO" -> Arrays.asList("INTRODUCTION", "INTRO");
            case "COLLECTIVE" -> Collections.singletonList("COLLECTIVE");
            default -> Collections.singletonList(lessonType);
        };
    }

    /**
     * 按类型查询课程环节
     */
    @Override
    public CourseLesson findByType(Long courseId, String lessonType) {
        log.info("按类型查询课程环节，courseId={}, lessonType={}", courseId, lessonType);
        CourseLesson result = courseLessonMapper.selectOne(
                new LambdaQueryWrapper<CourseLesson>()
                        .eq(CourseLesson::getCourseId, courseId)
                        .eq(CourseLesson::getLessonType, lessonType)
        );
        if (result != null) {
            log.info("查询课程环节成功，courseId={}, lessonType={}, id={}", courseId, lessonType, result.getId());
        }
        return result;
    }

    /**
     * 创建课程环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CourseLesson create(Long courseId, String lessonType, String name, String description,
                               Integer duration, String videoPath, String videoName,
                               String pptPath, String pptName, String pdfPath, String pdfName,
                               String objectives, String preparation, String extension,
                               String reflection, String assessmentData, Boolean useTemplate) {
        log.info("创建课程环节，courseId={}, lessonType={}, name={}", courseId, lessonType, name);
        // 检查是否已存在相同类型的课程
        CourseLesson existing = findByType(courseId, lessonType);
        if (existing != null) {
            log.warn("创建课程环节失败，已存在相同类型的课程环节，courseId={}, lessonType={}", courseId, lessonType);
            throw new BusinessException("该课程包已存在 " + lessonType + " 类型的课程");
        }

        // 获取最大排序号
        Integer maxSortOrder = courseLessonMapper.selectList(
                        new LambdaQueryWrapper<CourseLesson>()
                                .eq(CourseLesson::getCourseId, courseId)
                ).stream()
                .map(CourseLesson::getSortOrder)
                .max(Integer::compareTo)
                .orElse(0);

        CourseLesson lesson = new CourseLesson();
        lesson.setCourseId(courseId);
        lesson.setLessonType(lessonType);
        lesson.setName(name);
        lesson.setDescription(description);
        lesson.setDuration(duration);
        lesson.setVideoPath(videoPath);
        lesson.setVideoName(videoName);
        lesson.setPptPath(pptPath);
        lesson.setPptName(pptName);
        lesson.setPdfPath(pdfPath);
        lesson.setPdfName(pdfName);
        lesson.setObjectives(objectives);
        lesson.setPreparation(preparation);
        lesson.setExtension(extension);
        lesson.setReflection(reflection);
        // 确保 assessment_data 为有效 JSON，MySQL JSON 列不接受纯文本
        lesson.setAssessmentData(toValidJsonOrNull(assessmentData));
        lesson.setUseTemplate(useTemplate);
        lesson.setSortOrder(maxSortOrder + 1);
        lesson.setCreatedAt(LocalDateTime.now());

        courseLessonMapper.insert(lesson);
        log.info("课程环节创建成功，id={}, courseId={}, lessonType={}", lesson.getId(), courseId, lessonType);
        return lesson;
    }

    /**
     * 更新课程环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CourseLesson update(Long id, String name, String description, Integer duration,
                               String videoPath, String videoName, String pptPath, String pptName,
                               String pdfPath, String pdfName, String objectives, String preparation,
                               String extension, String reflection, String assessmentData, Boolean useTemplate) {
        log.info("更新课程环节，id={}", id);
        CourseLesson lesson = courseLessonMapper.selectById(id);
        if (lesson == null) {
            log.warn("课程环节不存在，id={}", id);
            throw new BusinessException("课程不存在");
        }

        if (name != null) {
            lesson.setName(name);
        }
        if (description != null) {
            lesson.setDescription(description);
        }
        if (duration != null) {
            lesson.setDuration(duration);
        }
        if (videoPath != null) {
            lesson.setVideoPath(videoPath);
        }
        if (videoName != null) {
            lesson.setVideoName(videoName);
        }
        if (pptPath != null) {
            lesson.setPptPath(pptPath);
        }
        if (pptName != null) {
            lesson.setPptName(pptName);
        }
        if (pdfPath != null) {
            lesson.setPdfPath(pdfPath);
        }
        if (pdfName != null) {
            lesson.setPdfName(pdfName);
        }
        if (objectives != null) {
            lesson.setObjectives(objectives);
        }
        if (preparation != null) {
            lesson.setPreparation(preparation);
        }
        if (extension != null) {
            lesson.setExtension(extension);
        }
        if (reflection != null) {
            lesson.setReflection(reflection);
        }
        if (assessmentData != null) {
            lesson.setAssessmentData(toValidJsonOrNull(assessmentData));
        }
        if (useTemplate != null) {
            lesson.setUseTemplate(useTemplate);
        }

        lesson.setUpdatedAt(LocalDateTime.now());
        courseLessonMapper.updateById(lesson);
        log.info("课程环节更新成功，id={}", id);
        return lesson;
    }

    /**
     * 删除课程环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        log.info("删除课程环节，id={}", id);
        CourseLesson lesson = courseLessonMapper.selectById(id);
        if (lesson == null) {
            log.warn("课程环节不存在，id={}", id);
            throw new BusinessException("课程不存在");
        }

        courseLessonMapper.deleteById(id);
        log.info("课程环节删除成功，id={}", id);
    }

    /**
     * 重新排序课程环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reorder(Long courseId, List<Long> lessonIds) {
        log.info("重新排序课程环节，courseId={}, count={}", courseId, lessonIds.size());
        for (int i = 0; i < lessonIds.size(); i++) {
            CourseLesson lesson = courseLessonMapper.selectById(lessonIds.get(i));
            if (lesson != null && lesson.getCourseId().equals(courseId)) {
                lesson.setSortOrder(i + 1);
                courseLessonMapper.updateById(lesson);
            }
        }
        log.info("课程环节重新排序成功，courseId={}", courseId);
    }

    /**
     * 查询课程环节的教学环节
     */
    @Override
    public List<LessonStep> findSteps(Long lessonId) {
        log.info("查询课程环节的教学环节，lessonId={}", lessonId);
        List<LessonStep> result = lessonStepMapper.selectList(
                new LambdaQueryWrapper<LessonStep>()
                        .eq(LessonStep::getLessonId, lessonId)
                        .orderByAsc(LessonStep::getSortOrder)
        );
        log.info("查询教学环节成功，lessonId={}, count={}", lessonId, result.size());
        return result;
    }

    /**
     * 创建教学环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LessonStep createStep(Long lessonId, String name, String content, Integer duration,
                                 String objective, List<Long> resourceIds) {
        log.info("创建教学环节，lessonId={}, name={}", lessonId, name);
        // 获取最大排序号
        Integer maxSortOrder = lessonStepMapper.selectList(
                        new LambdaQueryWrapper<LessonStep>()
                                .eq(LessonStep::getLessonId, lessonId)
                ).stream()
                .map(LessonStep::getSortOrder)
                .max(Integer::compareTo)
                .orElse(0);

        LessonStep step = new LessonStep();
        step.setLessonId(lessonId);
        step.setName(name);
        step.setContent(content);
        step.setDuration(duration != null ? duration : 5);
        step.setObjective(objective);
        step.setResourceIds(resourceIds != null ? resourceIds.toString() : null);
        step.setSortOrder(maxSortOrder + 1);
        step.setCreatedAt(LocalDateTime.now());

        lessonStepMapper.insert(step);

        // 创建环节资源关联
        if (resourceIds != null && !resourceIds.isEmpty()) {
            for (int i = 0; i < resourceIds.size(); i++) {
                LessonStepResource lsr = new LessonStepResource();
                lsr.setStepId(step.getId());
                lsr.setResourceId(resourceIds.get(i));
                lsr.setSortOrder(i);
                lessonStepResourceMapper.insert(lsr);
            }
        }

        log.info("教学环节创建成功，id={}, lessonId={}", step.getId(), lessonId);
        return step;
    }

    /**
     * 更新教学环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LessonStep updateStep(Long stepId, String name, String content, Integer duration,
                                 String objective, List<Long> resourceIds) {
        log.info("更新教学环节，stepId={}", stepId);
        LessonStep step = lessonStepMapper.selectById(stepId);
        if (step == null) {
            log.warn("教学环节不存在，stepId={}", stepId);
            throw new BusinessException("教学环节不存在");
        }

        if (name != null) {
            step.setName(name);
        }
        if (content != null) {
            step.setContent(content);
        }
        if (duration != null) {
            step.setDuration(duration);
        }
        if (objective != null) {
            step.setObjective(objective);
        }
        if (resourceIds != null) {
            step.setResourceIds(resourceIds.toString());

            // 删除旧的资源关联
            lessonStepResourceMapper.delete(
                    new LambdaQueryWrapper<LessonStepResource>()
                            .eq(LessonStepResource::getStepId, stepId)
            );

            // 创建新的资源关联
            for (int i = 0; i < resourceIds.size(); i++) {
                LessonStepResource lsr = new LessonStepResource();
                lsr.setStepId(stepId);
                lsr.setResourceId(resourceIds.get(i));
                lsr.setSortOrder(i);
                lessonStepResourceMapper.insert(lsr);
            }
        }

        step.setUpdatedAt(LocalDateTime.now());
        lessonStepMapper.updateById(step);
        log.info("教学环节更新成功，stepId={}", stepId);
        return step;
    }

    /**
     * 删除教学环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStep(Long stepId) {
        log.info("删除教学环节，stepId={}", stepId);
        lessonStepMapper.deleteById(stepId);
        log.info("教学环节删除成功，stepId={}", stepId);
    }

    /**
     * 重新排序教学环节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reorderSteps(Long lessonId, List<Long> stepIds) {
        log.info("重新排序教学环节，lessonId={}, count={}", lessonId, stepIds.size());
        for (int i = 0; i < stepIds.size(); i++) {
            LessonStep step = lessonStepMapper.selectById(stepIds.get(i));
            if (step != null && step.getLessonId().equals(lessonId)) {
                step.setSortOrder(i + 1);
                lessonStepMapper.updateById(step);
            }
        }
        log.info("教学环节重新排序成功，lessonId={}", lessonId);
    }

    /**
     * 将 assessmentData 转为 MySQL JSON 列可接受的有效 JSON。
     * 空值返回 null；已是有效 JSON 则原样返回；否则包装为 JSON 字符串。
     */
    private String toValidJsonOrNull(String assessmentData) {
        if (assessmentData == null || assessmentData.isEmpty()) {
            return null;
        }
        String trimmed = assessmentData.trim();
        if (trimmed.isEmpty()) {
            return null;
        }
        // 已是有效 JSON（对象或数组）则直接使用
        if ((trimmed.startsWith("{") && trimmed.endsWith("}")) || (trimmed.startsWith("[") && trimmed.endsWith("]"))) {
            try {
                JSON.parse(trimmed);
                return trimmed;
            } catch (Exception ignored) {
                // 解析失败，当作普通文本处理
            }
        }
        // 普通文本包装为 JSON 字符串
        return JSON.toJSONString(assessmentData);
    }

    /**
     * 查询教师的课程环节（带权限检查）
     */
    @Override
    public List<CourseLesson> findCourseLessonsForTeacher(Long courseId, Long tenantId) {
        log.info("查询教师的课程环节，courseId={}, tenantId={}", courseId, tenantId);
        // 检查租户是否有权限访问该课程
        TenantCourse tenantCourse = tenantCourseMapper.selectOne(
                new LambdaQueryWrapper<TenantCourse>()
                        .eq(TenantCourse::getTenantId, tenantId)
                        .eq(TenantCourse::getCourseId, courseId)
                        .eq(TenantCourse::getEnabled, 1)
        );

        if (tenantCourse == null) {
            // 检查是否通过套餐授权
            Long count = tenantPackageMapper.selectCount(
                    new LambdaQueryWrapper<TenantPackage>()
                            .eq(TenantPackage::getTenantId, tenantId)
                            .eq(TenantPackage::getStatus, TenantPackageStatus.ACTIVE)
            );

            if (count == 0) {
                log.warn("无权访问该课程，courseId={}, tenantId={}", courseId, tenantId);
                throw new BusinessException("无权访问该课程");
            }
        }

        List<CourseLesson> result = findByCourseId(courseId);
        log.info("查询教师的课程环节成功，courseId={}, count={}", courseId, result.size());
        return result;
    }
}
