import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireRole } from "@/lib/auth";
import { registerCredential } from "@/lib/device-punch";

/* Card & ID Registry — pre-registered identifier → person mappings, so
   punches match from day one instead of waiting in the unmatched queue.
   (AUTO rows are learned from punch mapping; MANUAL rows are entered here.) */

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

  const credentials = await prisma.attendanceCredential.findMany({
    where: { institutionId: session.institutionId },
    orderBy: { identifier: "asc" },
    include: {
      student: { select: { roll: true, name: true, nameBn: true, rfidCardNo: true } },
      staff: { select: { employeeCode: true, name: true, nameBn: true } },
    },
  });

  return NextResponse.json({
    credentials: credentials.map((c) => ({
      id: c.id,
      identifier: c.identifier,
      machineUserId: c.machineUserId,
      source: c.source,
      student: c.student
        ? { roll: c.student.roll, name: c.student.name, nameBn: c.student.nameBn, rfidCardNo: c.student.rfidCardNo }
        : null,
      staff: c.staff ? { employeeCode: c.staff.employeeCode, name: c.staff.name, nameBn: c.staff.nameBn } : null,
      studentId: c.studentId,
      staffId: c.staffId,
    })),
  });
}

/** Register (or re-point) a card/ID for a student or staff member. */
export async function POST(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session?.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = (await req.json().catch(() => ({}))) as Record<string, unknown>;
    const identifier = String(body.identifier ?? "").trim();
    const studentId = body.studentId ? Number(body.studentId) : null;
    const staffId = body.staffId ? Number(body.staffId) : null;
    const machineUserId = String(body.machineUserId ?? "").trim() || null;

    if (!identifier) return NextResponse.json({ error: "IDENTIFIER_REQUIRED" }, { status: 400 });
    if ((studentId ? 1 : 0) + (staffId ? 1 : 0) !== 1) {
      // exactly one of the two must be set
      return NextResponse.json({ error: "PERSON_REQUIRED" }, { status: 400 });
    }

    // the person must belong to this institution
    if (studentId) {
      const student = await prisma.student.findFirst({
        where: { id: studentId, institutionId: session.institutionId },
        select: { id: true },
      });
      if (!student) return NextResponse.json({ error: "PERSON_NOT_FOUND" }, { status: 404 });
    }
    if (staffId) {
      const staff = await prisma.staff.findFirst({
        where: { id: staffId, institutionId: session.institutionId },
        select: { id: true },
      });
      if (!staff) return NextResponse.json({ error: "PERSON_NOT_FOUND" }, { status: 404 });
    }

    const result = await registerCredential({
      institutionId: session.institutionId,
      identifier,
      studentId,
      staffId,
      machineUserId,
    });

    // keep the student's RFID card no in sync when asked (default: yes).
    // (cardNo stays untouched — that's the printed ID no, identification only)
    if (studentId && body.saveToStudent !== false) {
      await prisma.student.update({
        where: { id: studentId },
        data: { rfidCardNo: identifier.toUpperCase() },
      }).catch(() => undefined);
    }

    return NextResponse.json(result);
  } catch {
    return NextResponse.json({ error: "Could not save card" }, { status: 500 });
  }
}
