// Lightweight WebAuthn helpers for biometric (or platform-authenticator) unlock.
// The credential proves "this device + user is present". We pair it with the
// PIN-derived key stored locally so biometric unlock is offline & instant.

export function isBiometricSupported(): boolean {
  return typeof window !== "undefined" && !!window.PublicKeyCredential;
}

function b64urlFromBuf(buf: ArrayBuffer): string {
  const bytes = new Uint8Array(buf);
  let s = "";
  for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
  return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

function b64urlToBuf(s: string): Uint8Array {
  s = s.replace(/-/g, "+").replace(/_/g, "/");
  while (s.length % 4) s += "=";
  const bin = atob(s);
  const out = new Uint8Array(new ArrayBuffer(bin.length));
  for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
  return out;
}

export async function registerBiometric(userId: string, userName: string): Promise<string> {
  const challenge = crypto.getRandomValues(new Uint8Array(32));
  const cred = (await navigator.credentials.create({
    publicKey: {
      challenge,
      rp: { name: "AppPass" },
      user: {
        id: new TextEncoder().encode(userId),
        name: userName,
        displayName: userName,
      },
      pubKeyCredParams: [
        { type: "public-key", alg: -7 },
        { type: "public-key", alg: -257 },
      ],
      authenticatorSelection: {
        authenticatorAttachment: "platform",
        userVerification: "required",
        residentKey: "preferred",
      },
      timeout: 60_000,
      attestation: "none",
    },
  })) as PublicKeyCredential | null;
  if (!cred) throw new Error("Biometria cancelada");
  return b64urlFromBuf(cred.rawId);
}

export async function verifyBiometric(credentialIdB64Url: string): Promise<boolean> {
  const challenge = crypto.getRandomValues(new Uint8Array(32));
  try {
    const assertion = await navigator.credentials.get({
      publicKey: {
        challenge,
        allowCredentials: [
          {
            id: b64urlToBuf(credentialIdB64Url) as BufferSource,
            type: "public-key",
            transports: ["internal"],
          },
        ],
        userVerification: "required",
        timeout: 60_000,
      },
    });
    return !!assertion;
  } catch {
    return false;
  }
}

// Local cache for PIN-derived material so biometric unlock works offline.
const LS_KEY = "apppass:bio-pin:";

export function cachePinForBiometric(userId: string, pin: string) {
  sessionStorage.setItem(LS_KEY + userId, pin);
  localStorage.setItem(LS_KEY + userId, pin);
}

export function getCachedPin(userId: string): string | null {
  return sessionStorage.getItem(LS_KEY + userId) || localStorage.getItem(LS_KEY + userId);
}

export function clearCachedPin(userId: string) {
  sessionStorage.removeItem(LS_KEY + userId);
  localStorage.removeItem(LS_KEY + userId);
}
