/* global React */
// Shared reveal controller (IntersectionObserver is unreliable in some
// preview frames, so we use a rAF-throttled scroll/rect check instead).
(function () {
  if (window.__cueWatch) return;
  const watchers = [];
  let scheduled = false;
  function check() {
    scheduled = false;
    const vh = window.innerHeight || document.documentElement.clientHeight;
    for (let i = watchers.length - 1; i >= 0; i--) {
      const w = watchers[i];
      if (!w.el || !w.el.isConnected) {watchers.splice(i, 1);continue;}
      const r = w.el.getBoundingClientRect();
      if (r.top < vh * w.ratio && r.bottom > 0) {
        w.cb();
        if (w.once) watchers.splice(i, 1);
      }
    }
  }
  function onScroll() {
    if (!scheduled) {scheduled = true;requestAnimationFrame(check);}
    setTimeout(check, 60);
  }
  window.addEventListener("scroll", onScroll, { passive: true });
  window.addEventListener("resize", onScroll);
  window.__cueWatch = function (el, cb, ratio, once) {
    watchers.push({ el, cb, ratio: ratio == null ? 0.9 : ratio, once: once !== false });
    requestAnimationFrame(check);
    setTimeout(check, 60);
  };
})();

// "How Cue works" — animated scroll diagram.
// Sources (bottom) flow up into the Cue Index hub; Other data sources → Cue
// Tuner → Index on the left; the Index fans out to the ways you use it on top.

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

  // ---- Design-space geometry (stage is 1120 x 860) ----
  const HUB = { x: 590, y: 430, r: 113 };
  const consumers = [
  { id: "agent", x: 270, y: 138, ico: "smart_toy", title: "Agent", sub: "AEC & real-estate specialist" },
  { id: "studio", x: 590, y: 116, ico: "dashboard_customize", title: "Studio", sub: "Ready-made & custom apps" },
  { id: "connect", x: 910, y: 138, ico: "bolt", title: "Connect your AI", sub: "Claude · ChatGPT · Gemini" }];

  const tuner = { x: 350, y: 430, ico: "tune", title: "Tuner", sub: "Shape the Index · optional" };
  const ods = { x: 350, y: 712, ico: "dns", title: "Other sources", sub: "ERP · CRM · external" };
  const sources = [
  { id: "s2", x: 590, y: 712, ico: "folder_copy", title: "Project files", sub: "Specs · contracts · RFIs" },
  { id: "s3", x: 830, y: 712, ico: "description", title: "Some Silo", sub: "Email · PDFs · sheets" }];


  // ---- Connector geometry (all smooth cubic Béziers) ----
  // The upper curves (hub → consumers) are the exact 180° rotation of the
  // lower curves (sources → hub) about the hub centre (590,430): they start
  // at the point-reflections of the lower hub-touch points and end at the
  // lowest point of each consumer circle, entered with a vertical tangent —
  // so top and bottom read as one symmetric family.
  const P = {
    odsToTuner: `M 350 638 C 350 600, 350 560, 350 516`,
    tunerToHub: `M 436 430 C 450 430, 462 430, 477 430`,
    s2ToHub: `M 590 638 C 590 602, 590 574, 590 543`,
    s3ToHub: `M 830 638 C 830 566, 710 578, 632 538`,
    hubToStudio: `M 590 317 C 590 286, 590 258, 590 214`,
    hubToAgent: `M 548 322 C 470 282, 270 308, 270 236`,
    hubToConnect: `M 632 322 C 710 282, 910 308, 910 236`
  };

  const inPaths = [
  { d: P.odsToTuner, delay: 0.45 },
  { d: P.tunerToHub, delay: 0.66 },
  { d: P.s2ToHub, delay: 0.55 },
  { d: P.s3ToHub, delay: 0.74 }];

  const outPaths = [
  { d: P.hubToStudio, delay: 1.55 },
  { d: P.hubToAgent, delay: 1.7 },
  { d: P.hubToConnect, delay: 1.85 }];

  // Packet flow paths reuse the same Bézier curves.
  const packetPaths = [
  { d: P.s2ToHub, delay: 2.7 },
  { d: P.s3ToHub, delay: 3.0 },
  { d: P.odsToTuner, delay: 2.2 },
  { d: P.tunerToHub, delay: 2.6 }];

  const packetOut = [
  { d: P.hubToAgent, delay: 2.9, lime: true },
  { d: P.hubToStudio, delay: 3.2, lime: true },
  { d: P.hubToConnect, delay: 3.5, lime: true }];


  function Node({ cls, x, y, delay, children }) {
    return (
      <div className={`dg-node ${cls}`} style={{ left: x, top: y }}>
        <div className="dg-node__in" style={{ transitionDelay: `${delay}s` }}>{children}</div>
      </div>);

  }

  function useCounter(target, run, dur = 1400, delay = 1300) {
    const [v, setV] = useState(0);
    useEffect(() => {
      if (!run) return;
      let raf, start;
      const t = setTimeout(() => {
        const step = (now) => {
          if (!start) start = now;
          const p = Math.min(1, (now - start) / dur);
          const e = 1 - Math.pow(1 - p, 3);
          setV(Math.round(target * e));
          if (p < 1) raf = requestAnimationFrame(step);
        };
        raf = requestAnimationFrame(step);
      }, delay);
      // fallback: guarantee the final value even if rAF is throttled
      const done = setTimeout(() => setV(target), delay + dur + 500);
      return () => {clearTimeout(t);clearTimeout(done);cancelAnimationFrame(raf);};
    }, [run, target]);
    return v;
  }

  function Diagram() {
    const wrapRef = useRef(null);
    const scalerRef = useRef(null);
    const stageRef = useRef(null);
    const hubLogoRef = useRef(null);
    const [run, setRun] = useState(false);
    const files = useCounter(65000, run);
    const formats = useCounter(122, run);
    const nodes = useCounter(15, run);
    const edges = useCounter(123, run);

    // fit-to-width scaling
    useEffect(() => {
      const fit = () => {
        const wrap = wrapRef.current,scaler = scalerRef.current;
        if (!wrap || !scaler) return;
        const w = wrap.clientWidth;
        const scale = Math.min(1, w / 1120);
        // origin top-left + explicit left margin so the scaled stage stays
        // centered even when the container is narrower than 1120px (margin
        // auto can't center an overflowing box).
        scaler.style.transformOrigin = "top left";
        scaler.style.transform = `scale(${scale})`;
        scaler.style.width = "1120px";
        scaler.style.marginLeft = `${Math.max(0, (w - 1120 * scale) / 2)}px`;
        wrap.style.height = `${860 * scale}px`;
      };
      fit();
      window.addEventListener("resize", fit);
      const ro = new ResizeObserver(fit);
      if (wrapRef.current) ro.observe(wrapRef.current);
      return () => {window.removeEventListener("resize", fit);ro.disconnect();};
    }, []);

    // run on scroll into view
    useEffect(() => {
      if (stageRef.current) window.__cueWatch(stageRef.current, () => setRun(true), 0.82);
    }, []);

    // lock the final state shortly after the intro so it renders even if
    // CSS transitions are throttled (tooling/background frames)
    useEffect(() => {
      if (!run) return;
      const t = setTimeout(() => {if (stageRef.current) stageRef.current.classList.add("run-final");}, 3400);
      return () => clearTimeout(t);
    }, [run]);

    // fire the Cue Index logomark draw once the diagram scrolls into view
    // (unless the logo-animation tweak is off). Restart cleanly so it always
    // animates in-scope rather than having already played off-screen.
    useEffect(() => {
      if (!run) return;
      const el = hubLogoRef.current;
      if (!el) return;
      if (document.documentElement.dataset.cueLogo === "off") return;
      el.removeAttribute("active");
      const id = requestAnimationFrame(() => el.setAttribute("active", "true"));
      return () => cancelAnimationFrame(id);
    }, [run]);

    return (
      <div>
        <div className="diagram-wrap" ref={wrapRef}>
          <div className="diagram-scaler" ref={scalerRef}>
            <div className={`dg-stage ${run ? "run" : ""}`} ref={stageRef}>
              <svg className="dg-svg" viewBox="0 0 1120 860" preserveAspectRatio="xMidYMid meet">
                {inPaths.map((p, i) =>
                <path key={`in${i}`} className="dg-path" d={p.d} pathLength="1" style={{ transitionDelay: `${p.delay}s` }} />
                )}
                {outPaths.map((p, i) =>
                <path key={`out${i}`} className="dg-path out" d={p.d} pathLength="1" style={{ transitionDelay: `${p.delay}s` }} />
                )}
              </svg>

              {/* packets */}
              {packetPaths.map((p, i) =>
              <div key={`pk${i}`} className="dg-packet" style={{ offsetPath: `path('${p.d}')`, animationDelay: `${p.delay}s` }} />
              )}
              {packetOut.map((p, i) =>
              <div key={`pko${i}`} className="dg-packet lime" style={{ offsetPath: `path('${p.d}')`, animationDelay: `${p.delay}s` }} />
              )}

              {/* sources */}
              {sources.map((s, i) =>
              <Node key={s.id} cls="dg-src" x={s.x} y={s.y} delay={0.15 + i * 0.12}>
                  <div className="dg-circle">
                    <div className="dg-ico"><span className="cue-icon">{s.ico}</span></div>
                    <div className="dg-title">{s.title}</div>
                    <div className="dg-sub">{s.sub}</div>
                  </div>
                </Node>
              )}

              {/* other sources (a source card, feeding the Tuner) + tuner */}
              <Node cls="dg-src" x={ods.x} y={ods.y} delay={0.35}>
                <div className="dg-circle">
                  <div className="dg-ico"><span className="cue-icon">{ods.ico}</span></div>
                  <div className="dg-title">{ods.title}</div>
                  <div className="dg-sub">{ods.sub}</div>
                </div>
              </Node>
              <Node cls="dg-tuner" x={tuner.x} y={tuner.y} delay={0.5}>
                <div className="dg-circle">
                  <div className="dg-ico"><span className="cue-icon">{tuner.ico}</span></div>
                  <div className="dg-title">{tuner.title}</div>
                  <div className="dg-sub">{tuner.sub}</div>
                </div>
              </Node>

              {/* background Cue wordmark — centered watermark behind the graphic to show the whole platform is Cue */}
              <div style={{
                position: "absolute", inset: 0,
                display: "flex", alignItems: "center", justifyContent: "center",
                zIndex: 0, pointerEvents: "none", opacity: 0,
                transition: "opacity 1.2s ease 2.2s"
              }} ref={el => { if (el && run) requestAnimationFrame(() => el.style.opacity = "1"); }}>
                <cue-logo class="cl-bg" mode="playful" active="true" ref={hubLogoRef}></cue-logo>
              </div>

              {/* hub */}
              <div className="dg-node dg-hub" style={{ left: HUB.x, top: HUB.y }}>
                <div className="dg-hub__ring" />
                <div className="dg-hub__ring green" />
                <div className="dg-node__in" style={{ transitionDelay: "1.0s" }}>
                  <div className="dg-circle">
                    <div className="dg-ico" style={{ width: 52, height: 52, borderRadius: 16, background: "rgba(40,89,225,0.12)", color: "var(--cue-color-blue)", display: "grid", placeItems: "center", flex: "none" }}>
                      <span className="cue-icon" style={{ fontSize: 30 }}>hub</span>
                    </div>
                    <div className="dg-title" style={{ fontSize: 16 }}>Index</div>
                    <div className="dg-sub">The connected foundation under everything</div>
                    <div className="dg-hub__count" style={{ height: "75px", width: "107px" }}>
                      <span>100k+ files · 20+ formats</span>
                      <span>100m+ nodes &amp; edges</span>
                    </div>
                  </div>
                </div>
              </div>

              {/* consumers */}
              {consumers.map((c, i) =>
              <Node key={c.id} cls="dg-consumer" x={c.x} y={c.y} delay={1.8 + i * 0.15}>
                  <div className="dg-circle">
                    <div className="dg-ico">
                      {c.id === "agent" && window.CueAgentIcon ?
                    React.createElement(window.CueAgentIcon, { size: 26 }) :
                    <span className="cue-icon">{c.ico}</span>}
                    </div>
                    <div className="dg-title">{c.title}</div>
                    <div className="dg-sub">{c.sub}</div>
                    {c.soon ? <div className="dg-tag-soon">Coming soon</div> : null}
                  </div>
                </Node>
              )}
            </div>
          </div>
        </div>

        <div className="dg-legend">
          <div className="dg-legend__item">
            <span className="dg-legend__num">01</span>
            <div><p className="dg-legend__t">Connect your documents</p><p className="dg-legend__d">Point Cue at your project files, silos and other systems — in whatever shape they're in.</p></div>
          </div>
          <div className="dg-legend__item">
            <span className="dg-legend__num">02</span>
            <div><p className="dg-legend__t">Cue builds the Index</p><p className="dg-legend__d">Everything is read and connected into one searchable foundation. Shape it with the Tuner if you need to.</p></div>
          </div>
          <div className="dg-legend__item">
            <span className="dg-legend__num">03</span>
            <div><p className="dg-legend__t">Put it to work</p><p className="dg-legend__d">Connect the AI you already use, build on it with Cue Studio, or bring in the Cue Agent.</p></div>
          </div>
        </div>
      </div>);

  }

  return { Diagram };
}();

window.CueDiagram = DG.Diagram;