import { Injectable, NotFoundException, ForbiddenException, ConflictException, Logger } from '@nestjs/common';
import { PrismaService } from '../../database/prisma.service';

export interface TeacherLessonTrendItem {
  month: string;
  lessonCount: number;
  avgRating: number;
}

@Injectable()
export class TeacherCourseService {
  private readonly logger = new Logger(TeacherCourseService.name);

  constructor(private prisma: PrismaService) {}

  // ==================== 首页仪表板 ====================

  async getDashboard(teacherId: number, tenantId: number) {
    // 获取所有仪表板数据
    const [stats, todayLessons, recommendedCourses, weeklyStats, recentActivities] = await Promise.all([
      this.getTeacherStats(teacherId, tenantId),
      this.getTodayLessons(teacherId, tenantId),
      this.getRecommendedCourses(tenantId),
      this.getWeeklyStats(teacherId),
      this.getRecentActivities(teacherId),
    ]);

    return {
      stats,
      todayLessons,
      recommendedCourses,
      weeklyStats,
      recentActivities,
    };
  }

  private async getTeacherStats(teacherId: number, tenantId: number) {
    // 通过 ClassTeacher 表获取教师的班级
    const classTeachers = await this.prisma.classTeacher.findMany({
      where: {
        teacherId: teacherId,
      },
      include: {
        class: {
          select: {
            id: true,
            studentCount: true,
            tenantId: true,
          },
        },
      },
    });

    // 过滤出属于当前租户的班级
    const classes = classTeachers.filter((ct) => ct.class.tenantId === tenantId);

    const classCount = classes.length;
    const studentCount = classes.reduce((sum, ct) => sum + ct.class.studentCount, 0);

    // 获取授课次数
    const lessonCount = await this.prisma.lesson.count({
      where: {
        teacherId: teacherId,
        status: 'COMPLETED',
      },
    });

    // 获取可用课程数
    const courseCount = await this.prisma.tenantCourse.count({
      where: {
        tenantId: tenantId,
        authorized: true,
        course: {
          status: 'PUBLISHED',
        },
      },
    });

    return {
      classCount,
      studentCount,
      lessonCount,
      courseCount,
    };
  }

  async getTodayLessons(teacherId: number, tenantId: number) {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);

    const lessons = await this.prisma.lesson.findMany({
      where: {
        teacherId: teacherId,
        tenantId: tenantId,
        plannedDatetime: {
          gte: today,
          lt: tomorrow,
        },
      },
      orderBy: {
        plannedDatetime: 'asc',
      },
      include: {
        course: {
          select: {
            id: true,
            name: true,
            pictureBookName: true,
            duration: true,
          },
        },
        class: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });

    return lessons.map((lesson) => ({
      id: lesson.id,
      courseId: lesson.courseId,
      courseName: lesson.course.name,
      pictureBookName: lesson.course.pictureBookName,
      classId: lesson.classId,
      className: lesson.class.name,
      plannedDatetime: lesson.plannedDatetime,
      status: lesson.status,
      duration: lesson.course.duration,
    }));
  }

  async getRecommendedCourses(tenantId: number) {
    // 获取推荐课程（按使用次数和评分排序）
    const courses = await this.prisma.course.findMany({
      where: {
        status: 'PUBLISHED',
        tenantCourses: {
          some: {
            tenantId: tenantId,
            authorized: true,
          },
        },
      },
      orderBy: [
        { usageCount: 'desc' },
        { avgRating: 'desc' },
      ],
      take: 6,
      select: {
        id: true,
        name: true,
        pictureBookName: true,
        coverImagePath: true,
        duration: true,
        usageCount: true,
        avgRating: true,
        gradeTags: true,
      },
    });

    return courses.map((course) => ({
      ...course,
      gradeTags: this.parseJsonArray(course.gradeTags),
    }));
  }

