// landing-app.jsx — mounts the design's <PipiLanding/> with:
//   • password gate (LANDING_PASSWORD env var, checked via /api/landing-login)
//   • SK / CZ / EN language switcher (persisted in localStorage)
//   • waitlist modal triggered by any CTA / nav / download button
//
// We don't modify the design components — we wrap them.

const { useEffect, useState, useCallback, useRef } = React;

// Accessible-dialog focus trap (a11y finding A03): when active, move focus into
// the dialog, cycle Tab/Shift+Tab within it, and restore focus to the trigger on
// close. Escape is left to each modal's existing handler (no double-close).
// Returns a ref to attach to the dialog container.
function useFocusTrap(active) {
  const ref = useRef(null);
  useEffect(() => {
    if (!active) return;
    const prev = (typeof document !== 'undefined') ? document.activeElement : null;
    const node = ref.current;
    const focusables = () => node ? Array.prototype.slice.call(
      node.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])')
    ).filter((el) => el.offsetParent !== null) : [];
    const f0 = focusables();
    if (f0[0]) { try { f0[0].focus(); } catch {} }
    const onKey = (e) => {
      if (e.key !== 'Tab') return;
      const f = focusables(); if (!f.length) return;
      const first = f[0], last = f[f.length - 1];
      if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
      else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
    };
    document.addEventListener('keydown', onKey, true);
    return () => {
      document.removeEventListener('keydown', onKey, true);
      try { if (prev && prev.focus) prev.focus(); } catch {}
    };
  }, [active]);
  return ref;
}

const LANG_KEY = 'ippy.landing.lang';
const AUTH_KEY = 'pipi.landing.unlocked';

// Supported landing languages. Mirror of PIPI_LANGS in pipi-landing.jsx
// (that script loads first, so window.PIPI_LANGS is normally present;
// keep a literal fallback so this file is robust on its own).
const LANDING_LANGS = (typeof window !== 'undefined' && window.PIPI_LANGS) || ['sk', 'cz', 'en'];

// Pick the initial language: persisted choice → navigator.language
// (cs* → cz, en* → en, everything else → sk). Always returns a value
// that exists in LANDING_LANGS.
function pickInitialLang() {
  try {
    const saved = localStorage.getItem(LANG_KEY);
    if (saved && LANDING_LANGS.indexOf(saved) !== -1) return saved;
  } catch {}
  try {
    const navLang = (navigator.language || navigator.userLanguage || '').toLowerCase();
    if (navLang.indexOf('cs') === 0 || navLang.indexOf('cz') === 0) return 'cz';
    if (navLang.indexOf('en') === 0) return 'en';
  } catch {}
  return 'en';
}

// Keep the <html lang> attribute in sync with the chosen UI language so
// screen readers / browsers announce the right language. Our internal
// code uses 'cz' for Czech; the correct BCP-47 subtag is 'cs'.
function applyHtmlLang(lang) {
  try {
    const code = lang === 'cz' ? 'cs' : lang;
    document.documentElement.setAttribute('lang', code);
  } catch {}
}

