import { Injectable, NotFoundException, ForbiddenException, Logger } from '@nestjs/common';
import { PrismaService } from '../../database/prisma.service';
import { CreateLessonDto } from './dto/create-lesson.dto';
import { FinishLessonDto } from './dto/finish-lesson.dto';

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

  constructor(private prisma: PrismaService) {}

  async create(teacherId: number, tenantId: number, dto: CreateLessonDto) {
    // 验证课程是否已授权
    const course = await this.prisma.course.findUnique({
      where: { id: dto.courseId },
    });

    if (!course) {
      throw new NotFoundException('课程不存在');
    }

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

    // 检查授权
    const tenantCourse = await this.prisma.tenantCourse.findUnique({
      where: {
        tenantId_courseId: {
          tenantId: tenantId,
          courseId: dto.courseId,
        },
      },
    });

    if (!tenantCourse || !tenantCourse.authorized) {
      throw new ForbiddenException('您的学校未获得此课程的授权');
    }

    // 验证班级是否属于该教师
    const classEntity = await this.prisma.class.findFirst({
      where: {
        id: dto.classId,
        tenantId: tenantId,
        teacherId: teacherId,
      },
    });

    if (!classEntity) {
      throw new ForbiddenException('无权操作此班级');
    }

    // 创建授课记录
    const lesson = await this.prisma.lesson.create({
      data: {
        tenantId: tenantId,
        teacherId: teacherId,
        classId: dto.classId,
        courseId: dto.courseId,
        plannedDatetime: dto.plannedDatetime ? new Date(dto.plannedDatetime) : null,
        status: 'PLANNED',
      },
      include: {
        course: {
          select: {
            id: true,
            name: true,
            pictureBookName: true,
            duration: true,
          },
        },
        class: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });

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

    return lesson;
  }

  async start(lessonId: number, teacherId: number) {
    // 查找授课记录
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权操作此授课记录');
    }

    if (lesson.status !== 'PLANNED') {
      throw new ForbiddenException('该授课记录已开始或已完成');
    }

    // 更新状态和开始时间
    const updatedLesson = await this.prisma.lesson.update({
      where: { id: lessonId },
      data: {
        status: 'IN_PROGRESS',
        startDatetime: new Date(),
      },
      include: {
        course: {
          select: {
            id: true,
            name: true,
            pictureBookName: true,
            duration: true,
            pptPath: true,
            pptName: true,
            ebookPaths: true,
            audioPaths: true,
            videoPaths: true,
            posterPaths: true,
            scripts: {
              orderBy: { sortOrder: 'asc' },
              include: {
                pages: {
                  orderBy: { pageNumber: 'asc' },
                },
              },
            },
            activities: {
              orderBy: { sortOrder: 'asc' },
            },
          },
        },
        class: {
          select: {
            id: true,
            name: true,
            students: {
              select: {
                id: true,
                name: true,
                gender: true,
              },
            },
          },
        },
      },
    });

    this.logger.log(`Lesson started: ${lessonId}`);

    // 解析 JSON 字段
    return {
      ...updatedLesson,
      course: {
        ...updatedLesson.course,
        ebookPaths: updatedLesson.course.ebookPaths ? JSON.parse(updatedLesson.course.ebookPaths) : [],
        audioPaths: updatedLesson.course.audioPaths ? JSON.parse(updatedLesson.course.audioPaths) : [],
        videoPaths: updatedLesson.course.videoPaths ? JSON.parse(updatedLesson.course.videoPaths) : [],
        posterPaths: updatedLesson.course.posterPaths ? JSON.parse(updatedLesson.course.posterPaths) : [],
        scripts: updatedLesson.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: updatedLesson.course.activities.map((activity) => ({
          ...activity,
          onlineMaterials: activity.onlineMaterials ? JSON.parse(activity.onlineMaterials) : null,
          objectives: activity.objectives ? JSON.parse(activity.objectives) : null,
        })),
      },
    };
  }

  async finish(lessonId: number, teacherId: number, dto: FinishLessonDto) {
    // 查找授课记录
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权操作此授课记录');
    }

    if (lesson.status !== 'IN_PROGRESS') {
      throw new ForbiddenException('该授课记录未开始或已完成');
    }

    // 计算实际时长
    let actualDuration = dto.actualDuration;
    if (!actualDuration && lesson.startDatetime) {
      const endTime = new Date();
      actualDuration = Math.round((endTime.getTime() - lesson.startDatetime.getTime()) / 60000);
    }

    // 更新状态和结束时间
    const updatedLesson = await this.prisma.lesson.update({
      where: { id: lessonId },
      data: {
        status: 'COMPLETED',
        endDatetime: new Date(),
        actualDuration: actualDuration,
        overallRating: dto.overallRating,
        participationRating: dto.participationRating,
        completionNote: dto.completionNote,
      },
      include: {
        course: {
          select: {
            id: true,
            name: true,
          },
        },
        class: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });

    // 更新课程使用统计
    await this.prisma.course.update({
      where: { id: lesson.courseId },
      data: {
        usageCount: { increment: 1 },
      },
    });

    // 更新教师授课次数
    await this.prisma.teacher.update({
      where: { id: teacherId },
      data: {
        lessonCount: { increment: 1 },
      },
    });

    this.logger.log(`Lesson finished: ${lessonId}, duration: ${actualDuration} minutes`);

    return updatedLesson;
  }

  async cancel(lessonId: number, teacherId: number) {
    // 查找授课记录
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权操作此授课记录');
    }

    // 只有已计划状态的课程可以取消
    if (lesson.status !== 'PLANNED') {
      throw new ForbiddenException('只有已计划的课程可以取消');
    }

    // 更新状态为已取消
    const updatedLesson = await this.prisma.lesson.update({
      where: { id: lessonId },
      data: {
        status: 'CANCELLED',
      },
      include: {
        course: {
          select: {
            id: true,
            name: true,
          },
        },
        class: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });

    this.logger.log(`Lesson cancelled: ${lessonId}`);

    return updatedLesson;
  }

  async findOne(lessonId: number, teacherId: number) {
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
      include: {
        course: {
          select: {
            id: true,
            name: true,
            pictureBookName: true,
            duration: true,
            pptPath: true,
            pptName: true,
            ebookPaths: true,
            audioPaths: true,
            videoPaths: true,
            posterPaths: true,
            scripts: {
              orderBy: { sortOrder: 'asc' },
              include: {
                pages: {
                  orderBy: { pageNumber: 'asc' },
                },
              },
            },
            activities: {
              orderBy: { sortOrder: 'asc' },
            },
          },
        },
        class: {
          select: {
            id: true,
            name: true,
            students: {
              select: {
                id: true,
                name: true,
                gender: true,
              },
            },
          },
        },
      },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权查看此授课记录');
    }

    // 解析 JSON 字段
    return {
      ...lesson,
      course: {
        ...lesson.course,
        ebookPaths: lesson.course.ebookPaths ? JSON.parse(lesson.course.ebookPaths) : [],
        audioPaths: lesson.course.audioPaths ? JSON.parse(lesson.course.audioPaths) : [],
        videoPaths: lesson.course.videoPaths ? JSON.parse(lesson.course.videoPaths) : [],
        posterPaths: lesson.course.posterPaths ? JSON.parse(lesson.course.posterPaths) : [],
        scripts: lesson.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: lesson.course.activities.map((activity) => ({
          ...activity,
          onlineMaterials: activity.onlineMaterials ? JSON.parse(activity.onlineMaterials) : null,
          objectives: activity.objectives ? JSON.parse(activity.objectives) : null,
        })),
      },
    };
  }

  async findByTeacher(teacherId: number, query: any) {
    const { page = 1, pageSize = 10, status, courseId } = query;

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

    const where: any = {
      teacherId: teacherId,
    };

    if (status) {
      where.status = status;
    }

    if (courseId) {
      where.courseId = +courseId;
    }

    const [items, total] = await Promise.all([
      this.prisma.lesson.findMany({
        where,
        skip,
        take,
        orderBy: { createdAt: 'desc' },
        include: {
          course: {
            select: {
              id: true,
              name: true,
              pictureBookName: true,
            },
          },
          class: {
            select: {
              id: true,
              name: true,
            },
          },
        },
      }),
      this.prisma.lesson.count({ where }),
    ]);

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

  async saveStudentRecord(
    lessonId: number,
    teacherId: number,
    studentId: number,
    data: {
      focus?: number;
      participation?: number;
      interest?: number;
      understanding?: number;
      notes?: string;
    }
  ) {
    // 验证授课记录
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权操作此授课记录');
    }

    // 验证学生是否在班级中
    const student = await this.prisma.student.findFirst({
      where: {
        id: studentId,
        classId: lesson.classId,
      },
    });

    if (!student) {
      throw new NotFoundException('学生不存在或不在此班级');
    }

    // 创建或更新学生记录
    const record = await this.prisma.studentRecord.upsert({
      where: {
        lessonId_studentId: {
          lessonId: lessonId,
          studentId: studentId,
        },
      },
      update: data,
      create: {
        lessonId: lessonId,
        studentId: studentId,
        ...data,
      },
    });

    return record;
  }

  async getStudentRecords(lessonId: number, teacherId: number) {
    // 验证授课记录
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
      include: {
        class: {
          select: {
            id: true,
            name: true,
            students: {
              select: {
                id: true,
                name: true,
                gender: true,
              },
            },
          },
        },
      },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权操作此授课记录');
    }

    // 获取所有学生记录
    const records = await this.prisma.studentRecord.findMany({
      where: { lessonId },
      include: {
        student: {
          select: {
            id: true,
            name: true,
            gender: true,
          },
        },
      },
    });

    // 合并学生信息和记录
    const studentRecords = lesson.class.students.map((student) => {
      const record = records.find((r) => r.studentId === student.id);
      return {
        ...student,
        record: record || null,
      };
    });

    return {
      lesson: {
        id: lesson.id,
        status: lesson.status,
        className: lesson.class.name,
      },
      students: studentRecords,
    };
  }

  async batchSaveStudentRecords(
    lessonId: number,
    teacherId: number,
    records: Array<{
      studentId: number;
      focus?: number;
      participation?: number;
      interest?: number;
      understanding?: number;
      notes?: string;
    }>
  ) {
    // 验证授课记录
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权操作此授课记录');
    }

    // 批量保存记录
    const results = [];
    for (const record of records) {
      const saved = await this.prisma.studentRecord.upsert({
        where: {
          lessonId_studentId: {
            lessonId: lessonId,
            studentId: record.studentId,
          },
        },
        update: {
          focus: record.focus,
          participation: record.participation,
          interest: record.interest,
          understanding: record.understanding,
          notes: record.notes,
        },
        create: {
          lessonId: lessonId,
          studentId: record.studentId,
          focus: record.focus,
          participation: record.participation,
          interest: record.interest,
          understanding: record.understanding,
          notes: record.notes,
        },
      });
      results.push(saved);

      // 更新学生的阅读次数（仅首次记录时）
      const existingRecord = await this.prisma.studentRecord.findFirst({
        where: {
          studentId: record.studentId,
          lessonId: { not: lessonId },
        },
      });

      if (!existingRecord) {
        // 这是该学生第一次有记录，更新阅读次数
        await this.prisma.student.update({
          where: { id: record.studentId },
          data: { readingCount: { increment: 1 } },
        });
      }
    }

    this.logger.log(`Batch saved ${results.length} student records for lesson ${lessonId}`);

    return { count: results.length, records: results };
  }

  // ==================== 课程反馈功能 ====================

  async submitFeedback(
    lessonId: number,
    teacherId: number,
    data: {
      designQuality?: number;
      participation?: number;
      goalAchievement?: number;
      stepFeedbacks?: any;
      pros?: string;
      suggestions?: string;
      activitiesDone?: any;
    }
  ) {
    // 验证授课记录
    const lesson = await this.prisma.lesson.findUnique({
      where: { id: lessonId },
    });

    if (!lesson) {
      throw new NotFoundException('授课记录不存在');
    }

    if (lesson.teacherId !== teacherId) {
      throw new ForbiddenException('无权操作此授课记录');
    }

    // 创建或更新反馈
    const feedback = await this.prisma.lessonFeedback.upsert({
      where: {
        lessonId_teacherId: {
          lessonId: lessonId,
          teacherId: teacherId,
        },
      },
      update: {
        designQuality: data.designQuality,
        participation: data.participation,
        goalAchievement: data.goalAchievement,
        stepFeedbacks: data.stepFeedbacks ? JSON.stringify(data.stepFeedbacks) : null,
        pros: data.pros,
        suggestions: data.suggestions,
        activitiesDone: data.activitiesDone ? JSON.stringify(data.activitiesDone) : null,
      },
      create: {
        lessonId: lessonId,
        teacherId: teacherId,
        designQuality: data.designQuality,
        participation: data.participation,
        goalAchievement: data.goalAchievement,
        stepFeedbacks: data.stepFeedbacks ? JSON.stringify(data.stepFeedbacks) : null,
        pros: data.pros,
        suggestions: data.suggestions,
        activitiesDone: data.activitiesDone ? JSON.stringify(data.activitiesDone) : null,
      },
      include: {
        lesson: {
          select: {
            id: true,
            course: {
              select: {
                id: true,
                name: true,
              },
            },
          },
        },
      },
    });

    // 更新教师反馈次数
    await this.prisma.teacher.update({
      where: { id: teacherId },
      data: {
        feedbackCount: { increment: 1 },
      },
    });

    this.logger.log(`Feedback submitted for lesson: ${lessonId}`);

    return {
      ...feedback,
      stepFeedbacks: feedback.stepFeedbacks ? JSON.parse(feedback.stepFeedbacks as string) : null,
      activitiesDone: feedback.activitiesDone ? JSON.parse(feedback.activitiesDone as string) : null,
    };
  }

  async getFeedback(lessonId: number, teacherId: number) {
    const feedback = await this.prisma.lessonFeedback.findUnique({
      where: {
        lessonId_teacherId: {
          lessonId: lessonId,
          teacherId: teacherId,
        },
      },
      include: {
        lesson: {
          select: {
            id: true,
            course: {
              select: {
                id: true,
                name: true,
                pictureBookName: true,
              },
            },
            class: {
              select: {
                id: true,
                name: true,
              },
            },
          },
        },
      },
    });

    if (!feedback) {
      return null;
    }

    return {
      ...feedback,
      stepFeedbacks: feedback.stepFeedbacks ? JSON.parse(feedback.stepFeedbacks as string) : null,
      activitiesDone: feedback.activitiesDone ? JSON.parse(feedback.activitiesDone as string) : null,
    };
  }

  async getFeedbacksByTenant(tenantId: number, query: any) {
    const { page = 1, pageSize = 10, teacherId, courseId } = query;

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

    const where: any = {
      lesson: {
        tenantId: tenantId,
      },
    };

    if (teacherId) {
      where.teacherId = +teacherId;
    }

    if (courseId) {
      where.lesson = {
        ...where.lesson,
        courseId: +courseId,
      };
    }

    const [items, total] = await Promise.all([
      this.prisma.lessonFeedback.findMany({
        where,
        skip,
        take,
        orderBy: { createdAt: 'desc' },
        include: {
          lesson: {
            select: {
              id: true,
              startDatetime: true,
              actualDuration: true,
              course: {
                select: {
                  id: true,
                  name: true,
                  pictureBookName: true,
                },
              },
              class: {
                select: {
                  id: true,
                  name: true,
                },
              },
            },
          },
          teacher: {
            select: {
              id: true,
              name: true,
            },
          },
        },
      }),
      this.prisma.lessonFeedback.count({ where }),
    ]);

    return {
      items: items.map((item) => ({
        ...item,
        stepFeedbacks: item.stepFeedbacks ? JSON.parse(item.stepFeedbacks as string) : null,
        activitiesDone: item.activitiesDone ? JSON.parse(item.activitiesDone as string) : null,
      })),
      total,
      page: +page,
      pageSize: +pageSize,
    };
  }

  async getFeedbackStats(tenantId: number) {
    // 获取反馈统计
    const feedbacks = await this.prisma.lessonFeedback.findMany({
      where: {
        lesson: {
          tenantId: tenantId,
        },
      },
      select: {
        designQuality: true,
        participation: true,
        goalAchievement: true,
        lesson: {
          select: {
            courseId: true,
          },
        },
      },
    });

    const totalFeedbacks = feedbacks.length;
    const avgDesignQuality = feedbacks.reduce((sum, f) => sum + (f.designQuality || 0), 0) / (totalFeedbacks || 1);
    const avgParticipation = feedbacks.reduce((sum, f) => sum + (f.participation || 0), 0) / (totalFeedbacks || 1);
    const avgGoalAchievement = feedbacks.reduce((sum, f) => sum + (f.goalAchievement || 0), 0) / (totalFeedbacks || 1);

    // 按课程统计
    const courseStats: Record<number, { count: number; avgRating: number }> = {};
    feedbacks.forEach((f) => {
      const courseId = f.lesson.courseId;
      if (!courseStats[courseId]) {
        courseStats[courseId] = { count: 0, avgRating: 0 };
      }
      courseStats[courseId].count++;
      courseStats[courseId].avgRating += (f.designQuality || 0 + f.participation || 0 + f.goalAchievement || 0) / 3;
    });

    // 计算平均值
    Object.keys(courseStats).forEach((courseId) => {
      courseStats[+courseId].avgRating /= courseStats[+courseId].count;
    });

    return {
      totalFeedbacks,
      avgDesignQuality: Math.round(avgDesignQuality * 10) / 10,
      avgParticipation: Math.round(avgParticipation * 10) / 10,
      avgGoalAchievement: Math.round(avgGoalAchievement * 10) / 10,
      courseStats,
    };
  }

  async getTeacherFeedbackStats(teacherId: number) {
    const feedbacks = await this.prisma.lessonFeedback.findMany({
      where: { teacherId },
      select: {
        designQuality: true,
        participation: true,
        goalAchievement: true,
        lesson: {
          select: {
            courseId: true,
          },
        },
      },
    });

    const totalFeedbacks = feedbacks.length;
    const avgDesignQuality = feedbacks.reduce((sum, f) => sum + (f.designQuality || 0), 0) / (totalFeedbacks || 1);
    const avgParticipation = feedbacks.reduce((sum, f) => sum + (f.participation || 0), 0) / (totalFeedbacks || 1);
    const avgGoalAchievement = feedbacks.reduce((sum, f) => sum + (f.goalAchievement || 0), 0) / (totalFeedbacks || 1);

    return {
      totalFeedbacks,
      avgDesignQuality: Math.round(avgDesignQuality * 10) / 10,
      avgParticipation: Math.round(avgParticipation * 10) / 10,
      avgGoalAchievement: Math.round(avgGoalAchievement * 10) / 10,
    };
  }
}
