/**
 * HMAC-SHA256-Signaturen für eingehende Tracking-Webhooks (Shop-/CRM-Push).
 *
 * Verifikation per Header `X-MailForge-Signature: sha256=<hex>`. Pattern analog
 * GitHub/Stripe — Body wird mit dem workspace-spezifischen Secret hashen und gegen
 * den Header verglichen (constant-time).
 *
 * Wir wiederverwenden bewusst das Konzept aus `src/lib/email/footer-urls.ts`,
 * aber mit body-basiertem HMAC statt nur ID-basiertem Token. Body-Hash schützt
 * gegen Replay UND Tampering.
 */

import { createHmac, timingSafeEqual } from 'node:crypto';

const HEADER_NAME = 'x-mailforge-signature';
const PREFIX = 'sha256=';

/**
 * Berechnet HMAC-SHA256 des Bodies mit dem Workspace-Secret.
 * Returns: kompletter Header-Wert `sha256=<hex>`.
 *
 * Wird im Settings-UI für die "Test-Signatur"-Anzeige benutzt und intern für
 * die Compare-Logik.
 */
export function signBody(body: string, secret: string): string {
  const h = createHmac('sha256', secret);
  h.update(body);
  return PREFIX + h.digest('hex');
}

/**
 * Verifiziert die eingehende Signatur gegen das Workspace-Secret.
 *
 * - Header-Name case-insensitive (Headers-Object liefert lowercase)
 * - Prefix `sha256=` muss vorhanden sein
 * - Constant-time-Vergleich via Node's timingSafeEqual
 * - Bei jedem Fehler false (keine Aussage warum) — verhindert Oracle-Attacks
 */
export function verifySignature(body: string, signatureHeader: string | null, secret: string): boolean {
  if (!signatureHeader || !secret) return false;
  if (!signatureHeader.startsWith(PREFIX)) return false;

  const expected = signBody(body, secret);
  // Constant-time-Vergleich: beide Strings müssen gleiche Länge haben
  if (signatureHeader.length !== expected.length) return false;

  try {
    const a = Buffer.from(signatureHeader);
    const b = Buffer.from(expected);
    return timingSafeEqual(a, b);
  } catch {
    return false;
  }
}

/**
 * Extrahiert den Signatur-Header aus dem Request. Case-insensitive Lookup
 * (Next.js Headers-API liefert Header lowercase, aber wir sichern uns ab).
 */
export function readSignatureHeader(headers: Headers): string | null {
  return headers.get(HEADER_NAME);
}

/**
 * Generiert ein neues Webhook-Secret (256-bit Random-Hex).
 * Wird von der Settings-UI per Button-Click aufgerufen.
 *
 * Format: 64 Hex-Chars = 32 Bytes Entropie. Reicht weit für HMAC-Schlüssel.
 * (HMAC-SHA256 nutzt intern eh nur 32 Bytes der Key-Länge.)
 */
export function generateWebhookSecret(): string {
  const buf = new Uint8Array(32);
  crypto.getRandomValues(buf);
  return Array.from(buf, (b) => b.toString(16).padStart(2, '0')).join('');
}
