/* Email-capture popup — grows the newsletter list from non-subscribed visitors.
   Mounted globally in App.jsx as <EmailCapturePopup route={route} user={user} />.

   Incentive: the weekly Deep Dive newsletter (reuses NewsletterSignup for the
   subscribers write + duplicate handling; source="popup").

   Triggers (FIRST to fire wins, then suppressed): after 3 album views · desktop
   exit-intent · 50% scroll on /list · 45s dwell on any page.

   Suppression: never for logged-in accounts (already recipients) or after a
   successful subscribe (localStorage), once per session, and a 30-day cooldown
   after any dismiss. Emits GA4 events popup_shown / popup_submit / popup_dismiss.

   Mobile = bottom slide-up (no full-screen interstitial → protects SEO);
   desktop = centered 440px modal. Styles are injected once, below. */

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

  const LS_SUB = "bbr:nlpop:sub";        // subscribed (permanent)
  const LS_DISMISS = "bbr:nlpop:dismiss"; // last dismiss timestamp
  const LS_ALBUMS = "bbr:nlpop:albums";   // cumulative album-page views
  const SS_SHOWN = "bbr:nlpop:shown";     // shown this session
  const DISMISS_DAYS = 30, ALBUM_THRESHOLD = 3, DWELL_MS = 45000, SCROLL_PCT = 0.5;

  const lsGet = (k) => { try { return localStorage.getItem(k); } catch (e) { return null; } };
  const lsSet = (k, v) => { try { localStorage.setItem(k, v); } catch (e) {} };
  const ssGet = (k) => { try { return sessionStorage.getItem(k); } catch (e) { return null; } };
  const ssSet = (k, v) => { try { sessionStorage.setItem(k, v); } catch (e) {} };
  const track = (name, params) => { try { if (window.gtag) window.gtag("event", name, params || {}); } catch (e) {} };

  function EmailCapturePopup({ route = "home", user = null }) {
    const [open, setOpen] = useState(false);
    const doneRef = useRef(false);   // true once a subscribe succeeds (skip dismiss bookkeeping)
    const openRef = useRef(false);
    openRef.current = open;

    function eligible() {
      if (user) return false;                       // accounts are already recipients
      if (lsGet(LS_SUB)) return false;              // already subscribed via popup
      if (ssGet(SS_SHOWN)) return false;            // once per session
      const d = parseInt(lsGet(LS_DISMISS) || "0", 10);
      if (d && (Date.now() - d) < DISMISS_DAYS * 864e5) return false; // cooldown
      return true;
    }

    function show(trigger) {
      if (openRef.current || !eligible()) return;
      ssSet(SS_SHOWN, "1");
      setOpen(true);
      track("popup_shown", { trigger: trigger, route: route });
    }

    // Count album/deep-dive page views across client-side navigation (fires on
    // each entry to a reading route). Only bothers while still eligible.
    useEffect(() => {
      if ((route === "album" || route === "deep-dive") && !user && !lsGet(LS_SUB)) {
        const n = (parseInt(lsGet(LS_ALBUMS) || "0", 10) || 0) + 1;
        lsSet(LS_ALBUMS, String(n));
      }
    }, [route]);

    // Wire the triggers. Re-runs when route/user change; cleans up its listeners.
    useEffect(() => {
      if (!eligible()) return;

      // 1) Album-view threshold (already accumulated).
      if ((parseInt(lsGet(LS_ALBUMS) || "0", 10) || 0) >= ALBUM_THRESHOLD) { show("albums"); return; }

      const cleanup = [];
      // 2) Dwell on any page.
      const timer = setTimeout(() => show("dwell"), DWELL_MS);
      cleanup.push(() => clearTimeout(timer));

      // 3) Desktop exit-intent (cursor leaves via the top of the viewport).
      const onMouseOut = (e) => {
        if (!e.relatedTarget && e.clientY <= 0 && window.innerWidth > 768) show("exit");
      };
      document.addEventListener("mouseout", onMouseOut);
      cleanup.push(() => document.removeEventListener("mouseout", onMouseOut));

      // 4) 50% scroll depth on the ranked-list page.
      if (route === "list") {
        const onScroll = () => {
          const el = document.documentElement;
          const sc = el.scrollTop || document.body.scrollTop || 0;
          const max = (el.scrollHeight - el.clientHeight) || 1;
          if (sc / max >= SCROLL_PCT) show("scroll");
        };
        window.addEventListener("scroll", onScroll, { passive: true });
        cleanup.push(() => window.removeEventListener("scroll", onScroll));
      }

      return () => cleanup.forEach((fn) => fn());
    }, [route, user]);

    // Esc to close while open.
    useEffect(() => {
      if (!open) return;
      const onKey = (e) => { if (e.key === "Escape") dismiss(); };
      document.addEventListener("keydown", onKey);
      return () => document.removeEventListener("keydown", onKey);
    }, [open]);

    function dismiss() {
      if (!doneRef.current) {
        lsSet(LS_DISMISS, String(Date.now()));
        track("popup_dismiss", { route: route });
      }
      setOpen(false);
    }

    function handleDone(state) {
      doneRef.current = true;
      lsSet(LS_SUB, "1");
      track("popup_submit", { route: route, state: state });
      setTimeout(() => setOpen(false), 2000); // let them read the confirmation
    }

    if (!open) return null;
    const readingCtx = route === "album" || route === "deep-dive";
    return (
      <div
        className="nlpop-overlay"
        role="dialog"
        aria-modal="true"
        aria-label="Subscribe to The Lead-In"
        onClick={(e) => { if (e.target.classList.contains("nlpop-overlay")) dismiss(); }}
      >
        <div className="nlpop-card">
          <button className="nlpop-close" onClick={dismiss} aria-label="Close">×</button>
          <div className="nlpop-kicker">The Lead-In</div>
          <div className="nlpop-title">
            {readingCtx
              ? "Enjoying the read? Get the weekly Deep Dive."
              : "One classic album, properly examined — every Wednesday."}
          </div>
          <div className="nlpop-sub">
            A single legendary record, written up in full. No filler, no spam.
          </div>
          {window.NewsletterSignup && (
            <NewsletterSignup variant="feature" source="popup" hideCopy onDone={handleDone} />
          )}
          <button className="nlpop-decline" onClick={dismiss}>Maybe later</button>
          <div className="nlpop-legal">
            One email a week · unsubscribe anytime. See our <a href="/legal">privacy terms</a>.
          </div>
        </div>
      </div>
    );
  }

  // ---- styles (injected once) ----------------------------------------------
  if (!document.getElementById("nlpop-styles")) {
    const s = document.createElement("style");
    s.id = "nlpop-styles";
    s.textContent = `
      .nlpop-overlay{position:fixed;inset:0;z-index:100000;background:rgba(23,19,15,.55);
        display:flex;align-items:center;justify-content:center;padding:20px;
        animation:nlpopFade .2s ease both;}
      .nlpop-card{position:relative;width:100%;max-width:440px;background:#fffdf8;
        border:1px solid #d8d0bd;border-radius:14px;box-shadow:0 24px 60px rgba(23,19,15,.28);
        padding:30px 26px 22px;animation:nlpopPop .24s cubic-bezier(.2,.8,.3,1) both;}
      .nlpop-close{position:absolute;top:8px;right:10px;width:36px;height:36px;border:0;
        background:transparent;color:#8a8072;font:400 26px/1 Helvetica,Arial,sans-serif;
        cursor:pointer;border-radius:8px;}
      .nlpop-close:hover{color:#17130f;background:#f3ede1;}
      .nlpop-kicker{font:700 11px Helvetica,Arial,sans-serif;letter-spacing:.14em;
        text-transform:uppercase;color:#cf4827;margin-bottom:8px;}
      .nlpop-title{font:700 23px/1.2 Georgia,serif;color:#17130f;margin-bottom:8px;}
      .nlpop-sub{font:400 14px/1.5 Helvetica,Arial,sans-serif;color:#3a322a;margin-bottom:16px;}
      .nlpop-card .nl-copy{display:none;}
      .nlpop-decline{display:block;margin:12px auto 0;border:0;background:transparent;
        color:#8a8072;font:400 13px Helvetica,Arial,sans-serif;text-decoration:underline;
        cursor:pointer;}
      .nlpop-decline:hover{color:#17130f;}
      .nlpop-legal{margin-top:12px;text-align:center;font:400 11px Helvetica,Arial,sans-serif;color:#a89e8c;}
      .nlpop-legal a{color:#8a8072;}
      @keyframes nlpopFade{from{opacity:0}to{opacity:1}}
      @keyframes nlpopPop{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}
      @keyframes nlpopUp{from{transform:translateY(100%)}to{transform:none}}
      @media (max-width:600px){
        .nlpop-overlay{align-items:flex-end;padding:0;}
        .nlpop-card{max-width:100%;border-radius:16px 16px 0 0;padding:26px 20px calc(22px + env(safe-area-inset-bottom));
          animation:nlpopUp .28s cubic-bezier(.2,.8,.3,1) both;}
      }
      @media (prefers-reduced-motion:reduce){
        .nlpop-overlay,.nlpop-card{animation:none;}
      }
    `;
    document.head.appendChild(s);
  }

  window.EmailCapturePopup = EmailCapturePopup;
})();
