// Dedicated Face Recognition landing page. Routed via `/face-recognition`.
// Hero + how-it-works + use cases + privacy + embedded backend iframe + FAQ.
//
// Backend is the Python service in tools/photorecognation/. The iframe block
// uses the same probe + auto-retry as tools/photo-finder.jsx so the moment
// the engine is reachable the live tool slots in.

(function () {
  const { useState, useEffect, useRef } = React;

  const ACCENT      = '#ea580c';
  const ACCENT_SOFT = '#ffede0';

  function FaceRecognitionPage({ theme }) {
    useEffect(() => {
      if (theme) document.documentElement.dataset.theme = theme;
    }, [theme]);

    const scrollToTool = () => {
      document.getElementById('fr-tool')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
    };
    const scrollToHow = () => {
      document.getElementById('fr-how')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
    };

    return (
      <main className="container fr-page">
        {/* ----- HERO ----- */}
        <section className="fr-hero">
          <div className="fr-hero-deco" aria-hidden="true">
            <span className="fhd-1" /><span className="fhd-2" /><span className="fhd-3" />
            <span className="fhd-4" /><span className="fhd-5" /><span className="fhd-6" />
          </div>

          <div className="fr-hero-tag">
            <window.Icon name="scan" size={14} strokeWidth={2.2} />
            <span>AI · 100% PRIVATE · NO UPLOAD</span>
          </div>

          <h1 className="fr-hero-title">
            Find yourself in the&nbsp;<span className="hl">crowd</span>.
          </h1>

          <p className="fr-hero-sub">
            Race finishers, wedding guests, conference crowds — drop a couple of selfies,
            point us at the gallery, and we surface every photo of <em>you</em> in seconds.
            Detection runs on your computer. Your face never leaves your device.
          </p>

          <div className="fr-hero-ctas">
            <button className="btn btn-primary fr-btn-primary" onClick={scrollToTool}>
              <window.Icon name="scan" size={16} /> Find my photos
            </button>
            <button className="btn btn-secondary fr-btn-secondary" onClick={scrollToHow}>
              How it works <window.Icon name="arrow" size={14} />
            </button>
          </div>

          <div className="fr-hero-stats">
            <div className="fhs">
              <div className="fhs-v">5 000+</div>
              <div className="fhs-l">photos scanned per session</div>
            </div>
            <div className="fhs">
              <div className="fhs-v">~99%</div>
              <div className="fhs-l">ArcFace recognition accuracy</div>
            </div>
            <div className="fhs">
              <div className="fhs-v">2</div>
              <div className="fhs-l">free downloads per session</div>
            </div>
            <div className="fhs">
              <div className="fhs-v">0</div>
              <div className="fhs-l">files uploaded anywhere</div>
            </div>
          </div>
        </section>

        {/* ----- EMBEDDED TOOL ----- */}
        <section id="fr-tool" className="fr-tool fr-tool-top">
          <div className="fr-tool-head">
            <h2 className="fr-h2">Try it now</h2>
            <p className="fr-tool-sub">Your selfies + a gallery URL — that's it.</p>
          </div>
          <FaceRecognitionFrame />
        </section>

        {/* ----- USE CASES (compact horizontal strip) ----- */}
        <section className="fr-cases">
          <h2 className="fr-h2">Built for the events you actually go to.</h2>
          <div className="fr-case-strip">
            <div className="fr-case-chip">
              <span className="fr-case-dot" style={{ background: '#c8521a' }} />
              <strong>Marathons</strong>
              <span>12 of you in 5 000 finisher shots.</span>
            </div>
            <div className="fr-case-chip">
              <span className="fr-case-dot" style={{ background: '#be185d' }} />
              <strong>Weddings</strong>
              <span>Every shot a guest appears in.</span>
            </div>
            <div className="fr-case-chip">
              <span className="fr-case-dot" style={{ background: '#1d4ed8' }} />
              <strong>Conferences</strong>
              <span>Your panel shot in seconds.</span>
            </div>
            <div className="fr-case-chip">
              <span className="fr-case-dot" style={{ background: '#15803d' }} />
              <strong>Corporate events</strong>
              <span>800 photos → just yours.</span>
            </div>
          </div>
        </section>

        {/* ----- HOW + PRIVACY (single tight 2-column block) ----- */}
        <section id="fr-how" className="fr-how-priv">
          <div className="fr-how-priv-grid">
            <div className="fr-how-col">
              <h3 className="fr-h3">From selfie to matches · 3 steps</h3>
              <ol className="fr-step-list">
                <li>
                  <span className="fr-step-num">1</span>
                  <div>
                    <strong>Drop your selfies.</strong> Two or three is enough — we build a private signature, never sent anywhere.
                  </div>
                </li>
                <li>
                  <span className="fr-step-num">2</span>
                  <div>
                    <strong>Paste the gallery URL.</strong> Race-photo site, Google Photos album, conference dump — any public URL.
                  </div>
                </li>
                <li>
                  <span className="fr-step-num">3</span>
                  <div>
                    <strong>Get your photos.</strong> Ranked by confidence. Download 2 for free — upgrade for unlimited.
                  </div>
                </li>
              </ol>
            </div>

            <div className="fr-priv-col">
              <div className="fr-priv-tag">
                <window.Icon name="lock" size={12} strokeWidth={2.2} /> PRIVACY
              </div>
              <h3 className="fr-h3">Your face never leaves your device.</h3>
              <p className="fr-priv-sub">
                Detection runs locally with InsightFace ArcFace. No upload, no cloud lookup, no account.
              </p>
              <ul className="fr-priv-bullets">
                <li><window.Icon name="lock"  size={12} strokeWidth={2.4} /> Local processing</li>
                <li><window.Icon name="check" size={12} strokeWidth={2.4} /> Open-source models</li>
                <li><window.Icon name="x"     size={12} strokeWidth={2.4} /> No tracking by default</li>
              </ul>
            </div>
          </div>
        </section>

        {/* ----- FAQ (compact) ----- */}
        <section className="fr-faq">
          <h2 className="fr-h2">Common questions</h2>
          <div className="fr-faq-grid">
            <details className="fr-faq-item" open>
              <summary>How accurate is it?</summary>
              <p>
                InsightFace <code>buffalo_l</code> ArcFace — ~99% accuracy on well-lit shots where the face is larger than ~80 px.
              </p>
            </details>
            <details className="fr-faq-item">
              <summary>What galleries work?</summary>
              <p>
                Any public URL. Race sites, Google Photos albums, WordPress galleries, S3 listings.
              </p>
            </details>
            <details className="fr-faq-item">
              <summary>Do you store anything?</summary>
              <p>
                Locally yes (your match list). Server-side: never.
              </p>
            </details>
            <details className="fr-faq-item">
              <summary>How long does a 5 000-photo gallery take?</summary>
              <p>3–8 minutes on a recent laptop. Progress shown as a percentage.</p>
            </details>
            <details className="fr-faq-item">
              <summary>Is it free?</summary>
              <p>
                You get 2 free photo downloads per session — enough to grab your best shots.
                For unlimited downloads, PDF albums, and Instagram exports, upgrade to Premium.
              </p>
            </details>
            <details className="fr-faq-item">
              <summary>Bib numbers too?</summary>
              <p>OCR reads bibs — useful when your face is behind sunglasses or a grimace.</p>
            </details>
          </div>
        </section>
      </main>
    );
  }

  // -------------------------------------------------------------------------
  // Embedded iframe + offline state. Same behaviour as tools/photo-finder.jsx
  // but inlined so the landing page is self-contained.
  // -------------------------------------------------------------------------
  const PF_FREE_LIMIT = 2;
  const PF_DL_KEY = 'mm-pf-downloads';

  function FaceRecognitionFrame() {
    const [up, setUp] = useState(null);
    const [checking, setChecking] = useState(false);
    const [resultCount, setResultCount] = useState(0);
    const [downloads, setDownloads] = useState(() => {
      try { return parseInt(localStorage.getItem(PF_DL_KEY) || '0', 10) || 0; } catch { return 0; }
    });
    const [showPaywall, setShowPaywall] = useState(false);
    const iframeRef = useRef(null);

    const backendUrl = (window.MM_PHOTO_FINDER_URL || 'http://localhost:8888').replace(/\/+$/, '');
    const theme = document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light';
    const isPremium = false; // TODO: wire to entitlements from parent
    const freeLeft = Math.max(0, PF_FREE_LIMIT - downloads);
    const isLimited = !isPremium && downloads >= PF_FREE_LIMIT;

    const probe = React.useCallback(async () => {
      setChecking(true);
      try {
        const res = await fetch(backendUrl + '/api/health', {
          cache: 'no-store',
          signal: AbortSignal.timeout ? AbortSignal.timeout(2000) : undefined,
        });
        setUp(res.ok);
      } catch { setUp(false); } finally { setChecking(false); }
    }, [backendUrl]);

    useEffect(() => {
      let alive = true;
      let timer = null;
      let attempt = 0;
      let warmupKicked = false;
      const next = () => (attempt < 10 ? 1000 : 4000);
      const tick = async () => {
        try {
          const res = await fetch(backendUrl + '/api/health', {
            cache: 'no-store',
            signal: AbortSignal.timeout ? AbortSignal.timeout(2000) : undefined,
          });
          if (!alive) return;
          if (res.ok) {
            setUp(true);
            if (!warmupKicked) {
              warmupKicked = true;
              fetch(backendUrl + '/api/warmup', { method: 'POST' }).catch(() => {});
            }
            return;
          }
          setUp(false);
        } catch { if (!alive) return; setUp(false); }
        if (alive) { attempt++; timer = setTimeout(tick, next()); }
      };
      tick();
      return () => { alive = false; if (timer) clearTimeout(timer); };
    }, [backendUrl]);

    // Forward theme changes
    useEffect(() => {
      if (!up) return;
      const mo = new MutationObserver(() => {
        const t = document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light';
        iframeRef.current?.contentWindow?.postMessage({ type: 'mt-theme', theme: t }, '*');
      });
      mo.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
      return () => mo.disconnect();
    }, [up]);

    // Send limit to iframe once loaded.
    // Respects admin toggle: window.MM_PF_PAYWALL. When false, no limit is sent.
    useEffect(() => {
      if (!up) return;
      const sendLimit = () => {
        const win = iframeRef.current?.contentWindow;
        if (!win) return;
        const paywallOn = window.MM_PF_PAYWALL === true;
        if (isPremium || !paywallOn) win.postMessage({ type: 'mt-unlock' }, '*');
        else win.postMessage({ type: 'mt-limit', freeCount: PF_FREE_LIMIT }, '*');
      };
      const el = iframeRef.current;
      if (el) el.addEventListener('load', sendLimit);
      setTimeout(sendLimit, 500);
      return () => { if (el) el.removeEventListener('load', sendLimit); };
    }, [up, isPremium]);

    // Listen to iframe messages
    useEffect(() => {
      if (!up) return;
      const onMsg = (e) => {
        if (!e?.data) return;
        if (e.data.type === 'mt-iframe-height') {
          const el = iframeRef.current; if (!el) return;
          const h = Math.max(560, Math.min(4000, Number(e.data.height) || 0));
          if (h) el.style.height = h + 'px';
        }
        if (e.data.type === 'pf-results') setResultCount(e.data.total || 0);
        if (e.data.type === 'pf-download') {
          const newCount = e.data.count || (downloads + 1);
          setDownloads(newCount);
          try { localStorage.setItem(PF_DL_KEY, String(newCount)); } catch {}
          window.mmTrackComplete?.('photo-finder', { success: true });
        }
        if (e.data.type === 'pf-upgrade') setShowPaywall(true);
      };
      window.addEventListener('message', onMsg);
      return () => window.removeEventListener('message', onMsg);
    }, [up, downloads]);

    if (up === null) {
      return (
        <div className="fr-frame fr-frame-warm">
          <div className="fr-warm-icon"><window.Icon name="scan" size={28} strokeWidth={1.6} /></div>
          <div className="fr-warm-title">Warming up the recognition engine</div>
          <div className="fr-warm-sub">Hooking into {backendUrl.replace(/^https?:\/\//, '')}…</div>
        </div>
      );
    }

    if (up === false) {
      return (
        <div className="fr-frame fr-frame-down">
          <div className="fr-warm-icon"><window.Icon name="scan" size={28} strokeWidth={1.6} /></div>
          <div className="fr-warm-title">Engine not running yet</div>
          <div className="fr-warm-sub">
            We're auto-checking in the background. The tool will appear here automatically the moment
            it's available.
          </div>
          <div className="fr-warm-actions">
            <button className="btn btn-secondary" onClick={probe} disabled={checking}>
              <window.Icon name={checking ? 'rotate' : 'check'} size={14} /> {checking ? 'Checking…' : 'Check again'}
            </button>
          </div>
          {window.MM_IS_ADMIN && (
            <details className="fr-admin-hint">
              <summary>Admin diagnostic</summary>
              <pre>cd tools/photorecognation &amp;&amp; ./run.sh</pre>
              <span>Or set the URL in <strong>Admin → Settings → Photo-finder backend</strong>.</span>
            </details>
          )}
        </div>
      );
    }

    return (
      <div className="fr-frame fr-frame-live">
        {/* Usage indicator — hidden when admin disables paywall */}
        {!isPremium && window.MM_PF_PAYWALL === true && (
          <div style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '10px 16px', marginBottom: 10,
            background: 'var(--id-surface)', border: '1px solid var(--id-border)',
            borderRadius: 10, fontSize: 13,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontWeight: 600, color: 'var(--id-text)' }}>
              <window.Icon name="scan" size={14} />
              {isLimited ? 'Free limit reached' : `${freeLeft} free download${freeLeft !== 1 ? 's' : ''} remaining`}
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={{ display: 'flex', gap: 5 }}>
                {[...Array(PF_FREE_LIMIT)].map((_, i) => (
                  <span key={i} style={{
                    width: 10, height: 10, borderRadius: '50%',
                    background: i < downloads ? ACCENT : 'var(--id-border)',
                  }} />
                ))}
              </div>
              {isLimited && (
                <button onClick={() => setShowPaywall(true)} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  padding: '5px 12px', borderRadius: 6, border: `1px solid ${ACCENT}`,
                  background: 'transparent', color: ACCENT, fontSize: 11,
                  fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase',
                  cursor: 'pointer',
                }}>
                  <window.Icon name="bolt" size={12} /> Upgrade
                </button>
              )}
            </div>
          </div>
        )}

        {resultCount > 0 && (
          <div style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            padding: '6px 12px', marginBottom: 8,
            background: 'rgba(16,128,90,0.1)', color: '#10805a', borderRadius: 8,
            fontSize: 12, fontWeight: 600,
          }}>
            <window.Icon name="check" size={12} strokeWidth={2.5} />
            {resultCount} photo{resultCount !== 1 ? 's' : ''} found
          </div>
        )}

        <iframe ref={iframeRef}
                src={`${backendUrl}/?theme=${theme}`}
                title="Face Recognition"
                allow="clipboard-write"
                style={{ width: '100%', height: '78vh', border: 0, display: 'block', background: 'var(--id-surface)', borderRadius: 12 }} />

        {/* Paywall overlay */}
        {showPaywall && (
          <div style={{
            position: 'fixed', inset: 0, zIndex: 100,
            background: 'rgba(0,0,0,0.5)', backdropFilter: 'blur(4px)',
            display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20,
          }} onClick={() => setShowPaywall(false)}>
            <div style={{
              position: 'relative', maxWidth: 420, width: '100%',
              background: 'var(--id-surface)', border: '1px solid var(--id-border)',
              borderRadius: 16, padding: '32px 28px', textAlign: 'center',
            }} onClick={(e) => e.stopPropagation()}>
              <button onClick={() => setShowPaywall(false)} style={{
                position: 'absolute', top: 12, right: 12,
                background: 'none', border: 'none', color: 'var(--id-text-muted)', cursor: 'pointer',
              }}><window.Icon name="x" size={16} /></button>
              <div style={{
                width: 64, height: 64, borderRadius: 16, margin: '0 auto 16px',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                background: ACCENT_SOFT, color: ACCENT,
              }}>
                <window.Icon name="scan" size={32} strokeWidth={1.5} />
              </div>
              <h3 style={{ fontSize: 20, fontWeight: 800, color: 'var(--id-text)', margin: '0 0 8px' }}>Unlock Unlimited Downloads</h3>
              <p style={{ fontSize: 13, color: 'var(--id-text-muted)', lineHeight: 1.55, margin: '0 0 16px' }}>
                You've used your {PF_FREE_LIMIT} free downloads. Upgrade to Premium for unlimited access.
              </p>
              <div style={{ textAlign: 'left', display: 'grid', gap: 8, fontSize: 13, fontWeight: 500, color: 'var(--id-text)' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <window.Icon name="check" size={13} strokeWidth={2.5} style={{ color: ACCENT }} /> Unlimited photo downloads
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <window.Icon name="check" size={13} strokeWidth={2.5} style={{ color: ACCENT }} /> PDF album &amp; ZIP export
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <window.Icon name="check" size={13} strokeWidth={2.5} style={{ color: ACCENT }} /> Instagram story templates
                </div>
              </div>
              <button className="btn btn-primary" style={{ width: '100%', marginTop: 16, background: ACCENT, borderColor: ACCENT }}
                      onClick={() => { setShowPaywall(false); window.mmNavigate?.('home'); }}>
                <window.Icon name="bolt" size={16} /> Upgrade to Premium
              </button>
              <button className="btn btn-secondary" style={{ width: '100%', marginTop: 8 }}
                      onClick={() => setShowPaywall(false)}>
                Maybe later
              </button>
            </div>
          </div>
        )}
      </div>
    );
  }

  window.FaceRecognitionPage = FaceRecognitionPage;
})();
