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

const getDashboardData = async (req, res) => {
  try {
    // Users
    const totalUsers = await prisma.user.count();
    const activeUsers = await prisma.user.count({
      where: {
        lastActivity: {
          gte: new Date(Date.now() - 24 * 60 * 60 * 1000), // last 24 hours
        },
      },
    });
    // Payments
    const totalPayments = await prisma.paymentRequest.count();
    const revenueAgg = await prisma.paymentRequest.aggregate({
      where: { status: "approved" }, // only approved payments
      _sum: { amount: true },
    });

    const revenue = revenueAgg._sum.amount || 0;

    // Subjects
    const totalSubjects = await prisma.subject.count();

    // User Stats (Monthly)
    const users = await prisma.user.findMany({
      select: { createdAt: true },
    });

    // Aggregate users by month/year
    const userStatsMap = {};

    users.forEach((u) => {
      const date = new Date(u.createdAt);
      const monthYear = `${date.getMonth() + 1}/${date.getFullYear()}`; // e.g., "12/2025"
      if (!userStatsMap[monthYear]) {
        userStatsMap[monthYear] = 0;
      }
      userStatsMap[monthYear]++;
    });

    // Convert to array for frontend
    const userStatsFormatted = Object.entries(userStatsMap).map(
      ([month, count]) => ({
        month,
        count,
      })
    );

    // Sort by date ascending
    userStatsFormatted.sort((a, b) => {
      const [monthA, yearA] = a.month.split("/").map(Number);
      const [monthB, yearB] = b.month.split("/").map(Number);
      return (
        new Date(yearA, monthA - 1).getTime() -
        new Date(yearB, monthB - 1).getTime()
      );
    });

    // Payment Stats (Pie)
    const paymentStatsRaw = await prisma.paymentRequest.groupBy({
      by: ["status"], // Group by 'status' field
      _sum: { amount: true }, // Sum the 'amount' in each group
      where: {
        // Optional: only include approved/payments you care about
        status: { in: ["approved", "pending", "rejected"] },
      },
    });

    const paymentStats = paymentStatsRaw.map((p) => ({
      label: p.status.charAt(0).toUpperCase() + p.status.slice(1), // Capitalize for chart
      value: p._sum.amount || 0, // Handle null
    }));

    // Subject Enrollments (Bar)
    const subjectEnrollmentsRaw = await prisma.enrollment.groupBy({
      by: ["subjectId"],
      _count: { id: true },
    });

    // Fetch all subjects at once
    const subjectIds = subjectEnrollmentsRaw.map((s) => s.subjectId);
    const subjects = await prisma.subject.findMany({
      where: { id: { in: subjectIds } },
    });

    const subjectEnrollments = subjectEnrollmentsRaw.map((s) => {
      const subject = subjects.find((sub) => sub.id === s.subjectId);
      return {
        subject: subject?.title || "Unknown",
        enrollments: s._count.id,
      };
    });

    // Recent Activity
    const recentPayments = await prisma.paymentRequest.findMany({
      take: 5,
      orderBy: { createdAt: "desc" },
      include: { student: true, subject: true },
    });

    res.json({
      totalUsers,
      activeUsers,
      totalPayments,
      revenue,
      totalSubjects,
      userStats: userStatsFormatted,
      paymentStats,
      subjectEnrollments,
      recentPayments,
    });
  } catch (err) {
    console.error(err);
    res
      .status(500)
      .json({ message: "Failed to load dashboard data", error: err.message });
  }
};

