const prisma = require("../lib/prisma");

const path = require("path");
const { notifyUser, notifyManyUsers } = require("../services/notification.service");

// Create assignment (teacher only)
exports.createAssignment = async (req, res) => {
  try {
    const { title, description, subjectId, lessonId, dueDate } = req.body;

    // File validation
    if (!req.file) {
      return res.status(400).json({ message: "Assignment file is required" });
    }

    // Extract file info
    const fileUrl = req.file.path; // path or Cloudinary URL
    const fileType = req.file.mimetype;
    const fileSize = req.file.size;

    // Check if subject exists
    const subject = await prisma.subject.findUnique({
      where: { id: parseInt(subjectId) },
    });

    if (!subject) {
      return res.status(404).json({ message: "Subject not found" });
    }

    // Prevent unauthorized teacher
    if (subject.teacherId !== req.user.id) {
      return res
        .status(403)
        .json({ message: "You are not assigned to this subject" });
    }

    // Optional: check lesson exists if lessonId is provided
    let lesson = null;
    if (lessonId) {
      lesson = await prisma.lesson.findUnique({
        where: { id: parseInt(lessonId) },
      });
      if (!lesson) {
        return res.status(404).json({ message: "Lesson not found" });
      }
      if (lesson.teacherId !== req.user.id) {
        return res
          .status(403)
          .json({ message: "You are not assigned to this lesson" });
      }
    }

    // Create assignment
    const assignment = await prisma.assignment.create({
      data: {
        title,
        description,
        fileUrl,
        fileType,
        fileSize,
        dueDate: new Date(dueDate),
        subjectId: parseInt(subjectId),
        lessonId: lesson ? lesson.id : null,
        teacherId: req.user.id,
      },
    });

    // 🔔 Notify all enrolled students
    const enrolledStudents = await prisma.user.findMany({
      where: {
        role: "student",
        enrollment: {
          some: { subjectId: parseInt(subjectId) },
        },
      },
      select: { id: true },
    });

    const studentIds = enrolledStudents.map((s) => s.id);

    if (studentIds.length > 0) {
      const message = `New assignment "${title}" has been added to your course "${subject.title}". Due date: ${new Date(dueDate).toLocaleDateString()}.`;
      await notifyManyUsers(req, studentIds, message, null); // system notification
    }

    return res.status(200).json({
      message: "Assignment created successfully",
      assignment,
    });
  } catch (err) {
    console.log(err);
    return res.status(500).json({ message: "Server error" });
  }
};

// Get assignments by subject
exports.getAssignmentsBySubject = async (req, res) => {
  try {
    const lessonId = Number(req.params.lessonId);
    const subjectId = parseInt(req.params.subjectId);
    const studentId = req.user.id;

    const assignments = await prisma.assignment.findMany({
      where: { subjectId },
      include: { lesson: true },
    });
    return res.json(assignments.length > 0 ? assignments : []);
  } catch (err) {
    console.log(err);
    return res.status(500).json({ message: "Server error" });
  }
};

// Get assignments by lesson
exports.getAssignmentsByLesson = async (req, res) => {
  try {
    const lessonId = parseInt(req.params.lessonId);
    const subjectId = Number(req.query.subjectId);
    const studentId = req.user.id;
    
    if (isNaN(lessonId)) {
      return res.status(400).json({ message: "Invalid lesson ID" });
    }

    // ===== Pagination =====
    const page = parseInt(req.query.page) || 0;
    const pageSize = parseInt(req.query.pageSize) || 10;

    // ===== Sorting =====
    let orderBy = [];
    if (req.query.sort) {
      try {
        const sortModel = JSON.parse(req.query.sort);
        orderBy = sortModel
          .filter(({ field }) =>
            ["id", "title", "description", "dueDate", "createdAt"].includes(
              field
            )
          )
          .map(({ field, sort }) => ({ [field]: sort.toLowerCase() }));
      } catch (err) {
        console.error("Invalid sort JSON", err);
      }
    }
    if (orderBy.length === 0) orderBy = [{ id: "asc" }];

    // ===== Filtering =====
    let where = { lessonId };
    if (req.query.filter) {
      try {
        const filterModel = JSON.parse(req.query.filter);
        filterModel.items.forEach((item) => {
          if (item.value && item.field) {
            where[item.field] = { contains: item.value, mode: "insensitive" };
          }
        });
      } catch (err) {
        console.error("Invalid filter JSON", err);
      }
    }

    // Fetch lesson progress for this student
    const progress = await prisma.lessonProgress.findUnique({
      where: {
        studentId_lessonId: {
          studentId,
          lessonId,
        },
      },
      select: {
        assignmentCompleted: true,
      },
    });

    // ===== Fetch assignments =====
    const [total, assignments] = await Promise.all([
      prisma.assignment.count({ where }),
      prisma.assignment.findMany({
        where,
        include: { lesson: true },
        orderBy,
        skip: page * pageSize,
        take: pageSize,
      }),
    ]);

    // ===== Add S.No =====
    const formattedAssignments = assignments.map((a, index) => ({
      sno: page * pageSize + index + 1,
      ...a,
      dueDate: a.dueDate ? new Date(a.dueDate).toLocaleDateString() : null,
       status: progress?.assignmentCompleted ? "Completed" : "Pending",
    }));

    res.status(200).json({
      rows: formattedAssignments,
      total,
    });
  } catch (err) {
    console.error("Get assignments by lesson error:", err);
    res.status(500).json({ message: "Server error" });
  }
};

