import { prisma } from "@pmap/database";
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) as { token?: string } | null;
  if (!body?.token) return fail(request, "TOKEN_REQUIRED", "A QR token is required.", 422);
  const lookup = await resolveQrLookup(body.token);

  const credential = await prisma.qrCredential.findUnique({
    where: { tokenHash: lookup.tokenHash },
    include: { participant: true }
  });

  if (!credential || !credential.isActive) return fail(request, "INVALID_QR", "QR credential is invalid.", 404);
  if (lookup.reference && credential.participant.registrationReference !== lookup.reference) return fail(request, "REFERENCE_MISMATCH", "QR reference does not match the credential.", 409);
  if (credential.revokedAt) return fail(request, "REVOKED_QR", "QR credential has been revoked.", 409);
  if (credential.expiresAt && credential.expiresAt < new Date()) return fail(request, "EXPIRED_QR", "QR credential has expired.", 409);

  return ok(request, {
    participantId: credential.participantId,
    registrationReference: credential.participant.registrationReference,
    participantName: `${credential.participant.firstName} ${credential.participant.lastName}`,
    verificationStatus: credential.participant.verificationStatus
  });
}