const getStudentDashboard = async (req, res) => {
  try {
    const user = req.user;

    if (user.role !== "student") {
      return res.status(403).json({ message: "Unauthorized" });
    }

    // 1️⃣ Fetch enrolled subjects
    const enrollments = await prisma.enrollment.findMany({
      where: { studentId: user.id },
      include: { subject: true },
    });

    const enrolledSubjectIds = enrollments.map((e) => e.subjectId);

    if (!enrolledSubjectIds.length) {
      return res
        .status(403)
        .json({ message: "You are not enrolled in any subjects" });
    }

    // 2️⃣ Fetch assignments for enrolled subjects
    const assignments = await prisma.assignment.findMany({
      where: { lesson: { subjectId: { in: enrolledSubjectIds } } },
      include: {
        lesson: { include: { subject: true } },
        submissions: { where: { studentId: user.id } },
      },
      orderBy: { createdAt: "desc" },
    });

    const assignmentsRows = assignments.map((a, i) => ({
      id: a.id,
      sno: i + 1,
      assignmentTitle: a.title,
      lessonTitle: a.lesson?.title || "-",
      subjectTitle: a.lesson?.subject?.title || "-",
      submittedAt: a.submissions?.[0]?.submittedAt || null,
      status: a.submissions?.[0]?.status || "pending",
      marks: a.submissions?.[0]?.marks ?? null,
      feedback: a.submissions?.[0]?.feedback || "-",
    }));

    // 3️⃣ Fetch teachers for enrolled subjects
    const teacherIds = [
      ...new Set(enrollments.map((e) => e.subject?.teacherId).filter(Boolean)),
    ];

    // Only select fields that exist in your User model
    const teachers = await prisma.user.findMany({
      where: { id: { in: teacherIds } },
      select: { id: true, firstName: true, lastName: true },
    });

    // 4️⃣ Prepare stats
    const stats = {
      studentName: `${user.firstName} ${user.lastName}`,
      totalSubjects: enrolledSubjectIds.length,
      totalAssignments: assignments.length,
      totalSubmitted: assignments.filter((a) => a.submissions?.length).length,
      totalPending: assignments.filter((a) => !a.submissions?.length).length,
      enrolledCourses: enrollments.map((e) => ({
        id: e.subject?.id,
        title: e.subject?.title,
        thumbnailUrl: e.subject?.thumbnailUrl || "/default-thumbnail.png", // ✅ add thumbnail
      })),
      teachers: teachers.map((t) => ({
        id: t.id,
        name: `${t.firstName} ${t.lastName}`,
        avatar: `/static/images/avatar/${t.id}.jpg`, // default avatar path
      })),
    };

    // 5️⃣ Recent submissions for activity
    const recentSubmissions = await prisma.submission.findMany({
      where: { studentId: user.id },
      take: 5,
      orderBy: { submittedAt: "desc" },
      include: {
        assignment: { include: { lesson: { include: { subject: true } } } },
      },
    });

    const recentActivity = recentSubmissions.map((s) => ({
      assignmentTitle: s.assignment?.title || "-",
      lessonTitle: s.assignment?.lesson?.title || "-",
      subjectTitle: s.assignment?.lesson?.subject?.title || "-",
      submittedAt: s.submittedAt,
      status: s.status,
      marks: s.marks,
      feedback: s.feedback || "-",
    }));

    // 6️⃣ Send final response
    res.json({
      assignmentsRows,
      stats,
      recentActivity,
    });
  } catch (err) {
    console.error(err);
    res.status(500).json({
      message: "Failed to load student dashboard",
      error: err.message,
    });
  }
};

const getTeacherDashboard = async (req, res) => {
  try {
    const teacherId = req.user.id;

    // 1️⃣ Teacher basic info
    const teacher = await prisma.user.findUnique({
      where: { id: teacherId },
      select: { firstName: true, lastName: true },
    });

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

    // 2️⃣ Teacher subjects
    const subjects = await prisma.subject.findMany({
      where: { teacherId },
      select: { id: true },
    });

    const subjectIds = subjects.map((s) => s.id);

    // 3️⃣ Total students (unique)
    const totalStudents = await prisma.enrollment.count({
      where: { subjectId: { in: subjectIds }, status: "active" },
    });

    // 4️⃣ Pending submissions
    const totalPendingAssignments = await prisma.submission.count({
      where: { assignment: { teacherId }, status: "pending" },
    });

    // 5️⃣ Active live classes
    const activeLiveClasses = await prisma.liveClass.count({
      where: { teacherId, startTime: { gte: new Date() } },
    });

    // 6️⃣ Recent assignment submissions
    const recentSubmissions = await prisma.submission.findMany({
      where: { assignment: { teacherId } },
      orderBy: { submittedAt: "desc" },
      take: 5,
      include: {
        student: { select: { firstName: true, lastName: true } },
        assignment: { select: { title: true } },
      },
    });

    const recentActivity = recentSubmissions.map((s) => ({
      assignmentTitle: s.assignment.title,
      studentName: `${s.student.firstName} ${s.student.lastName}`,
      status: s.status,
      marks: s.marks,
      submittedAt: s.submittedAt,
    }));

    // 7️⃣ Upcoming live classes
    const upcomingLiveClasses = await prisma.liveClass.findMany({
      where: {
        teacherId,
        startTime: { gte: new Date() },
      },
      orderBy: { startTime: "asc" },
      take: 1,
      select: {
        id: true,
        startTime: true,
        endTime: true,
        meetingUrl: true,
        subject: {
          select: {
            title: true, // <--- this is the class "name"
          },
        },
      },
    });

    const notices = await prisma.notification.findMany({
      where: { userId: teacherId }, // only for this teacher
      orderBy: { createdAt: "desc" },
      take: 5, // show last 5 notifications
      include: {
        sender: { select: { firstName: true, lastName: true } }, // get sender info
        user: { select: { firstName: true, lastName: true } },
      },
    });

    const formattedNotices = notices.map((n) => ({
      id: n.id,
      title: n.message,
      date: n.createdAt,
      isRead: n.isRead,
      sender: n.sender
        ? { firstName: n.sender.firstName, lastName: n.sender.lastName }
        : undefined,
      recipients:
        n.user && n.user.length > 0
          ? {firstName : n.sender.firstName, lastName: n.sender.lastName}
          : [],
    }));

    res.json({
      stats: {
        teacherName: `${teacher.firstName} ${teacher.lastName}`,
        totalStudents,
        totalCourses: subjects.length,
        totalPendingAssignments,
        activeLiveClasses,
      },
      recentActivity,
      upcomingLiveClasses,
      notices: formattedNotices,
    });
  } catch (err) {
    console.error("Teacher dashboard error:", err);
    res.status(500).json({ message: "Failed to load teacher dashboard" });
  }
};

