/* global React, gtag */
// Build Theory — landing-page Pop-Up Notifications.
//
// Reads ACTIVE pop-ups from Supabase (managed in Superadmin → Pop-Up
// Notifications) and surfaces them on the public landing page as a small,
// non-intrusive carousel anchored to the bottom corner.
//
// Behaviour
//  • Each pop-up has a scroll_depth (0-100%). A pop-up becomes available once
//    the visitor has scrolled at least that far; the carousel appears as soon
//    as the first one is available, then grows as more unlock.
//  • When several are available, coral arrow buttons (left/right) and a coral
//    count badge let the visitor flip between them.
//  • Each pop-up runs a 5-second timer. When it elapses — or the visitor hits
//    cancel — the card "shrinks from the top" into a compact outro box whose
//    message types out letter-by-letter, ending with a "Go to events" button,
//    then disappears after ~3 seconds.
//  • Flipping to another pop-up before the timer ends restarts it at 5s.
//
// Design follows the Build Theory system (paper/ink/coral, Geist, pill CTAs).

const { useState: usePopState, useEffect: usePopEffect, useRef: usePopRef } = React;

const _POP_SB_URL = "https://mfhilndgkxrmhkhmllyw.supabase.co";
const _POP_SB_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im1maGlsbmRna3hybWhraG1sbHl3Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODAzMDA2MDAsImV4cCI6MjA5NTg3NjYwMH0._sTZwE3WhkhHn2yMbRz3ad3IGr3uo3mTxcYczAkQOIo";

const _POP_TIMER_MS = 5000;     // per-pop-up countdown
const _POP_OUTRO_MS = 3000;     // how long the outro lingers after typing
const _POP_SEEN_KEY = "bt_popups_seen";
const _POP_OUTRO_TEXT = "See all events in the footer to view more.";
const _POP_EVENTS_URL = "events.html";

const _POP_CATEGORY_LABEL = {
  webinar: "Upcoming Webinar",
  session: "Session",
  news: "News",
};

// Suppression is per-tab (sessionStorage), NOT per-browser. A fresh tab always
// shows the pop-ups again; within the same tab we don't re-nag on reload. We
// intentionally avoid localStorage so the pop-up isn't silenced across every
// tab/window for hours after a single auto-cycle.
function _popAlreadySeen() {
  try {
    return window.sessionStorage.getItem(_POP_SEEN_KEY) === "1";
  } catch (_) {
    return false;
  }
}

function _popMarkSeen() {
  try {
    window.sessionStorage.setItem(_POP_SEEN_KEY, "1");
  } catch (_) { /* ignore */ }
}

function _popTrack(event, params) {
  try {
    if (typeof gtag === "function") gtag("event", event, params);
  } catch (_) { /* ignore */ }
}

