/**
 * Unit-Tests für die Shared-Lib Email-Attribution.
 * Wir importieren direkt aus dem Packages-Folder, weil mailforge sie nur
 * indirekt benutzt (über den Webhook-Endpoint).
 *
 * Aufruf: `npx tsx scripts/test-attribution-cookie.ts`
 */

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

let failed = 0;
let passed = 0;
function check(name: string, cond: boolean, detail?: string) {
  if (cond) { passed++; console.log(`  ✓ ${name}`); }
  else { failed++; console.log(`  ✗ ${name}${detail ? ` — ${detail}` : ''}`); }
}
function section(t: string) { console.log(`\n${t}`); }

// ─── HMAC Roundtrip (Webhook-Pattern) ─────────────────────────────────────
section('Webhook HMAC roundtrip');
{
  const secret = 'test-secret-12345';
  const body = JSON.stringify({ recipientId: 'rec-123', kind: 'order', value: 9900 });
  const ts = String(Date.now());
  const payload = `${ts}.${body}`;
  const sig = createHmac('sha256', secret).update(payload).digest('hex');
  // Verifikation wie im Endpoint
  const expected = createHmac('sha256', secret).update(payload).digest('hex');
  check('Signatur deterministisch', sig === expected);
  check('Hex-Länge = 64', sig.length === 64);
  check('timingSafeEqual gleicher Signaturen',
    timingSafeEqual(Buffer.from(sig, 'utf8'), Buffer.from(expected, 'utf8')));
  // Verschiedene Bodies → verschiedene Signaturen
  const sig2 = createHmac('sha256', secret).update(`${ts}.${body}x`).digest('hex');
  check('Geänderter Body → andere Signatur', sig !== sig2);
}

// ─── Cookie-Format & Multi-Touch (lokale Logik-Verifikation) ──────────────
section('Attribution-Cookie Format (Logik-Simulation)');
{
  // Wir simulieren die appendTouch-Logik ohne DOM (für CI)
  interface Touch { r: string; c?: string; v?: string; t: number }
  interface State { touches: Touch[] }

  const ATTR_MAX_TOUCHES = 10;
  function append(state: State, touch: Touch): State {
    const last = state.touches[0];
    if (last && last.r === touch.r && last.c === touch.c && Math.abs(last.t - touch.t) < 60_000) {
      return state;
    }
    return { touches: [touch, ...state.touches].slice(0, ATTR_MAX_TOUCHES) };
  }

  // 1 Touch
  let s: State = { touches: [] };
  s = append(s, { r: 'r1', c: 'c1', t: 1_000_000 });
  check('1 Touch ergibt 1 Eintrag', s.touches.length === 1);

  // Gleicher Touch in 30s → kein neuer Eintrag
  s = append(s, { r: 'r1', c: 'c1', t: 1_030_000 });
  check('Refresh in 30s wird dedupliziert', s.touches.length === 1);

  // Anderer Recipient → neuer Eintrag
  s = append(s, { r: 'r2', c: 'c2', t: 1_040_000 });
  check('Anderer Recipient → 2 Einträge', s.touches.length === 2);
  check('LIFO: neuester zuerst', s.touches[0].r === 'r2');

  // 15 weitere Touches → kappt auf ATTR_MAX_TOUCHES
  for (let i = 0; i < 15; i++) {
    s = append(s, { r: `r-${i}`, t: 2_000_000 + i * 1000 });
  }
  check('Capped at ATTR_MAX_TOUCHES', s.touches.length === ATTR_MAX_TOUCHES);
  check('Capped → neueste behalten', s.touches[0].r === 'r-14');
}

// ─── Email-Attribution Schema-Sanity ──────────────────────────────────────
section('mfRcp Regex Pattern (Edge-Function Validation)');
{
  const pattern = /^[A-Za-z0-9_-]{1,200}$/;
  check('UUID akzeptiert', pattern.test('a1b2c3d4-e5f6-7890-abcd-ef1234567890'));
  check('Short ID akzeptiert', pattern.test('rec-123'));
  check('Empty rejected', !pattern.test(''));
  check('Sonderzeichen rejected', !pattern.test('rec/123'));
  check('SQL-injection rejected', !pattern.test("rec'; DROP TABLE--"));
  check('Über 200 chars rejected', !pattern.test('a'.repeat(201)));
}

console.log(`\n${passed} passed, ${failed} failed`);
if (failed > 0) process.exit(1);
