// ─────────────────────────────────────────────────────────────
// public/entrance.js — client-side behaviour for the entrance page.
// Loaded via <script src="/entrance.js" defer></script> so CSP
// can stay at `script-src 'self'` — no inline scripts.
//
// Flow:
//   1. On load, GET /auth/me — if session valid, go straight to the
//      welcome step (personalised with firstName if we have one).
//   2. Otherwise show the email step. On submit POST /auth/login —
//      a) 200: session cookie set by the server, advance to welcome.
//      b) 403 not_invited: inline "not invited" message, stay put.
//      c) 429: rate limited, ask to wait.
//      d) network/other: generic retry message.
// ─────────────────────────────────────────────────────────────

/* ───── Topographic currents ───── */
(function drawCurrents() {
  const wrap = document.getElementById('currents');
  if (!wrap) return;
  const W = 1400, H = 1400, cx = W * 0.55, cy = H * 0.45;
  const svgNS = 'http://www.w3.org/2000/svg';
  const svg = document.createElementNS(svgNS, 'svg');
  svg.setAttribute('viewBox', `0 0 ${W} ${H}`);
  svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
  const RINGS = 26, BASE_R = 90, STEP = 32, AMP = 26;
  for (let i = 0; i < RINGS; i++) {
    const r = BASE_R + i * STEP, segs = 260;
    const p1 = (i * 0.6) % (Math.PI * 2);
    const p2 = (i * 1.3 + 1.2) % (Math.PI * 2);
    const a1 = AMP * (0.9 + (i % 5) * 0.08);
    const a2 = AMP * 0.35;
    let d = '';
    for (let s = 0; s <= segs; s++) {
      const t = (s / segs) * Math.PI * 2;
      const rr = r + a1 * Math.sin(t * 3 + p1 + i * 0.15)
                   + a2 * Math.sin(t * 5 + p2 + i * 0.22)
                   + AMP * 0.18 * Math.sin(t * 7 + i);
      const x = cx + Math.cos(t) * rr;
      const y = cy + Math.sin(t) * rr * 0.92;
      d += (s === 0 ? 'M' : 'L') + x.toFixed(1) + ' ' + y.toFixed(1);
    }
    d += ' Z';
    const path = document.createElementNS(svgNS, 'path');
    path.setAttribute('d', d);
    path.setAttribute('fill', 'none');
    path.setAttribute('stroke', '#383831');
    path.setAttribute('stroke-width', '1');
    path.setAttribute('stroke-linejoin', 'round');
    path.setAttribute('opacity', (i % 3 === 0 ? 0.095 : 0.055).toString());
    svg.appendChild(path);
  }
  wrap.appendChild(svg);
  requestAnimationFrame(() => setTimeout(() => wrap.classList.add('is-ready'), 120));
})();

/* ───── Step transitions ───── */
const steps = {
  email:   document.getElementById('step-email'),
  welcome: document.getElementById('step-welcome'),
};
function showStep(name) {
  Object.entries(steps).forEach(([k, el]) => {
    el.classList.toggle('is-active', k === name);
  });
}

/* ───── Welcome headline — personalized when a first name is present.
   Uses the Fenja "Definitive Emphasis" rule: Newsreader Bold Italic
   on the terminal keyword + absolute period. Falls back to the
   anonymous variant when firstName is null. ───── */
function setWelcomeTitle(firstName) {
  const el = document.getElementById('welcome-title');
  if (!el) return;
  if (firstName) {
    // Keep DOM construction to textContent + appended <em> — no innerHTML
    // of unsanitised input. firstName came from the server but we still
    // construct the node tree explicitly for clarity.
    el.textContent = 'Thanks for your interest, ';
    const em = document.createElement('em');
    em.textContent = firstName + '.';
    el.appendChild(em);
  } else {
    el.textContent = 'Thank you for your ';
    const em = document.createElement('em');
    em.textContent = 'interest.';
    el.appendChild(em);
  }
}

/* ───── Step 1: email ───── */
const emailForm  = document.getElementById('email-form');
const emailInput = document.getElementById('email-input');
const emailAck   = document.getElementById('email-ack');

function setAck(el, text, isError) {
  el.textContent = text;
  el.classList.toggle('is-error', !!isError);
  el.classList.toggle('is-visible', !!text);
}

emailInput.addEventListener('input', () => {
  emailInput.classList.remove('is-error');
  setAck(emailAck, '', false);
});

emailForm.addEventListener('submit', async (e) => {
  e.preventDefault();
  const email = emailInput.value.trim();
  if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) {
    emailInput.classList.add('is-error');
    setAck(emailAck, 'Please enter a valid email address.', true);
    return;
  }

  emailInput.disabled = true;
  setAck(emailAck, 'One moment\u2026', false);

  try {
    const res = await fetch('/auth/login', {
      method: 'POST',
      credentials: 'same-origin',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    });

    if (res.status === 429) {
      emailInput.disabled = false;
      setAck(emailAck, 'Too many attempts. Try again in a little while.', true);
      return;
    }

    if (res.status === 403) {
      // Not on the invite list. Honest message — we've decided
      // enumeration is not a concern for this site.
      emailInput.disabled = false;
      emailInput.classList.add('is-error');
      setAck(emailAck, 'This email is not on the invite list.', true);
      return;
    }

    if (!res.ok) {
      emailInput.disabled = false;
      setAck(emailAck, 'Something went wrong. Try again.', true);
      return;
    }

    // 200 OK — session cookie set by the server. Personalise the
    // welcome step and advance.
    const data = await res.json().catch(() => ({}));
    setWelcomeTitle(data.firstName || null);
    setAck(emailAck, '', false);
    showStep('welcome');
  } catch (err) {
    emailInput.disabled = false;
    setAck(emailAck, 'Could not reach the archive. Retry?', true);
  }
});

/* ───── Step 2: welcome → timeline ───── */
document.getElementById('welcome-continue').addEventListener('click', () => {
  // Cross-document View Transitions animate this nav automatically on
  // supported browsers (Chrome/Safari). Firefox falls back to a plain nav.
  window.location.href = '/timeline';
});

/* ───── On-load routing ───── */
// `/` always serves this entrance shell. Decide which step to show based
// on whether the visitor already has a valid session.
(async function routeOnLoad() {
  let authed = false;
  let firstName = null;
  try {
    const res = await fetch('/auth/me', { credentials: 'same-origin' });
    if (res.ok) {
      authed = true;
      const data = await res.json().catch(() => ({}));
      firstName = data.firstName || null;
    }
  } catch { /* offline — fall through to email */ }

  if (authed) {
    setWelcomeTitle(firstName);
    showStep('welcome');
  } else {
    showStep('email');
    setTimeout(() => emailInput.focus(), 300);
  }
  document.body.classList.remove('is-pending');
})();
