import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireRole } from "@/lib/auth";

/** Institution dashboard overview. */
export async function GET() {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const institution = await prisma.institution.findUnique({
    where: { id: session.institutionId },
    include: {
      subscriptions: {
        where: { status: "ACTIVE" },
        orderBy: { createdAt: "desc" },
        take: 1,
        include: {
          packagePlan: { select: { name: true, nameBn: true, durationMonths: true } },
          payments: { select: { amount: true } },
        },
      },
      _count: { select: { academicSelections: true, requests: true } },
    },
  });

  if (!institution) return NextResponse.json({ error: "Institution not found" }, { status: 404 });

  const id = institution.id;
  const startOfToday = new Date();
  startOfToday.setHours(0, 0, 0, 0);
  const startOfMonth = new Date(startOfToday.getFullYear(), startOfToday.getMonth(), 1);

  const [selectionCounts, notices, events, fees, feeTotalAgg, feeMonthAgg, studentCount, staffCount, admissionCount, ticketCounts, recentTickets] =
    await Promise.all([
      prisma.academicSelection.groupBy({
        by: ["academicItemId"],
        where: { institutionId: id },
      }),
      prisma.notice.findMany({
        where: { institutionId: id, isActive: true },
        orderBy: [{ isPinned: "desc" }, { publishDate: "desc" }],
        take: 4,
        select: { id: true, title: true, titleBn: true, publishDate: true, isPinned: true },
      }),
      prisma.eventItem.findMany({
        where: { institutionId: id, isActive: true, startDate: { gte: startOfToday } },
        orderBy: { startDate: "asc" },
        take: 4,
        select: { id: true, title: true, titleBn: true, startDate: true, endDate: true, venue: true },
      }),
      prisma.feeCollection.findMany({
        where: { institutionId: id },
        orderBy: { paidAt: "desc" },
        take: 5,
        select: {
          id: true,
          invoiceNo: true,
          amount: true,
          method: true,
          paidAt: true,
          student: { select: { name: true, roll: true } },
        },
      }),
      prisma.feeCollection.aggregate({
        where: { institutionId: id },
        _sum: { amount: true },
      }),
      prisma.feeCollection.aggregate({
        where: { institutionId: id, paidAt: { gte: startOfMonth } },
        _sum: { amount: true },
      }),
      prisma.student.count({ where: { institutionId: id, status: "ACTIVE" } }),
      prisma.staff.count({ where: { institutionId: id, status: "ACTIVE" } }),
      prisma.admission.count({ where: { institutionId: id, status: "PENDING" } }),
      prisma.supportTicket.groupBy({ by: ["status"], where: { institutionId: id }, _count: true }),
      prisma.supportTicket.findMany({
        where: { institutionId: id },
        orderBy: { updatedAt: "desc" },
        take: 5,
        select: { id: true, subject: true, status: true, updatedAt: true },
      }),
    ]);

  const items = await prisma.academicItem.findMany({
    where: { id: { in: selectionCounts.map((s) => s.academicItemId) } },
    select: { category: true },
  });

  const categoryCounts: Record<string, number> = {};
  for (const item of items) {
    categoryCounts[item.category] = (categoryCounts[item.category] ?? 0) + 1;
  }

  const subscription = institution.subscriptions[0] ?? null;
  const totalAmount = subscription ? Number(subscription.totalAmount) : 0;
  const paid = subscription
    ? subscription.payments.reduce((sum, p) => sum + Number(p.amount), 0)
    : 0;
  const daysLeft = subscription
    ? Math.max(0, Math.ceil((subscription.endDate.getTime() - startOfToday.getTime()) / 86_400_000))
    : 0;

  // Demo environments show the audience how long their access window runs —
  // the central admin granted it for a limited number of days.
  const demoGrant = await prisma.demoRequest.findFirst({
    where: { demoInstitutionId: id, demoExpiresAt: { not: null } },
    select: { demoExpiresAt: true, validDays: true },
  });
  const demoAccess = demoGrant?.demoExpiresAt
    ? {
        expiresAt: demoGrant.demoExpiresAt,
        validDays: demoGrant.validDays,
        daysLeft: Math.max(
          0,
          Math.ceil((demoGrant.demoExpiresAt.getTime() - Date.now()) / 86_400_000),
        ),
      }
    : null;

  return NextResponse.json({
    institution: {
      id: institution.id,
      name: institution.name,
      type: institution.type,
      status: institution.status,
      email: institution.email,
      phone: institution.phone,
      address: institution.address,
      createdAt: institution.createdAt,
    },
    subscription: subscription
      ? {
          id: subscription.id,
          planName: subscription.packagePlan?.name ?? (subscription.studentRange ? `${subscription.studentRange} Students` : "IncrelogEMS Package"),
          planNameBn: subscription.packagePlan?.nameBn ?? (subscription.studentRange ? `${subscription.studentRange} শিক্ষার্থী` : "ইনক্রিলগইএমএস প্যাকেজ"),
          durationMonths: subscription.packagePlan?.durationMonths ?? 12,
          startDate: subscription.startDate,
          endDate: subscription.endDate,
          totalAmount,
          paid,
          due: Math.max(0, totalAmount - paid),
          daysLeft,
        }
      : null,
    academicCounts: categoryCounts,
    totalSelected: institution._count.academicSelections,
    demoAccess,
    counts: {
      students: studentCount,
      staff: staffCount,
      pendingAdmissions: admissionCount,
      notices: notices.length,
      events: events.length,
    },
    fees: {
      collectedTotal: feeTotalAgg._sum.amount ? Number(feeTotalAgg._sum.amount) : 0,
      collectedThisMonth: feeMonthAgg._sum.amount ? Number(feeMonthAgg._sum.amount) : 0,
      recent: fees.map((f) => ({
        id: f.id,
        invoiceNo: f.invoiceNo,
        amount: Number(f.amount),
        method: f.method,
        paidAt: f.paidAt,
        studentName: f.student.name,
        studentRoll: f.student.roll,
      })),
    },
    recentNotices: notices,
    upcomingEvents: events,
    support: {
      counts: {
        OPEN: ticketCounts.find((c) => c.status === "OPEN")?._count ?? 0,
        IN_PROGRESS: ticketCounts.find((c) => c.status === "IN_PROGRESS")?._count ?? 0,
        RESOLVED: ticketCounts.find((c) => c.status === "RESOLVED")?._count ?? 0,
        CLOSED: ticketCounts.find((c) => c.status === "CLOSED")?._count ?? 0,
      },
      recent: recentTickets,
    },
  });
}
