import type { CryptoProvider } from './crypto.js';

/**
 * Identity fingerprints (safety numbers).
 *
 * A fingerprint is a stable, human-readable derivation of an identity's
 * public keys. Two parties can compare fingerprints out-of-band (read aloud,
 * QR code, etc.) to verify they're not being MITM'd.
 *
 * Format: 60 decimal digits in 12 groups of 5, e.g.
 *   "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 67890"
 *
 * Derived from: SHA-256(signingKey || dhKey), truncated to 30 bytes,
 * interpreted as an unsigned big-endian integer and formatted as decimal.
 */

/** Compute a 12-group safety number from an identity's public keys */
export async function computeFingerprint(
  crypto: CryptoProvider,
  signingPublicKey: Uint8Array,
  dhPublicKey: Uint8Array,
): Promise<string> {
  // Concatenate
  const combined = new Uint8Array(signingPublicKey.length + dhPublicKey.length);
  combined.set(signingPublicKey, 0);
  combined.set(dhPublicKey, signingPublicKey.length);

  // SHA-256 via HKDF trick (CryptoProvider has no direct SHA-256, but we can use HMAC with empty key)
  // Actually we use HKDF-SHA256 output as the hash
  const salt = new Uint8Array(32);
  const info = new TextEncoder().encode('ShadeFingerprint');
  const hash = await crypto.hkdf(combined, salt, info, 30);

  // Format as 12 groups of 5 decimal digits
  // Each group = 5 decimal digits (0-99999), derived from consecutive bytes
  const groups: string[] = [];
  for (let i = 0; i < 12; i++) {
    // Use 3 bytes per group (24 bits), mod 100000 to get 5 digits
    const offset = i * 2; // 2 bytes per group = 16 bits, max 65535 → 5 digits
    const value = (hash[offset]! << 8) | hash[offset + 1]!;
    groups.push(value.toString().padStart(5, '0'));
  }

  return groups.join(' ');
}

/** Short-form fingerprint: first 4 groups only (20 digits), for quick verification */
export function shortFingerprint(full: string): string {
  return full.split(' ').slice(0, 4).join(' ');
}