function PopupNotification() {
  const [popups, setPopups] = usePopState([]);   // active pop-ups, ordered
  const [maxDepth, setMaxDepth] = usePopState(0); // highest scroll % reached
  const [phase, setPhase] = usePopState("hidden"); // hidden | carousel | outro
  const [index, setIndex] = usePopState(0);
  const [timeLeft, setTimeLeft] = usePopState(_POP_TIMER_MS);
  const [ready, setReady] = usePopState(false); // small settle delay before first reveal
  const seenRef = usePopRef(_popAlreadySeen());

  // Available = active pop-ups whose scroll depth has been reached.
  const available = popups.filter((p) => (p.scroll_depth || 0) <= maxDepth);

  // --- Fetch active pop-ups once ---
  usePopEffect(() => {
    if (seenRef.current) return undefined;
    let cancelled = false;
    fetch(
      `${_POP_SB_URL}/rest/v1/popups?select=*&status=eq.active&order=sort_order.asc,created_at.desc`,
      { headers: { apikey: _POP_SB_KEY, Authorization: `Bearer ${_POP_SB_KEY}` } }
    )
      .then((r) => (r.ok ? r.json() : []))
      .then((rows) => { if (!cancelled) setPopups(Array.isArray(rows) ? rows : []); })
      .catch(() => { /* fail silently — pop-ups are non-critical */ });
    return () => { cancelled = true; };
  }, []);

  // --- Track scroll depth (also seeds an initial reading for 0% pop-ups) ---
  usePopEffect(() => {
    if (seenRef.current) return undefined;
    const read = () => {
      const h = document.documentElement.scrollHeight - window.innerHeight;
      const depth = h > 0 ? Math.round((window.scrollY / h) * 100) : 100;
      setMaxDepth((cur) => (depth > cur ? depth : cur));
    };
    read();
    window.addEventListener("scroll", read, { passive: true });
    window.addEventListener("resize", read);
    return () => {
      window.removeEventListener("scroll", read);
      window.removeEventListener("resize", read);
    };
  }, []);

  // --- Gentle settle delay so a 0%/on-load pop-up doesn't snap in instantly ---
  usePopEffect(() => {
    if (seenRef.current) return undefined;
    const t = setTimeout(() => setReady(true), 1800);
    return () => clearTimeout(t);
  }, []);

  // --- Reveal the carousel as soon as something is available ---
  usePopEffect(() => {
    if (ready && phase === "hidden" && !seenRef.current && available.length > 0) {
      setPhase("carousel");
      _popTrack("popup_shown", { count: available.length });
    }
  }, [ready, available.length, phase]);

  // --- Per-pop-up countdown; restarts whenever the visible pop-up changes ---
  usePopEffect(() => {
    if (phase !== "carousel") return undefined;
    setTimeLeft(_POP_TIMER_MS);
    const started = Date.now();
    const id = setInterval(() => {
      const left = _POP_TIMER_MS - (Date.now() - started);
      if (left <= 0) {
        clearInterval(id);
        setTimeLeft(0);
        setPhase("outro");
      } else {
        setTimeLeft(left);
      }
    }, 60);
    return () => clearInterval(id);
  }, [phase, index]);

  // --- Dismiss on Escape ---
  usePopEffect(() => {
    if (phase === "hidden") return undefined;
    const onKey = (e) => {
      if (e.key !== "Escape") return;
      if (phase === "carousel") setPhase("outro");
      else finish();
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [phase]);

  const finish = () => {
    seenRef.current = true;
    _popMarkSeen();
    setPhase("hidden");
  };

  const go = (dir) => {
    setIndex((i) => {
      const n = available.length;
      return (i + dir + n) % n;
    });
  };

  if (phase === "hidden") return null;

  if (phase === "outro") {
    return <PopupOutro onClose={finish} />;
  }

  const safeIndex = Math.min(index, available.length - 1);
  const active = available[safeIndex];
  if (!active) return null;
  const hasImage = active.variant === "image" && active.image_url;
  const multiple = available.length > 1;
  const progress = timeLeft / _POP_TIMER_MS;

  const onCta = () => {
    _popTrack("popup_cta_click", { popup_id: active.id, category: active.category });
    if (active.cta_link) window.open(active.cta_link, "_blank", "noopener,noreferrer");
  };

  return (
    <div
      role="dialog"
      aria-label={active.title || "Notification"}
      className="bt-popup-root"
      style={{
        position: "fixed",
        zIndex: 120,
        right: 24,
        bottom: 24,
        width: "min(380px, calc(100vw - 32px))",
        animation: "bt-popup-in .3s var(--ease-out) both",
      }}
    >
      {/* Carousel arrows (only when more than one is available) */}
      {multiple && (
        <React.Fragment>
          <button className="bt-popup-arrow bt-popup-arrow-l" aria-label="Previous" onClick={() => go(-1)}>‹</button>
          <button className="bt-popup-arrow bt-popup-arrow-r" aria-label="Next" onClick={() => go(1)}>›</button>
        </React.Fragment>
      )}

      <div
        key={active.id}
        style={{
          background: "var(--bt-white)",
          borderRadius: 18,
          overflow: "hidden",
          boxShadow: "var(--shadow-modal)",
          border: "1px solid var(--border-hairline)",
          fontFamily: "var(--font-body)",
          animation: "bt-popup-card-in .26s var(--ease-out) both",
        }}
      >
        {/* Top bar: count badge + countdown ring + close */}
        <div
          style={{
            position: "absolute",
            top: 10,
            left: hasImage ? 12 : "auto",
            right: 10,
            zIndex: 3,
            display: "flex",
            alignItems: "center",
            gap: 8,
            width: "calc(100% - 22px)",
            justifyContent: "space-between",
            pointerEvents: "none",
          }}
        >
          {multiple ? (
            <span
              style={{
                pointerEvents: "auto",
                fontFamily: "var(--font-mono)",
                fontSize: 11,
                fontWeight: 600,
                letterSpacing: "0.04em",
                color: "#fff",
                background: "var(--bt-signal)",
                borderRadius: 999,
                padding: "3px 9px",
                boxShadow: "0 1px 4px rgba(255,119,89,0.45)",
              }}
            >
              {safeIndex + 1} / {available.length}
            </span>
          ) : <span />}

          <span style={{ display: "flex", alignItems: "center", gap: 8, pointerEvents: "auto" }}>
            <CountdownRing progress={progress} seconds={Math.ceil(timeLeft / 1000)} onImage={hasImage} />
            <button
              onClick={() => setPhase("outro")}
              aria-label="Close notification"
              style={{
                width: 30,
                height: 30,
                borderRadius: 999,
                border: "none",
                cursor: "pointer",
                background: hasImage ? "rgba(11,11,12,0.55)" : "var(--bt-concrete-050)",
                color: hasImage ? "#fff" : "var(--fg-2)",
                fontSize: 15,
                lineHeight: 1,
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                backdropFilter: hasImage ? "blur(4px)" : "none",
              }}
            >
              ✕
            </button>
          </span>
        </div>

        {hasImage && (
          <div style={{ width: "100%", aspectRatio: "16 / 9", background: "var(--bt-concrete-050)" }}>
            <img
              src={active.image_url}
              alt=""
              style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }}
            />
          </div>
        )}

        <div style={{ padding: 22, display: "flex", flexDirection: "column", gap: 12 }}>
          <span
            style={{
              alignSelf: "flex-start",
              fontFamily: "var(--font-mono)",
              fontSize: 10,
              fontWeight: 500,
              letterSpacing: "0.08em",
              textTransform: "uppercase",
              color: "#7A2A18",
              background: "var(--bt-signal-wash)",
              border: "1px solid var(--bt-signal-soft)",
              borderRadius: 999,
              padding: "4px 10px",
              marginTop: hasImage ? 0 : 26,
            }}
          >
            {_POP_CATEGORY_LABEL[active.category] || active.category}
          </span>

          <h3
            style={{
              margin: 0,
              fontFamily: "var(--font-display)",
              fontWeight: 400,
              fontSize: 22,
              lineHeight: 1.14,
              letterSpacing: "-0.01em",
              color: "var(--bt-ink)",
            }}
          >
            {active.title}
          </h3>

          {active.description && (
            <p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.55, color: "var(--fg-2)" }}>
              {active.description}
            </p>
          )}

          {active.cta_text && active.cta_link && (
            <button
              onClick={onCta}
              className="bt-popup-cta"
              style={{
                alignSelf: "flex-start",
                marginTop: 4,
                background: "var(--bt-ink)",
                color: "var(--fg-on-dark)",
                border: "none",
                borderRadius: 999,
                padding: "13px 22px",
                fontSize: 14,
                fontWeight: 500,
                fontFamily: "var(--font-body)",
                cursor: "pointer",
                display: "inline-flex",
                alignItems: "center",
                gap: 8,
                transition: "background-color .18s var(--ease-out), transform .18s var(--ease-out)",
              }}
            >
              {active.cta_text}
              <span aria-hidden="true">→</span>
            </button>
          )}
        </div>
      </div>

      <PopupStyles />
    </div>
  );
}

