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

/** 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 [staff, attendance] = await Promise.all([
    prisma.staff.findMany({
      where: { institutionId: session.institutionId, status: "ACTIVE" },
      orderBy: { id: "asc" },
      select: { id: true, employeeCode: true, name: true, nameBn: true, designation: true, department: true },
    }),
    prisma.staffAttendance.findMany({
      where: { institutionId: session.institutionId, date },
      select: { staffId: true, status: true, note: true },
    }),
  ]);

  const byStaff = new Map(attendance.map((a) => [a.staffId, a]));
  return NextResponse.json({
    date: date.toISOString().slice(0, 10),
    entries: staff.map((s) => ({
      staffId: s.id,
      employeeCode: s.employeeCode,
      name: s.name,
      nameBn: s.nameBn,
      designation: s.designation,
      department: s.department,
      status: byStaff.get(s.id)?.status ?? null,
      note: byStaff.get(s.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: [{ staffId, status }] }. */
export async function POST(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  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<{ staffId: 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 staffIds = new Set(
      (
        await prisma.staff.findMany({
          where: { institutionId: session.institutionId },
          select: { id: true },
        })
      ).map((s) => s.id)
    );

    await prisma.$transaction(
      entries
        .filter((e) => staffIds.has(Number(e.staffId)) && valid.has(e.status))
        .map((e) =>
          prisma.staffAttendance.upsert({
            where: { staffId_date: { staffId: Number(e.staffId), date } },
            update: { status: e.status as "PRESENT" | "ABSENT" | "LEAVE" },
            create: {
              institutionId: session.institutionId!,
              staffId: Number(e.staffId),
              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 });
  }
}