// ──────────────────────────────────────────────────────────────
// Password gate
// ──────────────────────────────────────────────────────────────
function PasswordGate({ lang, onUnlock }) {
  const [pw, setPw] = useState('');
  const [err, setErr] = useState('');
  const [busy, setBusy] = useState(false);
  const inputRef = useRef(null);
  const trapRef = useFocusTrap(true);

  useEffect(() => { inputRef.current && inputRef.current.focus(); }, []);

  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr('');
    try {
      const res = await fetch('/api/landing-login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ password: pw }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) {
        setErr(data.error || (lang === 'en' ? 'Wrong password.' : 'Nesprávne heslo.'));
        setBusy(false);
        return;
      }
      try { localStorage.setItem(AUTH_KEY, '1'); } catch {}
      onUnlock();
    } catch (e) {
      setErr(lang === 'en' ? 'Network glitch, try again.' : 'Sieť zlyhala, skús znova.');
      setBusy(false);
    }
  };

  // Render the gate via portal to document.body so it escapes the
  // scaled .stage-inner. Without the portal the gate inherits the
  // transform and becomes a postage-stamp on phones, with the input
  // physically unreachable.
  return ReactDOM.createPortal(
    <div style={{
      position: 'fixed', inset: 0, background: PIPI.paper,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24, zIndex: 9000, fontFamily: '"Patrick Hand", cursive',
      WebkitTapHighlightColor: 'transparent',
    }}>
      <div ref={trapRef} role="dialog" aria-modal="true"
        aria-label={lang === 'en' ? 'Soft launch, enter password' : 'Tichý štart — zadaj heslo'}
        style={{
        background: PIPI.paperLt, border: `4px solid ${PIPI.ink}`,
        borderRadius: 28, padding: '36px 26px 24px', maxWidth: 420, width: '100%',
        boxShadow: '10px 12px 0 rgba(0,0,0,0.16)', position: 'relative',
        textAlign: 'center',
      }}>
        <div style={{ display: 'flex', justifyContent: 'center', marginTop: -68, marginBottom: 6 }}>
          <div style={{ transform: 'rotate(-3deg)' }}>
            <Pipi size={96}/>
          </div>
        </div>
        <div style={{ fontFamily: '"Caveat", cursive', fontWeight: 700, fontSize: 44, lineHeight: 1 }}>
          {lang === 'en' ? 'Soft launch.' : 'Tichý štart.'}
        </div>
        <div style={{ fontSize: 18, lineHeight: 1.4, marginTop: 10, opacity: 0.82 }}>
          {lang === 'en'
            ? 'Ippy is not public yet. If you have a peek-password, type it below.'
            : 'Ippy ešte nie je verejné. Ak máš heslo na náhľad, zadaj ho dolu.'}
        </div>
        <form onSubmit={submit} style={{ marginTop: 18, display: 'flex', flexDirection: 'column', gap: 10 }}>
          <input
            ref={inputRef}
            type="password" autoComplete="current-password"
            inputMode="text" autoCapitalize="off" autoCorrect="off" spellCheck="false"
            value={pw} onChange={(e) => setPw(e.target.value)}
            placeholder={lang === 'en' ? 'password' : 'heslo'}
            style={{
              border: `3px solid ${PIPI.ink}`, borderRadius: 14, padding: '14px 16px',
              fontFamily: 'inherit', fontSize: 20, background: PIPI.paper, color: PIPI.ink,
              textAlign: 'center', minHeight: 48,
            }}
          />
          {err && (
            <div style={{
              background: PIPI.pink, color: PIPI.ink, padding: '8px 12px', borderRadius: 12,
              border: `2.5px solid ${PIPI.ink}`, fontSize: 16,
            }}>{err}</div>
          )}
          <button type="submit" disabled={busy} style={{
            marginTop: 4, background: PIPI.yellow, border: `3px solid ${PIPI.ink}`,
            borderRadius: 999, padding: '14px 18px', fontFamily: '"Caveat", cursive',
            fontWeight: 700, fontSize: 24, cursor: busy ? 'wait' : 'pointer', color: PIPI.ink,
            boxShadow: '4px 5px 0 rgba(0,0,0,0.18)', minHeight: 52,
          }}>
            {busy ? (lang === 'en' ? 'Checking…' : 'Overujem…') : (lang === 'en' ? 'Open' : 'Otvoriť')}
          </button>
        </form>
        <div style={{ marginTop: 14, fontSize: 13, opacity: 0.55, lineHeight: 1.4 }}>
          {lang === 'en'
            ? 'No password yet? Email the founders. We add new previewers each week.'
            : 'Nemáš heslo? Napíš zakladateľom. Pridávame náhľady postupne.'}
        </div>
      </div>
    </div>,
    document.body
  );
}