// Small depleting countdown ring with the remaining seconds in the centre.
function CountdownRing({ progress, seconds, onImage }) {
  const r = 11;
  const c = 2 * Math.PI * r;
  const track = onImage ? "rgba(255,255,255,0.35)" : "var(--bt-concrete-200)";
  const numColor = onImage ? "#fff" : "var(--bt-ink)";
  return (
    <span
      style={{
        position: "relative",
        width: 30,
        height: 30,
        display: "inline-flex",
        alignItems: "center",
        justifyContent: "center",
        background: onImage ? "rgba(11,11,12,0.45)" : "var(--bt-white)",
        borderRadius: 999,
        backdropFilter: onImage ? "blur(4px)" : "none",
      }}
      aria-hidden="true"
    >
      <svg width="30" height="30" viewBox="0 0 30 30" style={{ position: "absolute", transform: "rotate(-90deg)" }}>
        <circle cx="15" cy="15" r={r} fill="none" stroke={track} strokeWidth="2.5" />
        <circle
          cx="15" cy="15" r={r} fill="none" stroke="var(--bt-signal)" strokeWidth="2.5"
          strokeLinecap="round" strokeDasharray={c} strokeDashoffset={c * (1 - progress)}
          style={{ transition: "stroke-dashoffset .1s linear" }}
        />
      </svg>
      <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600, color: numColor }}>
        {seconds}
      </span>
    </span>
  );
}