  async getWeeklyStats(teacherId: number) {
    // 获取本周的统计数据
    const now = new Date();
    const dayOfWeek = now.getDay();
    const monday = new Date(now);
    monday.setDate(now.getDate() - (dayOfWeek === 0 ? 6 : dayOfWeek - 1));
    monday.setHours(0, 0, 0, 0);

    const sunday = new Date(monday);
    sunday.setDate(monday.getDate() + 7);

    // 本周完成的课程数
    const lessonCount = await this.prisma.lesson.count({
      where: {
        teacherId: teacherId,
        status: 'COMPLETED',
        endDatetime: {
          gte: monday,
          lt: sunday,
        },
      },
    });

    // 本周参与的学生数
    const studentRecords = await this.prisma.studentRecord.findMany({
      where: {
        lesson: {
          teacherId: teacherId,
          status: 'COMPLETED',
          endDatetime: {
            gte: monday,
            lt: sunday,
          },
        },
      },
      select: {
        studentId: true,
      },
      distinct: ['studentId'],
    });
    const studentParticipation = studentRecords.length;

    // 本周课程总时长
    const lessons = await this.prisma.lesson.findMany({
      where: {
        teacherId: teacherId,
        status: 'COMPLETED',
        endDatetime: {
          gte: monday,
          lt: sunday,
        },
      },
      select: {
        actualDuration: true,
        course: {
          select: {
            duration: true,
          },
        },
      },
    });

    const totalDuration = lessons.reduce((sum, lesson) => {
      return sum + (lesson.actualDuration || lesson.course.duration || 0);
    }, 0);

    // 平均评分（从反馈中获取）
    const feedbacks = await this.prisma.lessonFeedback.findMany({
      where: {
        teacherId: teacherId,
        lesson: {
          endDatetime: {
            gte: monday,
            lt: sunday,
          },
        },
      },
      select: {
        designQuality: true,
        participation: true,
        goalAchievement: true,
      },
    });

    let avgRating = 0;
    if (feedbacks.length > 0) {
      const totalRating = feedbacks.reduce((sum, f) => {
        const ratings = [f.designQuality, f.participation, f.goalAchievement].filter(r => r !== null);
        const avg = ratings.length > 0 ? ratings.reduce((s, r) => s + r, 0) / ratings.length : 0;
        return sum + avg;
      }, 0);
      avgRating = Math.round((totalRating / feedbacks.length) * 10) / 10;
    }

    return {
      lessonCount,
      studentParticipation,
      totalDuration,
      avgRating,
    };
  }

  private async getRecentActivities(teacherId: number, limit: number = 10) {
    const lessons = await this.prisma.lesson.findMany({
      where: {
        teacherId: teacherId,
      },
      orderBy: {
        updatedAt: 'desc',
      },
      take: limit,
      select: {
        id: true,
        status: true,
        updatedAt: true,
        course: {
          select: {
            name: true,
          },
        },
      },
    });

    return lessons.map((lesson) => ({
      id: lesson.id,
      type: lesson.status,
      description: this.getActivityDescription(lesson.status, lesson.course?.name),
      time: lesson.updatedAt,
    }));
  }

  private getActivityDescription(status: string, courseName?: string): string {
    const course = courseName || '课程';
    switch (status) {
      case 'COMPLETED':
        return `完成《${course}》授课`;
      case 'IN_PROGRESS':
        return `正在进行《${course}》授课`;
      case 'PLANNED':
        return `计划《${course}》授课`;
      case 'CANCELLED':
        return `取消《${course}》授课`;
      default:
        return `操作《${course}》`;
    }
  }

  /**
   * 获取教师个人授课趋势（最近N个月）
   */
  async getTeacherLessonTrend(teacherId: number, months: number = 6): Promise<TeacherLessonTrendItem[]> {
    const result: TeacherLessonTrendItem[] = [];
    const now = new Date();

    for (let i = months - 1; i >= 0; i--) {
      const startDate = new Date(now.getFullYear(), now.getMonth() - i, 1);
      const endDate = new Date(now.getFullYear(), now.getMonth() - i + 1, 0, 23, 59, 59);

      // 获取该月授课次数
      const lessonCount = await this.prisma.lesson.count({
        where: {
          teacherId,
          status: 'COMPLETED',
          createdAt: {
            gte: startDate,
            lte: endDate,
          },
        },
      });

      // 获取该月平均评分
      const feedbacks = await this.prisma.lessonFeedback.findMany({
        where: {
          teacherId,
          lesson: {
            endDatetime: {
              gte: startDate,
              lte: endDate,
            },
          },
        },
        select: {
          designQuality: true,
          participation: true,
          goalAchievement: true,
        },
      });

      let avgRating = 0;
      if (feedbacks.length > 0) {
        const totalRating = feedbacks.reduce((sum, f) => {
          const ratings = [f.designQuality, f.participation, f.goalAchievement].filter((r) => r !== null);
          const avg = ratings.length > 0 ? ratings.reduce((s, r) => s + r, 0) / ratings.length : 0;
          return sum + avg;
        }, 0);
        avgRating = Math.round((totalRating / feedbacks.length) * 10) / 10;
      }

      const monthLabel = `${startDate.getFullYear()}-${String(startDate.getMonth() + 1).padStart(2, '0')}`;
      result.push({
        month: monthLabel,
        lessonCount,
        avgRating,
      });
    }

    return result;
  }

