import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireAnyRole, MEMBER_ROLES } from "@/lib/auth";

function monthStart(): Date {
  const now = new Date();
  return new Date(now.getFullYear(), now.getMonth(), 1);
}

/** Role-aware overview for the shared member portal (/me). */
export async function GET() {
  const session = await requireAnyRole(MEMBER_ROLES);
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const user = await prisma.user.findUnique({
    where: { id: session.userId },
    select: {
      id: true,
      name: true,
      username: true,
      role: true,
      institution: { select: { id: true, name: true, code: true, type: true } },
      studentProfile: {
        select: {
          id: true, roll: true, name: true, nameBn: true, gender: true, dob: true,
          guardianName: true, guardianPhone: true, address: true, status: true,
          classItemId: true, sectionItemId: true,
          classItem: { select: { name: true, nameBn: true } },
          sectionItem: { select: { name: true, nameBn: true } },
          shiftItem: { select: { name: true, nameBn: true } },
          groupItem: { select: { name: true, nameBn: true } },
        },
      },
      parentOfStudent: {
        select: {
          id: true, roll: true, name: true, nameBn: true, gender: true, dob: true,
          guardianName: true, guardianPhone: true, address: true, status: true,
          classItemId: true, sectionItemId: true,
          classItem: { select: { name: true, nameBn: true } },
          sectionItem: { select: { name: true, nameBn: true } },
          shiftItem: { select: { name: true, nameBn: true } },
          groupItem: { select: { name: true, nameBn: true } },
        },
      },
      staff: {
        select: {
          id: true, employeeCode: true, name: true, nameBn: true, designation: true,
          department: true, phone: true, email: true, joinDate: true, status: true,
        },
      },
    },
  });

  if (!user || !user.institution) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const [notices, selections] = await Promise.all([
    prisma.notice.findMany({
      where: {
        institutionId: user.institution.id,
        isActive: true,
        // audience-aware: students/parents see ALL/STUDENTS, staff see ALL/STAFF
        audience: {
          in: user.role === "STUDENT" || user.role === "PARENT" ? ["ALL", "STUDENTS"] : ["ALL", "STAFF"],
        },
        OR: [{ expiryDate: null }, { expiryDate: { gte: new Date() } }],
      },
      orderBy: [{ isPinned: "desc" }, { publishDate: "desc" }],
      take: 8,
      select: { id: true, title: true, titleBn: true, body: true, publishDate: true, isPinned: true },
    }),
    // Name lookup for schedule FK columns (ClassSchedule has no item relations)
    prisma.academicSelection.findMany({
      where: { institutionId: user.institution.id },
      select: { academicItem: { select: { id: true, name: true, nameBn: true } } },
    }),
  ]);

  const names = new Map(
    selections.map((s) => [s.academicItem.id, { name: s.academicItem.name, nameBn: s.academicItem.nameBn }])
  );
  const label = (id: number | null) => (id ? names.get(id)?.name ?? null : null);
  const labelBn = (id: number | null) => (id ? names.get(id)?.nameBn ?? null : null);

  const base = {
    role: user.role,
    name: user.name,
    username: user.username,
    institution: user.institution,
    notices,
  };

  // ---------- Student & Parent: the (child) student's dashboard ----------
  const student = user.role === "STUDENT" ? user.studentProfile : user.parentOfStudent;
  if (user.role === "STUDENT" || user.role === "PARENT") {
    if (!student) return NextResponse.json({ error: "NO_LINKED_STUDENT" }, { status: 409 });

    const [attendance, feeAgg, markRows, routine] = await Promise.all([
      prisma.studentAttendance.findMany({
        where: { studentId: student.id, date: { gte: monthStart() } },
        select: { status: true },
      }),
      Promise.all([
        prisma.feeSchedule.aggregate({ where: { studentId: student.id }, _sum: { amount: true } }),
        prisma.feeCollection.aggregate({ where: { studentId: student.id }, _sum: { amount: true } }),
      ]),
      prisma.examMark.findMany({
        where: { studentId: student.id, examSchedule: { exam: { resultPublished: true } } },
        orderBy: { updatedAt: "desc" },
        take: 15,
        select: {
          total: true, cq: true, mcq: true, applied: true,
          examSchedule: {
            select: {
              fullMarks: true,
              exam: { select: { name: true, nameBn: true } },
              subjectItem: { select: { name: true, nameBn: true } },
            },
          },
        },
      }),
      prisma.classSchedule.findMany({
        where: {
          institutionId: user.institution.id,
          isActive: true,
          OR: [
            { classItemId: student.classItemId ?? -1 },
            ...(student.sectionItemId ? [{ sectionItemId: student.sectionItemId }] : []),
          ],
        },
        orderBy: { startTime: "asc" },
        select: {
          days: true, startTime: true, endTime: true,
          subjectItemId: true, roomItemId: true,
          staff: { select: { name: true } },
        },
      }),
    ]);

    const counts = { PRESENT: 0, ABSENT: 0, LEAVE: 0 } as Record<string, number>;
    for (const a of attendance) counts[a.status] = (counts[a.status] ?? 0) + 1;
    const marked = attendance.length;
    const percent = marked === 0 ? null : Math.round((counts.PRESENT / marked) * 100);

    const assigned = Number(feeAgg[0]._sum.amount ?? 0);
    const paid = Number(feeAgg[1]._sum.amount ?? 0);

    return NextResponse.json({
      ...base,
      student: {
        ...student,
        attendanceMonth: { ...counts, marked, percent },
        fees: { assigned, paid, due: Math.max(0, assigned - paid) },
        marks: markRows.map((m) => ({
          examName: m.examSchedule.exam.name,
          examNameBn: m.examSchedule.exam.nameBn,
          subjectName: m.examSchedule.subjectItem?.name ?? null,
          subjectNameBn: m.examSchedule.subjectItem?.nameBn ?? null,
          fullMarks: m.examSchedule.fullMarks,
          cq: m.cq, mcq: m.mcq, applied: m.applied, total: m.total,
        })),
        routine: routine.map((r) => ({
          days: r.days,
          startTime: r.startTime,
          endTime: r.endTime,
          subjectName: label(r.subjectItemId),
          subjectNameBn: labelBn(r.subjectItemId),
          roomName: label(r.roomItemId),
          roomNameBn: labelBn(r.roomItemId),
          teacherName: r.staff?.name ?? null,
        })),
      },
      staff: null,
    });
  }

  // ---------- Teacher & Staff: profile + teaching schedule ----------
  const schedule = user.staff
    ? await prisma.classSchedule.findMany({
        where: { institutionId: user.institution.id, isActive: true, staffId: user.staff.id },
        orderBy: { startTime: "asc" },
        select: {
          days: true, startTime: true, endTime: true,
          classItemId: true, sectionItemId: true, subjectItemId: true, roomItemId: true,
        },
      })
    : [];

  return NextResponse.json({
    ...base,
    student: null,
    staff: user.staff
      ? {
          ...user.staff,
          schedule: schedule.map((r) => ({
            days: r.days,
            startTime: r.startTime,
            endTime: r.endTime,
            className: label(r.classItemId),
            classNameBn: labelBn(r.classItemId),
            sectionName: label(r.sectionItemId),
            sectionNameBn: labelBn(r.sectionItemId),
            subjectName: label(r.subjectItemId),
            subjectNameBn: labelBn(r.subjectItemId),
            roomName: label(r.roomItemId),
            roomNameBn: labelBn(r.roomItemId),
          })),
        }
      : null,
  });
}