// Delete assignment (teacher or admin)
exports.deleteAssignment = async (req, res) => {
  try {
    const assignmentId = parseInt(req.params.id);
    const assignment = await prisma.assignment.findUnique({
      where: { id: assignmentId },
      include: { subject: true },
    });

    if (!assignment) {
      return res.status(404).json({ message: "Assignment not found" });
    }

    // Only assigned teacher or admin can delete
    if (
      req.user.role !== "admin" &&
      req.user.id !== assignment.subject.teacherId
    ) {
      return res.status(403).json({ message: "Not allowed" });
    }

    await prisma.assignment.delete({
      where: { id: assignmentId },
    });
    return res.json({ message: "Assignment deleted successfully" });
  } catch (err) {
    console.log(err);
    return res.status(500).json({ message: "Server error" });
  }
};

exports.getTeacherAssignments = async (req, res) => {
  try {
    const teacherId = req.user.id;
    const page = parseInt(req.query.page) || 0;
    const pageSize = parseInt(req.query.pageSize) || 10;
    const filter = req.query.filter ? JSON.parse(req.query.filter) : { items: [] };
    const sort = req.query.sort ? JSON.parse(req.query.sort) : [];

    // ===== Build where clause =====
    let where = { teacherId };

    filter.items.forEach((item) => {
      if (item.value) {
        switch (item.field) {
          case "title":
            where.title = { contains: item.value, mode: "insensitive" };
            break;
          case "subjectTitle":
            where.subject = { is: { title: { contains: item.value, mode: "insensitive" } } };
            break;
          case "lessonTitle":
            where.lesson = { is: { title: { contains: item.value, mode: "insensitive" } } };
            break;
          default:
            break;
        }
      }
    });

    // ===== Sorting =====
    let orderBy = sort.map((s) => ({ [s.field]: s.sort }));

    // ===== Fetch total count =====
    const total = await prisma.assignment.count({ where });

    // ===== Fetch paginated data =====
    const rows = await prisma.assignment.findMany({
      where,
      include: {
        subject: true,
        lesson: true,
      },
      orderBy: orderBy.length > 0 ? orderBy : undefined,
      skip: page * pageSize,
      take: pageSize,
    });

    const formattedAssignments = rows.map((a, index) => ({
      sno: page * pageSize + index + 1,
      ...a,
      dueDate: a.dueDate ? new Date(a.dueDate).toLocaleDateString() : null,
      subjectTitle: a.subject?.title || "",
      lessonTitle: a.lesson?.title || "",
    }));

    return res.json({ rows: formattedAssignments, total });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "Server error" });
  }
};

exports.getAssignmentById = async (req, res) => {
  try {
    const assignmentId = parseInt(req.params.id);
    const studentId = req.user.id;
    const userRole = req.user.role; // assuming you have role in req.user

    // 1️⃣ Fetch assignment + lesson info
    const assignment = await prisma.assignment.findUnique({
      where: { id: assignmentId },
      include: {
        lesson: {
          select: {
            id: true,
            title: true,
            subjectId: true,
          },
        },
      },
    });

    if (!assignment) {
      return res.status(404).json({ message: "Assignment not found" });
    }

    // 2️⃣ Fetch logged-in student's submission
    const mySubmission = await prisma.submission.findFirst({
      where: {
        assignmentId: assignmentId,
        studentId: studentId,
      },
    });

    // 3️⃣ If teacher/admin, fetch all submissions
    let submissions = [];
    if (["teacher", "admin"].includes(userRole)) {
      submissions = await prisma.submission.findMany({
        where: { assignmentId },
        include: {
          student: {
            select: { id: true, firstName: true, lastName: true, email: true },
          },
        },
        orderBy: { submittedAt: "desc" },
      });
    }

    // 4️⃣ Optional: check lesson progress for student
    let lessonProgress = null;
    if (userRole === "student") {
      lessonProgress = await prisma.lessonProgress.findFirst({
        where: {
          lessonId: assignment.lessonId,
          studentId,
        },
        select: { assignmentCompleted: true },
      });
    }

    // 5️⃣ Send final response
    res.json({
      id: assignment.id,
      title: assignment.title,
      description: assignment.description,
      fileUrl: assignment.fileUrl,
      dueDate: assignment.dueDate,
      lessonId: assignment.lessonId,
      lessonTitle: assignment.lesson.title,
      subjectId: assignment.lesson.subjectId,
      status: mySubmission ? "Completed" : lessonProgress?.assignmentCompleted ? "Completed" : "Pending",
      mySubmission, // student-specific submission
      submissions, // all submissions (teacher/admin view)
    });
  } catch (error) {
    console.error("Get assignment by id error:", error);
    res.status(500).json({ message: "Server error" });
  }
};