  /**
   * 获取教师课程使用统计
   */
  async getTeacherCourseUsage(teacherId: number) {
    // 获取该教师所有已完成的授课记录
    const lessons = await this.prisma.lesson.findMany({
      where: {
        teacherId,
        status: 'COMPLETED',
      },
      select: {
        courseId: true,
        course: {
          select: {
            name: true,
          },
        },
      },
    });

    // 统计每个课程的使用次数
    const courseMap = new Map<string, number>();

    lessons.forEach((lesson) => {
      const courseName = lesson.course?.name || '未知课程';
      courseMap.set(courseName, (courseMap.get(courseName) || 0) + 1);
    });

    // 转换为数组并排序
    const result = Array.from(courseMap.entries())
      .map(([name, value]) => ({ name, value }))
      .sort((a, b) => b.value - a.value)
      .slice(0, 6);

    return result;
  }

  // ==================== 课程管理 ====================

  async findAll(teacherId: number, tenantId: number, query: any) {
    const { page = 1, pageSize = 12, grade, domain, keyword } = query;

    const skip = (page - 1) * pageSize;
    const take = +pageSize;

    // 构建基础查询条件：已发布 + 已授权给教师所在租户
    const where: any = {
      status: 'PUBLISHED',
      tenantCourses: {
        some: {
          tenantId: tenantId,
          authorized: true,
        },
      },
    };

    // 关键词搜索
    if (keyword) {
      where.OR = [
        { name: { contains: keyword } },
        { pictureBookName: { contains: keyword } },
      ];
    }

    // 年级筛选 (SQLite 不支持 JSON path 查询，使用 contains)
    if (grade) {
      where.gradeTags = {
        contains: grade,
      };
    }

    // 领域筛选
    if (domain) {
      where.domainTags = {
        contains: domain,
      };
    }

    const [items, total] = await Promise.all([
      this.prisma.course.findMany({
        where,
        skip,
        take,
        orderBy: { publishedAt: 'desc' },
        select: {
          id: true,
          name: true,
          pictureBookName: true,
          coverImagePath: true,
          gradeTags: true,
          domainTags: true,
          duration: true,
          avgRating: true,
          usageCount: true,
          publishedAt: true,
        },
      }),
      this.prisma.course.count({ where }),
    ]);

    // 解析 JSON 字段
    const parsedItems = items.map((item) => ({
      ...item,
      gradeTags: JSON.parse(item.gradeTags || '[]'),
      domainTags: JSON.parse(item.domainTags || '[]'),
    }));

    return {
      items: parsedItems,
      total,
      page: +page,
      pageSize: +pageSize,
    };
  }