// ──────────────────────────────────────────────────────────────
// Waitlist modal
// ──────────────────────────────────────────────────────────────
function WaitlistModal({ open, onClose, lang }) {
  const [email, setEmail] = useState('');
  const [child, setChild] = useState('');
  const [status, setStatus] = useState('idle'); // idle | sending | ok | err
  const [errorMsg, setErrorMsg] = useState('');

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [open, onClose]);

  const trapRef = useFocusTrap(open);
  if (!open) return null;

  const tx = lang === 'en' ? {
    title: 'I want in early.',
    sub: 'Send me an email when Ippy opens publicly. No spam, no newsletters. One email, one link.',
    email_label: 'Parent email',
    email_ph: 'parent@example.com',
    age_label: 'Child age (optional)',
    age_ph: 'e.g. 5',
    cta: 'Add me to the list',
    busy: 'Sending…',
    note: 'No tracking. No selling. We only use your email once, when we launch.',
    invalid: 'Enter a valid email, please.',
    ok_title: 'You’re on the list.',
    ok_body: 'We’ll send you a link the moment Ippy can walk without wobbling.',
    ok_hint: 'Watch your inbox in the next few days. We sometimes land in spam, so drag “Ippy” into known contacts.',
  } : {
    title: 'Chcem ako prvý.',
    sub: 'Pošli mi email, keď Ippy otvoríme verejne. Žiadny spam, žiadne newslettre — jeden email, jeden odkaz.',
    email_label: 'Email rodiča',
    email_ph: 'rodic@example.sk',
    age_label: 'Vek dieťaťa (nepovinné)',
    age_ph: 'napr. 5',
    cta: 'Pridať ma na zoznam',
    busy: 'Posielam…',
    note: 'Bez sledovania. Bez predaja kontaktov. Email použijeme iba raz — keď spustíme.',
    invalid: 'Zadaj platný email, prosím.',
    ok_title: 'Si na zozname.',
    ok_body: 'Pošleme ti odkaz, hneď ako bude Ippy chodiť bez padania.',
    ok_hint: 'Skontroluj si email v najbližších dňoch. Niekedy končíme v spame — presuň „Ippy“ medzi známych.',
  };

  const submit = async (e) => {
    e.preventDefault();
    if (!email || !email.includes('@')) {
      setStatus('err'); setErrorMsg(tx.invalid);
      return;
    }
    setStatus('sending'); setErrorMsg('');
    try {
      const res = await fetch('/api/waitlist', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: email.trim(), childAge: child.trim(), source: 'landing-cta', lang }),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error || ('HTTP ' + res.status));
      }
      setStatus('ok');
    } catch (err) {
      setStatus('err'); setErrorMsg(err.message || (lang === 'en' ? 'Something failed. Try again in a moment.' : 'Niečo zlyhalo. Skús to o chvíľu.'));
    }
  };

  return (
    <div className="wl-backdrop" onClick={onClose}>
      <div ref={trapRef} className="wl-modal" onClick={(e) => e.stopPropagation()} role="dialog" aria-modal="true" aria-label={tx.title}>
        <button className="close" onClick={onClose} aria-label="×">×</button>
        {status === 'ok' ? (
          <>
            <h2>{tx.ok_title}</h2>
            <p>{tx.ok_body}</p>
            <div className="wl-success">{tx.ok_hint}</div>
          </>
        ) : (
          <>
            <h2>{tx.title}</h2>
            <p>{tx.sub}</p>
            <form className="wl-form" onSubmit={submit}>
              <label htmlFor="wl-email">{tx.email_label}</label>
              <input id="wl-email" type="email" autoComplete="email" required
                value={email} onChange={(e) => setEmail(e.target.value)}
                placeholder={tx.email_ph}/>
              <label htmlFor="wl-child">{tx.age_label}</label>
              <input id="wl-child" type="text" inputMode="numeric"
                value={child} onChange={(e) => setChild(e.target.value)}
                placeholder={tx.age_ph}/>
              {status === 'err' && <div className="wl-error">{errorMsg}</div>}
              <button type="submit" disabled={status === 'sending'}>
                {status === 'sending' ? tx.busy : tx.cta}
              </button>
              <div className="wl-note">{tx.note}</div>
            </form>
          </>
        )}
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// Auth modal (sign-up / sign-in via magic-link)
// ──────────────────────────────────────────────────────────────
// Legacy/dead path: real auth lives in the app (app.heyippy.com) via
// Supabase. The landing is marketing + waitlist only; this modal is
// retained but not wired to a backend.
const PIPI_API_BASE = (typeof window !== 'undefined' && window.PIPI_API_BASE)
  || ''; // fallback if config script fails to load

function AuthModal({ open, mode, onClose, onModeSwitch, onAuthed }) {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [status, setStatus] = useState('idle'); // idle | sending | err
  const [error, setError] = useState('');

  useEffect(() => {
    if (!open) return;
    setStatus('idle'); setError('');
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  if (!open) return null;
  const isSignUp = mode === 'signup';
  const submit = async (e) => {
    e.preventDefault();
    if (!email || !email.includes('@')) { setStatus('err'); setError('Zadaj platný email.'); return; }
    if (password.length < 6) { setStatus('err'); setError('Heslo musí mať aspoň 6 znakov.'); return; }
    setStatus('sending'); setError('');
    try {
      const res = await fetch(`${PIPI_API_BASE}/api/auth/${isSignUp ? 'sign-up' : 'sign-in'}`, {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ email: email.trim(), password }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || ('HTTP ' + res.status));
      // Logged in immediately — no email step.
      onAuthed && onAuthed(data.user || null);
    } catch (err) {
      setStatus('err'); setError(err.message || 'Sieť zlyhala.');
    }
  };

  return ReactDOM.createPortal(
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(26,26,46,0.78)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 20, zIndex: 9000, WebkitTapHighlightColor: 'transparent',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        background: PIPI.paperLt, border: `4px solid ${PIPI.ink}`,
        borderRadius: 28, padding: '30px 26px 24px', maxWidth: 420, width: '100%',
        boxShadow: '10px 12px 0 rgba(0,0,0,0.20)', position: 'relative',
        textAlign: 'center',
      }} role="dialog" aria-modal="true">
        <button onClick={onClose} aria-label="Zavrieť" style={{
          position: 'absolute', top: 12, right: 14, background: 'transparent',
          border: 0, fontSize: 26, cursor: 'pointer', color: PIPI.ink, lineHeight: 1,
        }}>×</button>
        <div style={{ display: 'flex', justifyContent: 'center', marginTop: -60, marginBottom: 6 }}>
          <div style={{ transform: 'rotate(-3deg)' }}><Pipi size={92}/></div>
        </div>
        <div style={{ fontFamily: '"Caveat", cursive', fontWeight: 700, fontSize: 42, lineHeight: 1 }}>
          {isSignUp ? 'Vytvor si účet' : 'Prihlás sa'}
        </div>
        <div style={{ fontSize: 17, lineHeight: 1.4, marginTop: 8, opacity: 0.82 }}>
          {isSignUp
            ? 'Zadaj e-mail a heslo. Účet vytvoríme hneď — bez overovania e-mailu.'
            : 'Zadaj e-mail a heslo, ktorými si sa registroval/a.'}
        </div>
        <form onSubmit={submit} style={{ marginTop: 18, display: 'flex', flexDirection: 'column', gap: 10 }}>
          <input
            type="email" autoComplete="email" required autoFocus
            value={email} onChange={(e) => setEmail(e.target.value)}
            placeholder="rodic@example.sk"
            style={{
              border: `3px solid ${PIPI.ink}`, borderRadius: 14, padding: '14px 16px',
              fontFamily: 'inherit', fontSize: 19, background: PIPI.paper, color: PIPI.ink,
              textAlign: 'center', minHeight: 48,
            }}
          />
          <input
            type="password" autoComplete={isSignUp ? 'new-password' : 'current-password'} required
            value={password} onChange={(e) => setPassword(e.target.value)}
            placeholder={isSignUp ? 'heslo (aspoň 6 znakov)' : 'heslo'}
            style={{
              border: `3px solid ${PIPI.ink}`, borderRadius: 14, padding: '14px 16px',
              fontFamily: 'inherit', fontSize: 19, background: PIPI.paper, color: PIPI.ink,
              textAlign: 'center', minHeight: 48,
            }}
          />
          {error && (
            <div style={{
              background: PIPI.pink, color: PIPI.ink, padding: '8px 12px', borderRadius: 12,
              border: `2.5px solid ${PIPI.ink}`, fontSize: 15,
            }}>{error}</div>
          )}
          <button type="submit" disabled={status === 'sending'} style={{
            marginTop: 4, background: PIPI.yellow, border: `3px solid ${PIPI.ink}`,
            borderRadius: 999, padding: '14px 18px', fontFamily: '"Caveat", cursive',
            fontWeight: 700, fontSize: 24, cursor: status === 'sending' ? 'wait' : 'pointer',
            color: PIPI.ink, boxShadow: '4px 5px 0 rgba(0,0,0,0.18)', minHeight: 52,
          }}>
            {status === 'sending' ? 'Moment…' : (isSignUp ? 'Vytvoriť účet' : 'Prihlásiť sa')}
          </button>
        </form>
        <div style={{ marginTop: 14, fontSize: 14, opacity: 0.7 }}>
          {isSignUp ? (
            <>Už máš účet? <a href="#" onClick={(e) => { e.preventDefault(); onModeSwitch('signin'); }} style={{ color: PIPI.ink, fontWeight: 700 }}>Prihlás sa.</a></>
          ) : (
            <>Ešte nie si registrovaný? <a href="#" onClick={(e) => { e.preventDefault(); onModeSwitch('signup'); }} style={{ color: PIPI.ink, fontWeight: 700 }}>Vytvor si účet.</a></>
          )}
        </div>
      </div>
    </div>,
    document.body
  );
}

// ──────────────────────────────────────────────────────────────
// App shell
// ──────────────────────────────────────────────────────────────
// Trilingual SK · CZ · EN. The chosen language is persisted in
// localStorage (LANG_KEY) and defaulted from navigator.language; the
// SK/CZ/EN switcher in the header drives `setLang`.
function LandingApp() {
  const [lang, setLang] = useState(pickInitialLang);
  const [unlocked, setUnlocked] = useState(null); // null = checking, true/false after

  // Persist the chosen language + keep <html lang> in sync.
  const changeLang = useCallback((next) => {
    if (!next || LANDING_LANGS.indexOf(next) === -1) return;
    setLang(next);
    try { localStorage.setItem(LANG_KEY, next); } catch {}
    applyHtmlLang(next);
  }, []);

  // Reflect the initial language on <html lang> on first mount.
  useEffect(() => { applyHtmlLang(lang); }, []);
  const [waitlistOpen, setWaitlistOpen] = useState(false);
  const [authMode, setAuthMode] = useState(null); // null | 'signin' | 'signup'
  const [currentUser, setCurrentUser] = useState(null);

  // The landing is marketing + waitlist only. Account auth lives on the APP
  // surface (Supabase) — we no longer probe the retired Cloudflare Worker
  // (/papi/api/auth/me), which 502'd here. The header always offers "Prihlás
  // sa", which routes to the app (see the sign-in/sign-up handlers below).
  const signOut = useCallback(() => { setCurrentUser(null); }, []);

  // Check whether the password gate is active at all.
  useEffect(() => {
    (async () => {
      try {
        const res = await fetch('/api/landing-login', { method: 'GET' });
        const data = await res.json().catch(() => ({}));
        if (!data.required) {
          setUnlocked(true);
          return;
        }
        // gate is active — see if we already unlocked once this session
        try {
          if (localStorage.getItem(AUTH_KEY) === '1') {
            setUnlocked(true);
            return;
          }
        } catch {}
        setUnlocked(false);
      } catch {
        // If the endpoint doesn't exist (local static preview), be permissive.
        setUnlocked(true);
      }
    })();
  }, []);

  const openWaitlist = useCallback(() => setWaitlistOpen(true), []);

  // Event delegation: we only intercept clicks that bubble up from elements
  // explicitly tagged with `data-action="..."`. Everything else (the signup
  // form submit, the listen-sample button, the SK/EN pills, anchor links)
  // is left alone.
  useEffect(() => {
    if (!unlocked) return;
    const root = document.getElementById('root');
    if (!root) return;
    const handler = (e) => {
      let el = e.target;
      while (el && el !== root) {
        const action = el.dataset && el.dataset.action;
        if (action === 'sign-in' || action === 'sign-up') {
          // Account auth lives on the app surface (Supabase). Route there
          // instead of the retired /papi worker the in-page modal used to hit.
          e.preventDefault(); e.stopPropagation();
          window.location.href = (window.IPPY_LINKS.app || '') + '/demo';
          return;
        }
        if (action === 'sign-out') {
          e.preventDefault(); e.stopPropagation();
          signOut();
          return;
        }
        if (action === 'open-demo') {
          e.preventDefault();
          e.stopPropagation();
          window.location.href = (window.IPPY_LINKS.app || '') + '/demo';
          return;
        }
        if (action === 'goto-signup') {
          e.preventDefault();
          e.stopPropagation();
          const target = document.getElementById('signup');
          if (target) {
            target.scrollIntoView({ behavior: 'smooth', block: 'start' });
            // Focus the email input shortly after scrolling settles.
            setTimeout(() => {
              const input = document.getElementById('cta-email');
              if (input) input.focus({ preventScroll: true });
            }, 700);
          }
          return;
        }
        el = el.parentElement;
      }
    };
    root.addEventListener('click', handler, true);
    return () => root.removeEventListener('click', handler, true);
  }, [unlocked]);

  // Resize hook after render
  useEffect(() => {
    if (typeof window.pipiResize === 'function') {
      setTimeout(window.pipiResize, 20);
      setTimeout(window.pipiResize, 250);
      setTimeout(window.pipiResize, 900);
    }
    const booting = document.getElementById('booting');
    if (booting && unlocked !== null) booting.remove();
  }, [unlocked, lang]);

  if (unlocked === null) {
    return null; // boot screen is still visible from index.html
  }
  if (unlocked === false) {
    return <PasswordGate lang={lang} onUnlock={() => setUnlocked(true)}/>;
  }

  return (
    <>
      <PipiLanding width={1320} lang={lang} onLangChange={changeLang} currentUser={currentUser}/>
      <WaitlistModal open={waitlistOpen} onClose={() => setWaitlistOpen(false)} lang={lang}/>
      <AuthModal
        open={authMode !== null}
        mode={authMode}
        onClose={() => setAuthMode(null)}
        onModeSwitch={(m) => setAuthMode(m)}
        onAuthed={(user) => { setCurrentUser(user); setAuthMode(null); }}
      />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<LandingApp/>);
