/* ABM Pages - Scrollable GTM system. Shared React kit for the 5 variations.
   Babel script. Reads window.SD + the abmp3-kit exports (Icon, Tag, PillBtn…).
   Exports building blocks to window. */
const { useState, useEffect, useRef, useCallback } = React;

/* Entrance animations are an enhancement layered on visible-by-default content.
   We only arm the hidden→animate state once a real requestAnimationFrame tick
   fires - proving a live, non-frozen, visible context. In print, PDF export,
   reduced-motion, or throttled/snapshot frames (where rAF is paused) the body
   never gets .sd-animate, so content stays at its finished, visible state. */
(function enableAnim() {
  if (window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
  const go = () => {
    const b = document.body;
    if (!b) return;
    b.classList.add("sd-noanim");     // suppress transitions for the hide
    b.classList.add("sd-animate");    // reveals jump to hidden instantly
    void b.offsetWidth;               // reflow
    requestAnimationFrame(() => b.classList.remove("sd-noanim"));
  };
  requestAnimationFrame(() => requestAnimationFrame(go));
})();

/* ---------- reveal-on-scroll ---------- */
function useInView(opts) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let done = false;
    const reveal = () => { if (!done) { done = true; setSeen(true); } };
    const check = () => {
      const vh = window.innerHeight || document.documentElement.clientHeight || 0;
      if (vh < 200) { reveal(); return; }
      const r = el.getBoundingClientRect();
      if (r.top < vh * 0.92 && r.bottom > 0) reveal();
    };
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) reveal(); });
    }, { threshold: 0.18, rootMargin: "0px 0px -8% 0px", ...(opts || {}) });
    io.observe(el);
    // fallback: works even where IntersectionObserver callbacks don't fire (capture frames, etc.)
    const onScroll = () => { if (!done) check(); };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    requestAnimationFrame(check);
    // poll until in view (reliable where scroll/rAF are throttled)
    let pollId;
    const poll = () => { if (done) return; check(); pollId = setTimeout(poll, 200); };
    pollId = setTimeout(poll, 120);
    return () => { io.disconnect(); window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); clearTimeout(pollId); };
  }, []);
  return [ref, seen];
}

/* generic reveal wrapper. dir: up|left|right|scale */
function Reveal({ dir = "up", delay = 0, as = "div", className = "", style, children, ...rest }) {
  const [ref, seen] = useInView();
  const cls = { up: "sd-reveal", left: "sd-reveal-l", right: "sd-reveal-r", scale: "sd-reveal-s" }[dir] || "sd-reveal";
  const El = as;
  return (
    <El ref={ref} className={cls + (seen ? " in" : "") + (className ? " " + className : "")}
        style={{ transitionDelay: (delay || 0) + "ms", ...style }} {...rest}>
      {children}
    </El>
  );
}

/* ---------- section header ---------- */
function SecHead2({ n, title, lede, action, theme }) {
  return (
    <div className="sd-sec-head">
      <div style={{ maxWidth: 720 }}>
        <Reveal dir="up">
          <div className="sd-kicker">
            <span className="bar" />
            <span className="sd-secnum">{n} / 04</span>
            <Tag tone="ember">{title.toUpperCase()}</Tag>
          </div>
        </Reveal>
        <Reveal dir="up" delay={60}><h2 className="sd-h2">{title}</h2></Reveal>
        {lede && <Reveal dir="up" delay={120}><p className="sd-lede">{lede}</p></Reveal>}
      </div>
      {action && <Reveal dir="up" delay={120}>{action}</Reveal>}
    </div>
  );
}

/* ---------- source feed (a couple sources → database) ---------- */
function SourceList({ live }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      {window.SD.sources.map((s, i) => (
        <Reveal key={s.id} dir="left" delay={i * 70}>
          <div className="sd-source">
            <span className="glyph">{s.glyph}</span>
            <div style={{ minWidth: 0 }}>
              <div className="nm">{s.name}</div>
              <div className="kd">{s.kind}</div>
            </div>
            {live && <span style={{ marginLeft: "auto", width: 7, height: 7, borderRadius: 7, background: "var(--abm-ember)", animation: "sd-pulse 1.3s ease-in-out infinite" }} />}
          </div>
        </Reveal>
      ))}
    </div>
  );
}