  async findOne(courseId: number, teacherId: number, tenantId: number) {
    // 检查课程是否存在且已发布
    const course = await this.prisma.course.findUnique({
      where: { id: courseId },
      include: {
        resources: {
          orderBy: { sortOrder: 'asc' },
        },
        scripts: {
          orderBy: { sortOrder: 'asc' },
          include: {
            pages: {
              orderBy: { pageNumber: 'asc' },
            },
          },
        },
        activities: {
          orderBy: { sortOrder: 'asc' },
        },
        tenantCourses: {
          where: { tenantId },
        },
      },
    });

    if (!course) {
      throw new NotFoundException(`Course #${courseId} not found`);
    }

    if (course.status !== 'PUBLISHED') {
      throw new ForbiddenException('该课程未发布');
    }

    // 检查授权
    const tenantCourse = course.tenantCourses.find((tc) => tc.tenantId === tenantId);
    if (!tenantCourse || !tenantCourse.authorized) {
      throw new ForbiddenException('您的学校未获得此课程的授权');
    }

    // 解析 JSON 字段
    return {
      ...course,
      gradeTags: JSON.parse(course.gradeTags || '[]'),
      domainTags: JSON.parse(course.domainTags || '[]'),
      ebookPaths: course.ebookPaths ? JSON.parse(course.ebookPaths) : null,
      audioPaths: course.audioPaths ? JSON.parse(course.audioPaths) : null,
      videoPaths: course.videoPaths ? JSON.parse(course.videoPaths) : null,
      otherResources: course.otherResources ? JSON.parse(course.otherResources) : null,
      posterPaths: course.posterPaths ? JSON.parse(course.posterPaths) : null,
      tenantCourses: undefined, // 移除敏感信息
      scripts: course.scripts.map((script) => ({
        ...script,
        interactionPoints: script.interactionPoints ? JSON.parse(script.interactionPoints) : null,
        resourceIds: script.resourceIds ? JSON.parse(script.resourceIds) : null,
        pages: script.pages?.map((page) => ({
          ...page,
          resourceIds: page.resourceIds ? JSON.parse(page.resourceIds) : null,
        })),
      })),
      activities: course.activities.map((activity) => ({
        ...activity,
        onlineMaterials: activity.onlineMaterials ? JSON.parse(activity.onlineMaterials) : null,
        objectives: activity.objectives ? JSON.parse(activity.objectives) : null,
      })),
    };
  }

  async getTeacherClasses(teacherId: number) {
    // 通过 ClassTeacher 表查询教师关联的班级
    const classTeachers = await this.prisma.classTeacher.findMany({
      where: { teacherId },
      include: {
        class: {
          select: {
            id: true,
            name: true,
            grade: true,
            studentCount: true,
            lessonCount: true,
          },
        },
      },
      orderBy: [
        { isPrimary: 'desc' },
        { createdAt: 'asc' },
      ],
    });

    return classTeachers.map((ct) => ({
      id: ct.class.id,
      name: ct.class.name,
      grade: ct.class.grade,
      studentCount: ct.class.studentCount,
      lessonCount: ct.class.lessonCount,
      myRole: ct.role,          // 我在该班级的角色
      isPrimary: ct.isPrimary,  // 是否班主任
    }));
  }

  async getClassTeachers(teacherId: number, classId: number) {
    // 验证教师是否有权限查看该班级
    const teacherClass = await this.prisma.classTeacher.findFirst({
      where: { teacherId, classId },
    });

    if (!teacherClass) {
      throw new ForbiddenException('您没有权限查看该班级');
    }

    const classTeachers = await this.prisma.classTeacher.findMany({
      where: { classId },
      include: {
        teacher: {
          select: {
            id: true,
            name: true,
            phone: true,
          },
        },
      },
      orderBy: [
        { isPrimary: 'desc' },
        { createdAt: 'asc' },
      ],
    });

    return classTeachers.map((ct) => ({
      teacherId: ct.teacher.id,
      teacherName: ct.teacher.name,
      teacherPhone: ct.teacher.phone,
      role: ct.role,
      isPrimary: ct.isPrimary,
    }));
  }

  /**
   * 获取教师所有班级的学生列表（跨班级）
   */
  async getAllTeacherStudents(teacherId: number, query: any) {
    const { page = 1, pageSize = 20, keyword } = query;
    const skip = (page - 1) * pageSize;
    const take = +pageSize;

    // 获取教师关联的所有班级ID
    const classTeachers = await this.prisma.classTeacher.findMany({
      where: { teacherId },
      select: { classId: true },
    });

    const classIds = classTeachers.map((ct) => ct.classId);

    if (classIds.length === 0) {
      return {
        items: [],
        total: 0,
        page: +page,
        pageSize: +pageSize,
      };
    }

    // 构建搜索条件
    const where: any = {
      classId: { in: classIds },
    };

    if (keyword) {
      where.name = { contains: keyword };
    }

    // 查询学生列表
    const [students, total] = await Promise.all([
      this.prisma.student.findMany({
        where,
        skip,
        take,
        select: {
          id: true,
          name: true,
          gender: true,
          birthDate: true,
          classId: true,
          parentName: true,
          parentPhone: true,
          createdAt: true,
          class: {
            select: {
              id: true,
              name: true,
              grade: true,
            },
          },
        },
        orderBy: { createdAt: 'desc' },
      }),
      this.prisma.student.count({ where }),
    ]);

    return {
      items: students.map((student) => ({
        id: student.id,
        name: student.name,
        gender: student.gender,
        birthDate: student.birthDate,
        classId: student.classId,
        parentName: student.parentName,
        parentPhone: student.parentPhone,
        createdAt: student.createdAt,
        class: student.class,
      })),
      total,
      page: +page,
      pageSize: +pageSize,
    };
  }

