/**
 * Have I Been Pwned (HIBP) breach check — k-anonymity model.
 * Checks if a password appears in known breaches via the Pwned Passwords API.
 *
 * Uses SHA-1 prefix (first 5 chars) for privacy — the full hash is never sent.
 */

import { createHash } from 'node:crypto';

const HIBP_API = 'https://api.pwnedpasswords.com/range';

/**
 * Check if a password has been seen in data breaches.
 * Returns the number of times seen (0 = not breached).
 * Fails open (returns 0) if HIBP API is unreachable.
 */
export async function checkBreached(password: string): Promise<number> {
  const sha1 = createHash('sha1').update(password).digest('hex').toUpperCase();
  const prefix = sha1.slice(0, 5);
  const suffix = sha1.slice(5);

  try {
    const res = await fetch(`${HIBP_API}/${prefix}`, {
      headers: {
        'User-Agent': 'ByteLyst-SmartAuth/1.0',
        ...(process.env.HIBP_API_KEY ? { 'hibp-api-key': process.env.HIBP_API_KEY } : {}),
      },
      signal: AbortSignal.timeout(5000),
    });

    if (!res.ok) return 0; // fail open

    const text = await res.text();
    for (const line of text.split('\n')) {
      const [hashSuffix, countStr] = line.trim().split(':');
      if (hashSuffix === suffix) {
        return parseInt(countStr, 10) || 0;
      }
    }
    return 0;
  } catch {
    // Fail open — HIBP is advisory, not blocking
    return 0;
  }
}

/**
 * Returns true if the password is breached and should be rejected.
 * Threshold: seen 3+ times in breaches.
 */
export async function isPasswordBreached(password: string): Promise<boolean> {
  const count = await checkBreached(password);
  return count >= 3;
}