/* database stage stack (what happens inside the DB) */
function DBStages({ compact }) {
  return (
    <div>
      {window.SD.dbStages.map((s, i) => (
        <Reveal key={s.id} dir="up" delay={i * 80}>
          <div className={"sd-stage" + (s.crm ? " crm" : "")}>
            <span className="ic"><Icon name={s.icon} size={18} /></span>
            <div style={{ minWidth: 0 }}>
              <div className="lab">{s.label}{s.crm && <span className="abm-tag" style={{ marginLeft: 10, color: "var(--abm-blue)" }}>SALESFORCE</span>}</div>
              {!compact && <div className="ds">{s.desc}</div>}
            </div>
            <div style={{ textAlign: "right" }}>
              <span className="ct">{s.count}</span>
            </div>
          </div>
        </Reveal>
      ))}
    </div>
  );
}

/* ---------- Claude Code console (animated, replayable) ---------- */
function ConsoleStream({ title = "claude-code", height = 520, autostart = true, speed = 1, onDone, avatar = false, recordCard = false }) {
  const script = window.SD.consoleScript;
  const [shown, setShown] = useState(0);
  const [done, setDone] = useState(false);
  const bodyRef = useRef(null);
  const timerRef = useRef(null);
  const startedRef = useRef(false);
  const [ref, seen] = useInView({ threshold: 0.3 });

  const run = useCallback(() => {
    clearTimeout(timerRef.current);
    setShown(0); setDone(false);
    let i = 0;
    const tick = () => {
      i += 1;
      setShown(i);
      if (i >= script.length) { setDone(true); onDone && onDone(); return; }
      const line = script[i - 1];
      const base = line.t === "src" || line.t === "run" ? 620 : line.t === "signal" ? 460 : line.t === "cmd" ? 560 : 360;
      timerRef.current = setTimeout(tick, base / speed);
    };
    timerRef.current = setTimeout(tick, 320);
  }, [script, speed, onDone]);

  useEffect(() => {
    if (!autostart || !seen || startedRef.current) return;
    startedRef.current = true;
    run();
  }, [seen, autostart, run]);

  useEffect(() => () => clearTimeout(timerRef.current), []);

  useEffect(() => {
    if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
  }, [shown]);

  const replay = () => { run(); };

  const gut = { claude: "$", cmd: "›", info: "·", src: "↘", run: "•", ok: "✓", signal: "◆", done: "★" };

  return (
    <div className="sd-console" ref={ref} style={{ height }}>
      <div className="sd-console-bar">
        <span className="lights"><i style={{ background: "#ff5f57" }} /><i style={{ background: "#febc2e" }} /><i style={{ background: "#28c840" }} /></span>
        <span className="ttl">{title}</span>
        <span className="live"><i />{done ? "READY" : "STREAMING"}</span>
      </div>
      <div className="sd-console-body" ref={bodyRef} style={{ height: height - 45 }}>
        {avatar && <ConsoleAvatar group={shown > 0 ? (script[Math.min(shown, script.length) - 1] || {}).group : null} done={done} />}
        {script.slice(0, shown).map((l, i) => (
          <div key={i} className={"sd-cl sd-cl--" + l.t + " show"}>
            <span className="gut">{gut[l.t] || "·"}</span>
            <div className="body">
              <span className="tx">{l.text}</span>
              {l.sub && l.t === "src"
                ? <div className="sd-cl-chips">{l.sub.split(" · ").map((c, j) => <span key={j} className="sd-cl-chip">{c}</span>)}</div>
                : l.sub && <div className="sub">{l.sub}</div>}
            </div>
          </div>
        ))}
        {!done && shown > 0 && <div className="sd-cl show" style={{ paddingLeft: 28 }}><span className="sd-caret" /></div>}
        {done && recordCard && <ConsoleRecord />}
        {done && (
          <div style={{ marginTop: 16 }}>
            <button className="sd-replay" onClick={replay}><Icon name="loop" size={13} /> Replay</button>
          </div>
        )}
      </div>
    </div>
  );
}