  /**
   * 获取教师关联的所有班级ID
   */
  async getTeacherClassIds(teacherId: number): Promise<number[]> {
    const classTeachers = await this.prisma.classTeacher.findMany({
      where: { teacherId },
      select: { classId: true },
    });
    return classTeachers.map((ct) => ct.classId);
  }

  async getClassStudents(teacherId: number, classId: number, query: any) {
    const { page = 1, pageSize = 20, keyword } = query;
    const skip = (page - 1) * pageSize;
    const take = +pageSize;

    // 验证教师是否关联该班级（通过 ClassTeacher 表）
    const teacherClass = await this.prisma.classTeacher.findFirst({
      where: {
        teacherId,
        classId,
      },
      include: {
        class: {
          select: {
            id: true,
            name: true,
            grade: true,
            studentCount: true,
            lessonCount: true,
          },
        },
      },
    });

    if (!teacherClass) {
      throw new ForbiddenException('您没有权限查看该班级或班级不存在');
    }

    const classEntity = teacherClass.class;

    // 构建搜索条件
    const where: any = {
      classId: classId,
    };

    if (keyword) {
      where.name = { contains: keyword };
    }

    // 查询学生列表
    const [students, total] = await Promise.all([
      this.prisma.student.findMany({
        where,
        skip,
        take,
        select: {
          id: true,
          name: true,
          gender: true,
          birthDate: true,
          parentName: true,
          parentPhone: true,
          lessonCount: true,
          readingCount: true,
          createdAt: true,
        },
        orderBy: { createdAt: 'desc' },
      }),
      this.prisma.student.count({ where }),
    ]);

    return {
      items: students.map(student => ({
        id: student.id,
        name: student.name,
        gender: student.gender,
        birthDate: student.birthDate,
        parentName: student.parentName,
        parentPhone: student.parentPhone,
        lessonCount: student.lessonCount,
        readingCount: student.readingCount,
        createdAt: student.createdAt,
      })),
      total,
      page: +page,
      pageSize: +pageSize,
      class: classEntity,
    };
  }

  // ==================== 工具方法 ====================

  private parseJsonArray(value: any): any[] {
    if (!value) return [];
    if (typeof value === 'string') {
      try {
        return JSON.parse(value);
      } catch {
        return [];
      }
    }
    return Array.isArray(value) ? value : [];
  }

  // ==================== 排课管理 ====================

  async getTeacherSchedules(teacherId: number, query: any) {
    const { page = 1, pageSize = 20, startDate, endDate, status } = query;

    const skip = (page - 1) * pageSize;
    const take = +pageSize;

    const where: any = {
      teacherId,
      status: status || 'ACTIVE',
    };

    if (startDate || endDate) {
      where.scheduledDate = {};
      if (startDate) where.scheduledDate.gte = new Date(startDate);
      if (endDate) where.scheduledDate.lte = new Date(endDate);
    }

    const [items, total] = await Promise.all([
      this.prisma.schedulePlan.findMany({
        where,
        skip,
        take,
        orderBy: { scheduledDate: 'asc' },
        include: {
          class: { select: { id: true, name: true, grade: true } },
          course: { select: { id: true, name: true, pictureBookName: true, duration: true } },
          lessons: {
            where: { teacherId },
            select: { id: true, status: true },
            take: 1,
          },
        },
      }),
      this.prisma.schedulePlan.count({ where }),
    ]);

    return {
      items: items.map((item) => ({
        ...item,
        className: item.class.name,
        courseName: item.course.name,
        hasLesson: item.lessons.length > 0,
        lessonId: item.lessons[0]?.id,
        lessonStatus: item.lessons[0]?.status,
      })),
      total,
      page: +page,
      pageSize: +pageSize,
    };
  }

