import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { ingestPunches, type PunchInput } from "@/lib/device-punch";

/**
 * Device push ingest — the GENERIC_HTTP edge. Machines (or a middleware/
 * gateway) POST punches with an `x-api-key` header matching a registered
 * machine's key. Body shape is flexible; common field names are tried, and
 * a machine's pushFieldMap can override the paths:
 *   { identifier | cardNo | badgeNumber | userId, timestamp | time | punchedAt }
 * A single punch object or a `punches` array is accepted.
 */
export async function POST(req: Request) {
  const apiKey = req.headers.get("x-api-key") ?? "";
  if (!apiKey) return NextResponse.json({ error: "API key required" }, { status: 401 });

  const machine = await prisma.attendanceMachine.findUnique({ where: { apiKey } });
  if (!machine || !machine.isActive) {
    return NextResponse.json({ error: "Invalid API key" }, { status: 401 });
  }

  let body: Record<string, unknown>;
  try {
    body = (await req.json()) as Record<string, unknown>;
  } catch {
    return NextResponse.json({ error: "JSON body required" }, { status: 400 });
  }

  const map = (machine.pushFieldMap as Record<string, string> | null) ?? {};
  const idPath = map.identifier ?? "identifier";
  const timePath = map.timestamp ?? "timestamp";

  const get = (obj: Record<string, unknown>, path: string): unknown =>
    path.split(".").reduce<unknown>((acc, k) => (acc && typeof acc === "object" ? (acc as Record<string, unknown>)[k] : undefined), obj);

  const rawList: Record<string, unknown>[] = Array.isArray(body.punches)
    ? (body.punches as Record<string, unknown>[])
    : [body];

  const punches: PunchInput[] = [];
  for (const item of rawList) {
    const identifier = String(
      get(item, idPath) ?? item.cardNo ?? item.badgeNumber ?? item.userId ?? item.id ?? ""
    ).trim();
    const t =
      get(item, timePath) ?? item.time ?? item.punchedAt ?? item.recordTime ?? item.dateTime;
    const punchedAt = t ? new Date(String(t).replace(" ", "T")) : new Date();
    if (!identifier) continue;
    punches.push({
      institutionId: machine.institutionId,
      machineId: machine.id,
      source: "HTTP_PUSH",
      identifier,
      punchedAt: isNaN(punchedAt.getTime()) ? new Date() : punchedAt,
      machineUserId: item.userId != null ? String(item.userId) : null,
      raw: item,
    });
  }

  const result = await ingestPunches(punches);
  return NextResponse.json({ ok: true, ...result });
}