/* ---------- Clay table ---------- */
function FitCell({ v, tone }) {
  return (
    <span className={"sd-fit " + tone}>
      <span className="bar"><i style={{ width: v + "%" }} /></span>{v}
    </span>
  );
}
function RouteCell({ id }) {
  const r = window.SD.ROUTES[id];
  return (
    <span className="sd-route">
      <span className="rg" style={{ background: r.color }}>{r.glyph}</span>
      <span className="rl">{r.label}</span>
    </span>
  );
}
function ClayTable({ interactive, name = "TAM · routing", maxRows }) {
  const { clayColumns, clayRows } = window.SD;
  const rows = maxRows ? clayRows.slice(0, maxRows) : clayRows;
  const [sel, setSel] = useState(null);
  return (
    <div className="sd-clay">
      <div className="sd-clay-top">
        <span className="abm-itile abm-itile--ember" style={{ width: 24, height: 24 }}><Icon name="route" size={13} /></span>
        <span className="nm">{name}</span>
        <span className="meta">{rows.length} accounts · {clayColumns.length} enriched columns · live</span>
      </div>
      <div style={{ overflowX: "auto" }}>
        <table className="sd-claytbl">
          <thead>
            <tr>{clayColumns.map((c) => <th key={c.key} style={{ minWidth: c.w }}>{c.label}</th>)}</tr>
          </thead>
          <tbody>
            {rows.map((r, i) => (
              <React.Fragment key={r.account}>
                <tr className={"sd-clay-row" + (sel === i ? " sel" : "")}
                    style={interactive ? { cursor: "pointer" } : null}
                    onClick={interactive ? () => setSel(sel === i ? null : i) : undefined}>
                  <td>
                    <div className="sd-clay-acct">
                      <span className="fav">{r.account[0]}</span>
                      <div><div className="nm">{r.account}</div><div className="dm">{r.domain}</div></div>
                    </div>
                  </td>
                  <td><span className="abm-chip" style={{ fontSize: 10 }}>{r.source}</span></td>
                  <td><FitCell v={r.fit} tone={r.fitTone} /></td>
                  <td><span className="sd-trig"><span className="pt" />{r.trigger}</span></td>
                  <td><span className={"sd-stage-tag " + r.stageTone}>{r.stage}</span></td>
                  <td style={{ fontWeight: 500 }}>{r.next}</td>
                  <td><RouteCell id={r.route} /></td>
                </tr>
                {interactive && sel === i && (
                  <tr><td colSpan={clayColumns.length} style={{ padding: 0 }}>
                    <div className="sd-clay-detail">
                      <RowDetail row={r} />
                    </div>
                  </td></tr>
                )}
              </React.Fragment>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function RowDetail({ row }) {
  const crit = [
    ["Fit criteria", `ICP match · ${row.fit}/100 · ${row.fitTone.toUpperCase()}`],
    ["Trigger", row.trigger],
    ["Classification", row.stage],
    ["Routing rule", window.SD.ROUTES[row.route].label],
  ];
  return (
    <div style={{ display: "grid", gridTemplateColumns: "1.2fr 1fr", gap: 28 }}>
      <div>
        <div className="abm-tag" style={{ marginBottom: 12 }}>WHY THIS ROUTING</div>
        <div style={{ display: "grid", gridTemplateColumns: "auto 1fr", gap: "10px 18px" }}>
          {crit.map(([k, v]) => (
            <React.Fragment key={k}>
              <span className="abm-tag" style={{ color: "var(--abm-faint)" }}>{k}</span>
              <span style={{ fontSize: 13.5, fontWeight: 500 }}>{v}</span>
            </React.Fragment>
          ))}
        </div>
      </div>
      <div style={{ borderLeft: "1px solid var(--abm-line)", paddingLeft: 24 }}>
        <div className="abm-tag" style={{ marginBottom: 12, color: "var(--abm-ember)" }}>ACTIVATION CHAIN</div>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {["Salesforce · create lead", window.SD.ROUTES[row.route].label, "Sales alert + brief", "Feedback → re-score"].map((s, i) => (
            <div key={i} style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 13 }}>
              <span style={{ width: 18, height: 18, display: "grid", placeItems: "center", background: i === 3 ? "var(--abm-amber)" : "var(--abm-ember)", color: i === 3 ? "var(--abm-ink)" : "#fff", fontFamily: "var(--abm-mono)", fontSize: 10 }}>{i + 1}</span>
              {s}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ---------- enablement + feedback ---------- */
function EnablementGrid() {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 16 }}>
      {window.SD.enablement.map((e, i) => (
        <Reveal key={e.title} dir="up" delay={i * 70}>
          <div className="sd-enable">
            <span className="ic"><Icon name={e.icon} size={24} /></span>
            <div className="t">{e.title}</div>
            <div className="d">{e.desc}</div>
          </div>
        </Reveal>
      ))}
    </div>
  );
}

function FeedbackLoop({ note = "Every outcome re-scores the database - the next cycle starts smarter." }) {
  return (
    <div>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 18 }}>
        <span style={{ color: "var(--abm-amber)" }}><Icon name="loop" size={20} /></span>
        <span className="abm-tag" style={{ color: "inherit" }}>FEEDBACK LOOP</span>
        <span style={{ flex: 1, height: 1, background: "var(--abm-line)" }} />
        <span className="abm-tag" style={{ color: "var(--abm-amber)" }}>→ FEEDS THE DATABASE</span>
      </div>
      <div style={{ display: "flex", flexWrap: "wrap", gap: 10 }}>
        {window.SD.feedback.map((f, i) => (
          <Reveal key={f.label} dir="scale" delay={i * 50}>
            <span className="sd-fb-chip"><span className="pt" />{f.label}</span>
          </Reveal>
        ))}
      </div>
      <p className="sd-lede" style={{ marginTop: 22, fontSize: 16 }}>{note}</p>
    </div>
  );
}

/* ---------- final record card printed in the console ---------- */
function ConsoleRecord() {
  const sigs = window.SD.signals;
  return (
    <div className="sd-record">
      <div className="sd-record-hd"><span className="mk">★</span> RECORD SENT TO CLAY</div>
      <div className="sd-record-row"><span className="k">account</span><span className="v">Northwind Logistics</span></div>
      <div className="sd-record-row"><span className="k">classified</span><span className="v">Tier 1 · fit 94 · intent HIGH · angle cost-to-serve</span></div>
      <div className="sd-record-row"><span className="k">signals enriched</span><span className="v">{sigs.length} tracked</span></div>
      <div className="sd-record-chips">{sigs.map((s) => <span key={s} className="sd-record-chip">{s}</span>)}</div>
    </div>
  );
}

/* ---------- Claude avatar that spawns the agents ---------- */
function ConsoleAvatar({ group, done }) {
  const agents = [["enrich", "Enrich"], ["research", "Research"], ["signal", "Signals"]];
  return (
    <div className="sd-agentbar">
      <span className={"sd-avatar" + (done ? " is-done" : "")}>
        <i /><i /><i /><i />
      </span>
      <div style={{ minWidth: 0 }}>
        <div className="sd-agentbar-ttl">Claude Code agent {done ? "· run complete" : "· orchestrating"}</div>
        <div className="sd-agentchips">
          {agents.map(([k, l]) => <span key={k} className={"sd-agentchip" + (group === k ? " on" : "") + (done ? " done" : "")}>{l}</span>)}
        </div>
      </div>
      <span className="sd-agentarrow">→</span>
    </div>
  );
}

/* ---------- scroll-driven zoom (small → full as it nears viewport center) ---------- */
function ScrollZoom({ minScale = 0.86, children }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    el.style.transformOrigin = "center top";
    el.style.willChange = "transform";
    el.style.transition = "transform .1s linear";
    let last = -1;
    const apply = () => {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight || 800;
      const center = r.top + el.offsetHeight / 2;
      const d = Math.min(1, Math.abs(center - vh / 2) / (vh * 0.6));
      const s = Math.max(minScale, 1 - d * (1 - minScale));
      if (Math.abs(s - last) > 0.003) { el.style.transform = "scale(" + s.toFixed(3) + ")"; last = s; }
    };
    apply();
    let stop = false, t;
    const loop = () => { if (stop) return; apply(); t = setTimeout(loop, 80); };
    t = setTimeout(loop, 80);
    return () => { stop = true; clearTimeout(t); };
  }, []);
  return <div ref={ref}>{children}</div>;
}

/* ---------- left section rail + scroll progress ---------- */
function SectionRail({ ids }) {
  const meta = window.SD.sectionsMeta;
  const [active, setActive] = useState(meta[0].id);
  useEffect(() => {
    const obs = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) setActive(e.target.id); });
    }, { threshold: 0.4, rootMargin: "-30% 0px -50% 0px" });
    meta.forEach((m) => { const el = document.getElementById(m.id); if (el) obs.observe(el); });
    return () => obs.disconnect();
  }, []);
  return (
    <nav className="sd-rail">
      {meta.map((m) => (
        <a key={m.id} href={"#" + m.id} className={active === m.id ? "on" : ""}>
          <span className="tick" style={active === m.id ? { background: m.color, borderColor: m.color } : null} />
          <span className="lbl">{m.n} {m.label}</span>
        </a>
      ))}
    </nav>
  );
}