  async getTeacherTimetable(teacherId: number, startDate: string, endDate: string) {
    const schedules = await this.prisma.schedulePlan.findMany({
      where: {
        teacherId,
        status: 'ACTIVE',
        scheduledDate: {
          gte: new Date(startDate),
          lte: new Date(endDate),
        },
      },
      orderBy: [{ scheduledDate: 'asc' }, { scheduledTime: 'asc' }],
      include: {
        class: { select: { id: true, name: true, grade: true } },
        course: { select: { id: true, name: true, pictureBookName: true, duration: true } },
        lessons: {
          where: { teacherId },
          select: { id: true, status: true },
          take: 1,
        },
      },
    });

    // 按日期分组
    const timetable: Record<string, any[]> = {};
    const start = new Date(startDate);
    const end = new Date(endDate);

    // 初始化所有日期
    for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
      const dateStr = d.toISOString().split('T')[0];
      timetable[dateStr] = [];
    }

    // 填充排课数据
    schedules.forEach((schedule) => {
      const dateStr = schedule.scheduledDate!.toISOString().split('T')[0];
      if (timetable[dateStr]) {
        timetable[dateStr].push({
          ...schedule,
          className: schedule.class.name,
          courseName: schedule.course.name,
          hasLesson: schedule.lessons.length > 0,
          lessonId: schedule.lessons[0]?.id,
          lessonStatus: schedule.lessons[0]?.status,
        });
      }
    });