// The compact outro: shrinks in from the top, types its message out
// letter-by-letter, reveals a "Go to events" button, then fades away.
function PopupOutro({ onClose }) {
  const [typed, setTyped] = usePopState("");
  const [showBtn, setShowBtn] = usePopState(false);

  usePopEffect(() => {
    let i = 0;
    const typer = setInterval(() => {
      i += 1;
      setTyped(_POP_OUTRO_TEXT.slice(0, i));
      if (i >= _POP_OUTRO_TEXT.length) {
        clearInterval(typer);
        setShowBtn(true);
      }
    }, 38);
    return () => clearInterval(typer);
  }, []);

  // Auto-dismiss after the message has had time to land.
  usePopEffect(() => {
    if (!showBtn) return undefined;
    const t = setTimeout(onClose, _POP_OUTRO_MS);
    return () => clearTimeout(t);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [showBtn]);

  return (
    <div
      role="status"
      className="bt-popup-root"
      style={{
        position: "fixed",
        zIndex: 120,
        right: 24,
        bottom: 24,
        width: "min(380px, calc(100vw - 32px))",
      }}
    >
      <div
        className="bt-popup-outro"
        style={{
          background: "var(--bt-ink)",
          color: "var(--fg-on-dark)",
          borderRadius: 16,
          boxShadow: "var(--shadow-modal)",
          overflow: "hidden",
          transformOrigin: "top center",
        }}
      >
        <div style={{ padding: "16px 18px", display: "flex", flexDirection: "column", gap: 12 }}>
          <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 10 }}>
            <p
              style={{
                margin: 0,
                fontSize: 14.5,
                lineHeight: 1.5,
                color: "var(--fg-on-dark)",
                minHeight: 22,
                fontFamily: "var(--font-body)",
              }}
            >
              {typed}
              <span className="bt-popup-caret">▍</span>
            </p>
            <button
              onClick={onClose}
              aria-label="Dismiss"
              style={{
                flexShrink: 0,
                background: "transparent",
                border: "none",
                color: "var(--fg-on-dark-2)",
                cursor: "pointer",
                fontSize: 14,
                lineHeight: 1,
              }}
            >
              ✕
            </button>
          </div>

          <a
            href={_POP_EVENTS_URL}
            onClick={() => _popTrack("popup_go_to_events", {})}
            className="bt-popup-events-btn"
            style={{
              alignSelf: "flex-start",
              background: "var(--bt-signal)",
              color: "var(--bt-ink)",
              borderRadius: 999,
              padding: "10px 18px",
              fontSize: 13.5,
              fontWeight: 600,
              fontFamily: "var(--font-body)",
              textDecoration: "none",
              display: "inline-flex",
              alignItems: "center",
              gap: 7,
              opacity: showBtn ? 1 : 0,
              transform: showBtn ? "translateY(0)" : "translateY(6px)",
              transition: "opacity .3s var(--ease-out), transform .3s var(--ease-out), background-color .18s var(--ease-out)",
              pointerEvents: showBtn ? "auto" : "none",
            }}
          >
            Go to events <span aria-hidden="true">→</span>
          </a>
        </div>
      </div>

      <PopupStyles />
    </div>
  );
}

function PopupStyles() {
  return (
    <style>{`
      @keyframes bt-popup-in { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
      @keyframes bt-popup-card-in { from { opacity: 0; } to { opacity: 1; } }
      @keyframes bt-popup-outro-shrink {
        from { max-height: 420px; opacity: 0.6; transform: scaleY(1.04); }
        to   { max-height: 200px; opacity: 1; transform: scaleY(1); }
      }
      @keyframes bt-popup-blink { 0%,49% { opacity: 1; } 50%,100% { opacity: 0; } }

      .bt-popup-outro { animation: bt-popup-outro-shrink .42s var(--ease-out) both; }
      .bt-popup-caret { display: inline-block; margin-left: 1px; color: var(--bt-signal); animation: bt-popup-blink .9s steps(1) infinite; }
      .bt-popup-cta:hover { background: var(--bt-signal) !important; color: var(--bt-ink) !important; transform: translateY(-1px); }
      .bt-popup-events-btn:hover { background: var(--bt-signal-deep) !important; }

      .bt-popup-arrow {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        z-index: 4;
        width: 34px; height: 34px;
        border-radius: 999px;
        border: none;
        cursor: pointer;
        background: var(--bt-signal);
        color: #fff;
        font-size: 22px;
        line-height: 1;
        display: flex; align-items: center; justify-content: center;
        box-shadow: 0 4px 12px -2px rgba(255,119,89,0.6);
        opacity: 0.55;
        transition: opacity .15s var(--ease-out), background-color .15s var(--ease-out), transform .15s var(--ease-out);
      }
      .bt-popup-root:hover .bt-popup-arrow { opacity: 1; }
      .bt-popup-arrow:hover { background: var(--bt-signal-deep); }
      .bt-popup-arrow:active { transform: translateY(-50%) scale(0.92); }
      .bt-popup-arrow-l { left: -14px; }
      .bt-popup-arrow-r { right: -14px; }

      @media (max-width: 480px) {
        .bt-popup-root { right: 12px !important; left: 12px !important; bottom: 12px !important; width: auto !important; }
        .bt-popup-arrow-l { left: -6px; }
        .bt-popup-arrow-r { right: -6px; }
      }
      @media (prefers-reduced-motion: reduce) {
        .bt-popup-root, .bt-popup-outro { animation: none !important; }
      }
    `}</style>
  );
}

window.PopupNotification = PopupNotification;
