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

/** Boarder attendance sheet for a date (?date=YYYY-MM-DD, default today). */
export async function GET(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const url = new URL(req.url);
  const dateParam = url.searchParams.get("date");
  const date = new Date(
    dateParam && /^\d{4}-\d{2}-\d{2}$/.test(dateParam) ? dateParam : new Date().toISOString().slice(0, 10)
  );

  const [members, attendance] = await Promise.all([
    prisma.hostelMember.findMany({
      where: { institutionId: session.institutionId, status: "ACTIVE" },
      orderBy: { id: "asc" },
      select: {
        id: true,
        bedNo: true,
        student: {
          select: {
            roll: true,
            name: true,
            nameBn: true,
            gender: true,
            classItem: { select: { name: true } },
          },
        },
        hostel: { select: { name: true, type: true } },
        room: { select: { roomNo: true } },
      },
    }),
    prisma.hostelAttendance.findMany({
      where: { institutionId: session.institutionId, date },
      select: { memberId: true, status: true, note: true },
    }),
  ]);

  const byMember = new Map(attendance.map((a) => [a.memberId, a]));
  return NextResponse.json({
    date: date.toISOString().slice(0, 10),
    entries: members.map((m) => ({
      memberId: m.id,
      roll: m.student.roll,
      studentName: m.student.name,
      nameBn: m.student.nameBn,
      hostelName: m.hostel.name,
      roomNo: m.room?.roomNo ?? null,
      bedNo: m.bedNo,
      status: byMember.get(m.id)?.status ?? null,
      note: byMember.get(m.id)?.note ?? null,
    })),
    counts: {
      marked: attendance.length,
      present: attendance.filter((a) => a.status === "PRESENT").length,
      absent: attendance.filter((a) => a.status === "ABSENT").length,
      leave: attendance.filter((a) => a.status === "LEAVE").length,
    },
  });
}

/** Save attendance for a date: { date, entries: [{ memberId, status }] }. */
export async function POST(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  const institutionId = session.institutionId;

  try {
    const body = await req.json();
    const dateStr = String(body.date ?? "").slice(0, 10);
    if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
      return NextResponse.json({ error: "Invalid date" }, { status: 400 });
    }
    const date = new Date(dateStr);
    const entries: Array<{ memberId: number; status: string }> = Array.isArray(body.entries)
      ? body.entries
      : [];
    if (entries.length === 0) {
      return NextResponse.json({ error: "No entries" }, { status: 400 });
    }

    const valid = new Set(["PRESENT", "ABSENT", "LEAVE"]);
    const memberIds = new Set(
      (
        await prisma.hostelMember.findMany({
          where: { institutionId },
          select: { id: true },
        })
      ).map((m) => m.id)
    );

    await prisma.$transaction(
      entries
        .filter((e) => memberIds.has(Number(e.memberId)) && valid.has(e.status))
        .map((e) =>
          prisma.hostelAttendance.upsert({
            where: { memberId_date: { memberId: Number(e.memberId), date } },
            update: { status: e.status as "PRESENT" | "ABSENT" | "LEAVE" },
            create: {
              institutionId,
              memberId: Number(e.memberId),
              date,
              status: e.status as "PRESENT" | "ABSENT" | "LEAVE",
            },
          })
        )
    );

    return NextResponse.json({ success: true, saved: entries.length });
  } catch {
    return NextResponse.json({ error: "Could not save attendance" }, { status: 500 });
  }
}
