import { prisma } from "@pmap/database";
import { scanSchema } from "@pmap/validation";
import { fail, ok } from "../../_lib";

async function sha256(value: string): Promise<string> {
  const bytes = new TextEncoder().encode(value);
  const hash = await crypto.subtle.digest("SHA-256", bytes);
  return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}

async function resolveQrLookup(value: string) {
  try {
    const parsed = JSON.parse(value) as { reference?: unknown; tokenHash?: unknown; token?: unknown };
    if (typeof parsed.tokenHash === "string") return { tokenHash: parsed.tokenHash, reference: typeof parsed.reference === "string" ? parsed.reference : "" };
    if (typeof parsed.token === "string") return { tokenHash: await sha256(parsed.token), reference: typeof parsed.reference === "string" ? parsed.reference : "" };
  } catch {
    return { tokenHash: await sha256(value), reference: "" };
  }
  return { tokenHash: await sha256(value), reference: "" };
}

export async function POST(request: Request) {
  const body = await request.json().catch(() => null);
  const parsed = scanSchema.safeParse(body);
  if (!parsed.success) return fail(request, "VALIDATION_ERROR", "Invalid scan request.", 422, parsed.error.flatten());

  const existing = await prisma.scanEvent.findUnique({ where: { clientScanId: parsed.data.clientScanId } });
  if (existing) return ok(request, { result: existing.result, message: existing.message, idempotentReplay: true });

  const lookup = await resolveQrLookup(parsed.data.token);
  const credential = await prisma.qrCredential.findUnique({
    where: { tokenHash: lookup.tokenHash },
    include: { participant: true }
  });
  const station = await prisma.scannerStation.findUnique({ where: { id: parsed.data.scannerStationId } });

  if (!station?.active) return fail(request, "INACTIVE_STATION", "Scanner station is inactive.", 403);
  if (!credential || !credential.isActive || credential.revokedAt || (credential.expiresAt && credential.expiresAt < new Date())) {
    return fail(request, "INVALID_QR", "QR credential is not valid for attendance.", 409);
  }
  if (lookup.reference && credential.participant.registrationReference !== lookup.reference) {
    return fail(request, "REFERENCE_MISMATCH", "QR reference does not match the credential.", 409);
  }
  if (credential.participant.verificationStatus !== "VERIFIED") {
    return fail(request, "UNVERIFIED_PARTICIPANT", "Participant is not verified.", 409);
  }

  const event = await prisma.scanEvent.create({
    data: {
      clientScanId: parsed.data.clientScanId,
      participantId: credential.participantId,
      scannerId: station.id,
      sessionId: parsed.data.sessionId ?? station.sessionId,
      scanType: parsed.data.scanMode,
      result: "SUCCESS",
      message: "Scan accepted.",
      scannedAt: new Date()
    }
  });

  await prisma.attendanceRecord.create({
    data: {
      participantId: credential.participantId,
      sessionId: parsed.data.sessionId ?? station.sessionId,
      scannerId: station.id,
      status: "PRESENT",
      source: "SCAN"
    }
  });

  return ok(request, { result: event.result, message: event.message, idempotentReplay: false });
}