    return Object.entries(timetable).map(([date, items]) => ({
      date,
      weekDay: new Date(date).getDay(),
      schedules: items,
    }));
  }

  async getTodaySchedules(teacherId: number) {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);

    const schedules = await this.prisma.schedulePlan.findMany({
      where: {
        teacherId,
        status: 'ACTIVE',
        scheduledDate: {
          gte: today,
          lt: tomorrow,
        },
      },
      orderBy: { scheduledTime: 'asc' },
      include: {
        class: { select: { id: true, name: true } },
        course: { select: { id: true, name: true, pictureBookName: true, duration: true } },
        lessons: {
          where: { teacherId },
          select: { id: true, status: true },
          take: 1,
        },
      },
    });

    return schedules.map((schedule) => ({
      ...schedule,
      className: schedule.class.name,
      courseName: schedule.course.name,
      hasLesson: schedule.lessons.length > 0,
      lessonId: schedule.lessons[0]?.id,
      lessonStatus: schedule.lessons[0]?.status,
    }));
  }

  /**
   * 解析时间字符串为分钟数
   * @param timeStr 格式: "HH:mm"
   * @returns 从午夜开始的分钟数
   */
  private parseTimeToMinutes(timeStr: string): number {
    const [hours, minutes] = timeStr.split(':').map(Number);
    return hours * 60 + minutes;
  }

  /**
   * 检查两个时间段是否重叠
   * @param time1 格式: "HH:mm-HH:mm"
   * @param time2 格式: "HH:mm-HH:mm"
   */
  private isTimeOverlapping(time1: string, time2: string): boolean {
    const [start1, end1] = time1.split('-').map(t => this.parseTimeToMinutes(t.trim()));
    const [start2, end2] = time2.split('-').map(t => this.parseTimeToMinutes(t.trim()));

    // 两个时间段重叠的条件: start1 < end2 AND start2 < end1
    return start1 < end2 && start2 < end1;
  }

  /**
   * 检查教师排课时间冲突
   */
  private async checkScheduleConflict(
    teacherId: number,
    scheduledDate: string,
    scheduledTime: string,
    excludeScheduleId?: number,
  ): Promise<{ courseName: string; className: string; scheduledTime: string } | null> {
    // 使用日期范围查询，避免时区问题
    const dateStart = new Date(scheduledDate + 'T00:00:00.000Z');
    const dateEnd = new Date(scheduledDate + 'T23:59:59.999Z');

    // 获取该教师当天的所有排课
    const existingSchedules = await this.prisma.schedulePlan.findMany({
      where: {
        teacherId,
        scheduledDate: {
          gte: dateStart,
          lte: dateEnd,
        },
        status: 'ACTIVE',
        ...(excludeScheduleId && { id: { not: excludeScheduleId } }),
      },
      include: {
        class: { select: { name: true } },
        course: { select: { name: true } },
      },
    });

    // 检查是否存在时间重叠
    for (const schedule of existingSchedules) {
      if (schedule.scheduledTime && this.isTimeOverlapping(scheduledTime, schedule.scheduledTime)) {
        return {
          courseName: schedule.course.name,
          className: schedule.class.name,
          scheduledTime: schedule.scheduledTime,
        };
      }
    }

    return null;
  }

  async createTeacherSchedule(teacherId: number, tenantId: number, dto: any) {
    // 验证班级存在且教师有权限
    const classTeacher = await this.prisma.classTeacher.findFirst({
      where: { teacherId, classId: dto.classId },
    });

    if (!classTeacher) {
      throw new ForbiddenException('您没有权限在此班级排课');
    }

    // 验证课程存在且已授权
    const tenantCourse = await this.prisma.tenantCourse.findFirst({
      where: { tenantId, courseId: dto.courseId, authorized: true },
    });

    if (!tenantCourse) {
      throw new ForbiddenException('该课程未授权或不存在');
    }

    // 检查教师时间冲突
    if (dto.scheduledDate && dto.scheduledTime) {
      const conflict = await this.checkScheduleConflict(teacherId, dto.scheduledDate, dto.scheduledTime);
      if (conflict) {
        throw new ConflictException(
          `时间冲突：您在 ${conflict.scheduledTime} 已有排课「${conflict.courseName}」（${conflict.className}），请选择其他时间段`
        );
      }
    }

    const schedule = await this.prisma.schedulePlan.create({
      data: {
        tenantId,
        classId: dto.classId,
        courseId: dto.courseId,
        teacherId,
        scheduledDate: dto.scheduledDate ? new Date(dto.scheduledDate) : null,
        scheduledTime: dto.scheduledTime,
        weekDay: dto.weekDay,
        repeatType: dto.repeatType || 'NONE',
        repeatEndDate: dto.repeatEndDate ? new Date(dto.repeatEndDate) : null,
        source: 'TEACHER',
        createdBy: teacherId,
        note: dto.note,
        status: 'ACTIVE',
      },
      include: {
        class: { select: { id: true, name: true } },
        course: { select: { id: true, name: true } },
      },
    });

    this.logger.log(`Teacher schedule created: ${schedule.id} by teacher ${teacherId}`);

    return {
      ...schedule,
      className: schedule.class.name,
      courseName: schedule.course.name,
    };
  }

  async updateTeacherSchedule(teacherId: number, id: number, dto: any) {
    const schedule = await this.prisma.schedulePlan.findFirst({
      where: { id, teacherId },
    });

    if (!schedule) {
      throw new NotFoundException('排课计划不存在或无权限');
    }

    const updated = await this.prisma.schedulePlan.update({
      where: { id },
      data: {
        scheduledDate: dto.scheduledDate ? new Date(dto.scheduledDate) : undefined,
        scheduledTime: dto.scheduledTime,
        weekDay: dto.weekDay,
        repeatType: dto.repeatType,
        repeatEndDate: dto.repeatEndDate ? new Date(dto.repeatEndDate) : undefined,
        note: dto.note,
        status: dto.status,
      },
      include: {
        class: { select: { id: true, name: true } },
        course: { select: { id: true, name: true } },
      },
    });

    this.logger.log(`Teacher schedule updated: ${id}`);

    return {
      ...updated,
      className: updated.class.name,
      courseName: updated.course.name,
    };
  }

  async cancelTeacherSchedule(teacherId: number, id: number) {
    const schedule = await this.prisma.schedulePlan.findFirst({
      where: { id, teacherId },
    });

    if (!schedule) {
      throw new NotFoundException('排课计划不存在或无权限');
    }

    await this.prisma.schedulePlan.update({
      where: { id },
      data: { status: 'CANCELLED' },
    });

    this.logger.log(`Teacher schedule cancelled: ${id}`);

    return { message: '取消成功' };
  }
}