/* ---------- hub link (top-right) ---------- */
function HubLink() {
  return (
    <div className="sd-hub">
      <a className="sd-hublink" href="index.html"><Icon name="scatter" size={13} /> All 5 variations</a>
    </div>
  );
}

/* ---------- hero ---------- */
function Hero({ headline, sub, kicker = "THE GTM SYSTEM", cta = "Book a system-mapping call", cta2 = "See how it works", children }) {
  const s = window.SD.hero;
  return (
    <header className="sd-hero">
      <div className="sd-wrap" style={{ width: "100%" }}>
        <Reveal dir="up">
          <div className="sd-kicker"><span className="bar" /><Tag tone="ember">{kicker}</Tag></div>
        </Reveal>
        <Reveal dir="up" delay={80}><h1>{headline || s.headline}</h1></Reveal>
        <Reveal dir="up" delay={160}><p className="sd-lede">{sub || s.sub}</p></Reveal>
        <Reveal dir="up" delay={240}>
          <div className="sd-hero-cta">
            <PillBtn label={cta} variant="ember" />
            <PillBtn label={cta2} />
          </div>
        </Reveal>
        {children}
      </div>
      <div className="sd-wrap" style={{ position: "absolute", left: 0, right: 0, bottom: 0 }}>
        <div className="sd-scrollcue"><span className="dot" /><span className="abm-tag">SCROLL · THE SYSTEM RUNS BELOW</span></div>
      </div>
    </header>
  );
}