const getAccountantDashboardData = async (req, res) => {
  try {
    const accountant = await prisma.user.findUnique({
      where: { id: req.user.id },
      select: { firstName: true, lastName: true },
    });

    // Users
    const totalUsers = await prisma.user.count();
    const activeUsers = await prisma.user.count({
      where: {
        lastActivity: {
          gte: new Date(Date.now() - 24 * 60 * 60 * 1000), // last 24 hours
        },
      },
    });
    // Payments
    const totalPayments = await prisma.paymentRequest.count();
    const revenueAgg = await prisma.paymentRequest.aggregate({
      where: { status: "approved" }, // only approved payments
      _sum: { amount: true },
    });

    const revenue = revenueAgg._sum.amount || 0;

    // Subjects
    const totalSubjects = await prisma.subject.count();

    // User Stats (Monthly)
    const users = await prisma.user.findMany({
      select: { createdAt: true },
    });

    // Aggregate users by month/year
    const userStatsMap = {};

    users.forEach((u) => {
      const date = new Date(u.createdAt);
      const monthYear = `${date.getMonth() + 1}/${date.getFullYear()}`; // e.g., "12/2025"
      if (!userStatsMap[monthYear]) {
        userStatsMap[monthYear] = 0;
      }
      userStatsMap[monthYear]++;
    });

    // Convert to array for frontend
    const userStatsFormatted = Object.entries(userStatsMap).map(
      ([month, count]) => ({
        month,
        count,
      })
    );

    // Sort by date ascending
    userStatsFormatted.sort((a, b) => {
      const [monthA, yearA] = a.month.split("/").map(Number);
      const [monthB, yearB] = b.month.split("/").map(Number);
      return (
        new Date(yearA, monthA - 1).getTime() -
        new Date(yearB, monthB - 1).getTime()
      );
    });

    // Payment Stats (Pie)
    const paymentStatsRaw = await prisma.paymentRequest.groupBy({
      by: ["status"], // Group by 'status' field
      _sum: { amount: true }, // Sum the 'amount' in each group
      where: {
        // Optional: only include approved/payments you care about
        status: { in: ["approved", "pending", "rejected"] },
      },
    });

    const paymentStats = paymentStatsRaw.map((p) => ({
      label: p.status.charAt(0).toUpperCase() + p.status.slice(1), // Capitalize for chart
      value: p._sum.amount || 0, // Handle null
    }));

    // Subject Enrollments (Bar)
    const subjectEnrollmentsRaw = await prisma.enrollment.groupBy({
      by: ["subjectId"],
      _count: { id: true },
    });

    // Fetch all subjects at once
    const subjectIds = subjectEnrollmentsRaw.map((s) => s.subjectId);
    const subjects = await prisma.subject.findMany({
      where: { id: { in: subjectIds } },
    });

    const subjectEnrollments = subjectEnrollmentsRaw.map((s) => {
      const subject = subjects.find((sub) => sub.id === s.subjectId);
      return {
        subject: subject?.title || "Unknown",
        enrollments: s._count.id,
      };
    });

    // Recent Activity
    const recentPayments = await prisma.paymentRequest.findMany({
      take: 5,
      orderBy: { createdAt: "desc" },
      include: { student: true, subject: true },
    });

    res.json({
      accountantName: `${accountant.firstName} ${accountant.lastName}`,
      totalUsers,
      activeUsers,
      totalPayments,
      revenue,
      totalSubjects,
      userStats: userStatsFormatted,
      paymentStats,
      subjectEnrollments,
      recentPayments,
    });
  } catch (err) {
    console.error(err);
    res
      .status(500)
      .json({ message: "Failed to load dashboard data", error: err.message });
  }
};

module.exports = {
  getDashboardData,
  getStudentDashboard,
  getTeacherDashboard,
  getAccountantDashboardData,
};