/* ---- textured pixel panel: real gradient asset + deterministic pixel mosaic
   overlay (structure on top of the grain). tex: green | coral | grain ---- */
const TEX_SRC = {
  green: (window.__resources || {}).texGreen || "assets/tex-green.png",
  coral: (window.__resources || {}).texCoral || "assets/tex-coral.png",
  grain: (window.__resources || {}).texGrain || "assets/tex-grain.png"
};
function TexturePanel({ tex = "green", cols = 24, rows = 12, seed = 14, style, cellStyle, children, gridColor = "rgba(255,255,255,0.07)" }) {
  const rnd = window.ABM.mulberry(seed);
  const cells = [];
  for (let i = 0; i < cols * rows; i++) {
    const r = rnd();
    let bg = "transparent";
    if (r < 0.12) bg = "rgba(0,0,0,0.20)";
    else if (r < 0.24) bg = "rgba(0,0,0,0.09)";
    else if (r < 0.38) bg = "rgba(255,255,255,0.10)";
    else if (r < 0.45) bg = "rgba(255,255,255,0.20)";
    cells.push(bg);
  }
  return (
    <div style={{ position: "relative", overflow: "hidden", backgroundImage: `url(${TEX_SRC[tex]})`, backgroundSize: "cover", backgroundPosition: "center", ...style }}>
      <div style={{ position: "absolute", inset: 0, display: "grid", gridTemplateColumns: `repeat(${cols},1fr)`, gridTemplateRows: `repeat(${rows},1fr)`, gap: 1, background: gridColor }}>
        {cells.map((c, i) => <i key={i} style={{ background: c, ...cellStyle }} />)}
      </div>
      {children}
    </div>
  );
}

Object.assign(window, {
  useInView, Reveal, SecHead2, SourceList, DBStages, ConsoleStream,
  ClayTable, FitCell, RouteCell, RowDetail, EnablementGrid, FeedbackLoop,
  SectionRail, HubLink, Hero, TexturePanel, ConsoleAvatar, ConsoleRecord, ScrollZoom,
});
