// landing-vortex.jsx — "Connected workspace" halo / orbit layout
// Clean enterprise SaaS section: a semi-circular halo of app integration
// tiles beneath the headline. Featured logos sit at the front, sharp and
// prominent; backing tiles recede along the arc with progressive scale,
// opacity and blur to suggest a wide ecosystem.

(function () {
  const FLOW = {
    width: 1280,
    height: 560,
    centerX: 640,
    orbitTopY: 96,
    mergeY: 310,
    coreY: 502,
    radius: 880,
    maxAngle: Math.PI * 0.46,
    ySquash: 0.42,
  };

  const clamp01 = (v) => Math.max(0, Math.min(1, v));

  // i18n bridge
  const __i18nVx = (typeof window !== "undefined" && window.Wisbid && window.Wisbid.i18n) || null;
  const __tVx = (k, fb) => { if (!__i18nVx) return fb; const v = __i18nVx.t(k); return v === k ? fb : v; };
  const useVxT = () => {
    const i18n = (typeof window !== "undefined" && window.Wisbid && window.Wisbid.i18n) || null;
    const [, force] = useState(0);
    useEffect(() => {
      if (!i18n) return;
      return i18n.subscribe(() => force((v) => v + 1));
    }, [i18n]);
    return (k, fb) => i18n ? i18n.t(k, fb) : fb;
  };

  function useCompactViewport() {
    const [m, setM] = useState(() =>
      typeof window !== "undefined" ? window.matchMedia("(max-width: 1024px)").matches : false
    );
    useEffect(() => {
      const mq = window.matchMedia("(max-width: 1024px)");
      const update = () => setM(mq.matches);
      update();
      mq.addEventListener("change", update);
      return () => { mq.removeEventListener("change", update); };
    }, []);
    return m;
  }

  function useFlowProgress(ref) {
    const [p, setP] = useState(0);
    useEffect(() => {
      const el = ref.current;
      if (!el) return;
      const media = window.matchMedia("(prefers-reduced-motion: reduce)");
      if (media.matches) {
        setP(1);
        return;
      }

      let raf = 0;
      const update = () => {
        raf = 0;
        const r = el.getBoundingClientRect();
        const vh = window.innerHeight || 1;
        const next = clamp01((0 - r.top) / (vh * 0.56));
        setP(next < 0.01 ? 0 : next);
      };
      const request = () => {
        if (!raf) raf = window.requestAnimationFrame(update);
      };

      update();
      window.addEventListener("scroll", request, { passive: true });
      window.addEventListener("resize", request);
      return () => {
        window.removeEventListener("scroll", request);
        window.removeEventListener("resize", request);
        if (raf) window.cancelAnimationFrame(raf);
      };
    }, [ref]);
    return p;
  }

  /* ---------- tiles ---------- */
  // Featured 9 = real product logos (front row, sharp)
  const FEATURED = [
    { name: "Microsoft Teams",  src: "assets/icons/teams.png" },
    { name: "Xero",             src: "assets/icons/xero.png" },
    { name: "Outlook",          src: "assets/icons/outlook.png" },
    { name: "SharePoint",       src: "assets/icons/sharepoint.png" },
    { name: "Gmail",            src: "assets/icons/gmail.svg" },
    { name: "Power BI",         src: "assets/icons/powerbi.png" },
    { name: "Google Calendar",  src: "assets/icons/google-calendar.webp" },
    { name: "Outlook Calendar", src: "assets/icons/outlook-calendar.jpg" },
    { name: "QuickBooks",       src: "assets/icons/quickbooks.png" },
  ];

  // Background "ghost" tiles — colour-tinted monograms representing the rest
  // of an enterprise integration ecosystem. Original artwork (single letter
  // monograms in brand-adjacent gradients), not real third-party logos.
  const GHOSTS = [
    { mark: "S", tone: "linear-gradient(135deg,#5B5FC7 0%,#7E81C6 100%)" }, // Skype-ish purple
    { mark: "D", tone: "linear-gradient(135deg,#0061FF 0%,#4F8AFF 100%)" }, // Dropbox-ish blue
    { mark: "N", tone: "linear-gradient(135deg,#1F1F1F 0%,#404040 100%)" }, // Notion-ish black
    { mark: "J", tone: "linear-gradient(135deg,#0052CC 0%,#2684FF 100%)" }, // Jira-ish blue
    { mark: "Z", tone: "linear-gradient(135deg,#2D8CFF 0%,#5BB7FF 100%)" }, // Zoom-ish
    { mark: "F", tone: "linear-gradient(135deg,#0866FF 0%,#1877F2 100%)" }, // Meta-ish
    { mark: "A", tone: "linear-gradient(135deg,#F06A6A 0%,#F9A77E 100%)" }, // Asana-ish
    { mark: "T", tone: "linear-gradient(135deg,#0079BF 0%,#5BA4CF 100%)" }, // Trello-ish
    { mark: "Q", tone: "linear-gradient(135deg,#FF3D57 0%,#FFB400 100%)" }, // Monday-ish
    { mark: "X", tone: "linear-gradient(135deg,#1DA1F2 0%,#74C0FC 100%)" }, // X-ish
  ];

  /* ---------- arc geometry — app positions stay on one shared orbit --------
     Centre apps are closest and sharpest. Edges sit further down the same
     semicircle and naturally fade/blur back into the ecosystem. */
  const layoutTile = (i, total) => {
    const t = (i - (total - 1) / 2) / ((total - 1) / 2); // -1..1
    const absT = Math.abs(t);
    const angle = t * FLOW.maxAngle;
    const x = Math.sin(angle) * FLOW.radius;
    const y = (1 - Math.cos(angle)) * FLOW.radius * FLOW.ySquash;
    const scale = 1 - absT * 0.62;
    const z = Math.round(100 - absT * 80);
    return {
      x,
      y,
      cx: FLOW.centerX + x,
      cy: FLOW.orbitTopY + y,
      scale,
      z,
      absT,
    };
  };

  const layoutCompactTile = (index) => {
    const positions = [
      { cx: 160, cy: 96, scale: 0.76 },
      { cx: 400, cy: 96, scale: 0.80 },
      { cx: 640, cy: 96, scale: 0.84 },
      { cx: 880, cy: 96, scale: 0.80 },
      { cx: 1120, cy: 96, scale: 0.76 },
      { cx: 280, cy: 226, scale: 0.76 },
      { cx: 520, cy: 226, scale: 0.76 },
      { cx: 760, cy: 226, scale: 0.76 },
      { cx: 1000, cy: 226, scale: 0.76 },
    ];
    const p = positions[index] || positions[positions.length - 1];
    const absT = Math.min(1, Math.abs(p.cx - FLOW.centerX) / 560);
    return {
      cx: p.cx,
      cy: p.cy,
      scale: p.scale,
      z: Math.round(120 - absT * 24),
      absT,
    };
  };

  const orbitFlowPath = (item) => {
    const halfSize = item.ghost ? 40 : 48;
    const startY = item.cy + halfSize * item.scale + 8;
    const side = item.cx - FLOW.centerX;
    const pull = 0.34 + item.absT * 0.08;
    const c1Y = startY + 64 + item.absT * 34;
    const c2X = FLOW.centerX + side * pull;
    const c2Y = FLOW.mergeY - 50 - item.absT * 16;
    return [
      `M ${item.cx.toFixed(1)} ${startY.toFixed(1)}`,
      `C ${item.cx.toFixed(1)} ${c1Y.toFixed(1)}`,
      `${c2X.toFixed(1)} ${c2Y.toFixed(1)}`,
      `${FLOW.centerX} ${FLOW.mergeY}`,
    ].join(" ");
  };

  const compactFlowPath = (item) => {
    const startY = item.cy + 48 * item.scale + 8;
    const side = item.cx - FLOW.centerX;
    const isLowerRow = item.cy > 150;
    const mergeY = FLOW.mergeY + 2;
    if (Math.abs(side) < 1) {
      return `M ${item.cx.toFixed(1)} ${startY.toFixed(1)} V ${mergeY.toFixed(1)}`;
    }
    const dir = Math.sign(side);
    const hubX = FLOW.centerX + dir * 120;
    const hubY = FLOW.mergeY - 10;
    const stemY = isLowerRow
      ? Math.min(hubY - 6, startY + 26)
      : FLOW.mergeY - 76 - item.absT * 8;
    const pullSpan = Math.min(isLowerRow ? 72 : 96, Math.abs(item.cx - hubX) * (isLowerRow ? 0.55 : 0.80));
    const pullX = hubX + dir * pullSpan;
    return [
      `M ${item.cx.toFixed(1)} ${startY.toFixed(1)}`,
      `V ${stemY.toFixed(1)}`,
      `C ${item.cx.toFixed(1)} ${(stemY + (isLowerRow ? 10 : 56)).toFixed(1)}`,
      `${pullX.toFixed(1)} ${hubY.toFixed(1)}`,
      `${hubX.toFixed(1)} ${hubY.toFixed(1)}`,
      `C ${(FLOW.centerX + dir * 78).toFixed(1)} ${hubY.toFixed(1)}`,
      `${(FLOW.centerX + dir * 34).toFixed(1)} ${(mergeY - 5).toFixed(1)}`,
      `${FLOW.centerX} ${mergeY.toFixed(1)}`,
    ].join(" ");
  };

  const WisAICore = ({ label, progress = 1, className = "", style = {} }) => (
    <div
      className={`lp-wisai-core ${className}`}
      aria-label={label}
      style={{ ...style, "--flow-progress": progress }}
    >
      <img className="lp-wisai-core-logo" src="assets/wisbid-icon.png" alt="" />
    </div>
  );

  const FlowLines = ({ items, progress, compact = false }) => {
    const branchBase = clamp01(progress / 0.68);
    const trunkProgress = clamp01((progress - 0.50) / 0.38);
    const connected = items.filter((item) => !item.ghost).sort((a, b) => a.absT - b.absT);
    const trunkStartY = compact ? FLOW.mergeY - 2 : FLOW.mergeY;
    const trunkPath = `M ${FLOW.centerX} ${trunkStartY} C ${FLOW.centerX} ${FLOW.mergeY + 54} ${FLOW.centerX} ${FLOW.coreY - 86} ${FLOW.centerX} ${FLOW.coreY - 56}`;
    return (
      <svg className="lp-halo-flow" viewBox={`0 0 ${FLOW.width} ${FLOW.height}`} preserveAspectRatio="none" aria-hidden="true">
        {connected.map((item) => {
          const fade = compact ? 1 : Math.max(0.16, 1 - item.absT * 1.55);
          const draw = clamp01((branchBase - item.absT * 0.08) / (1 - item.absT * 0.08));
          return (
            <path
              key={`${item.name}-flow`}
              className="lp-halo-orbit-line"
              d={compact ? compactFlowPath(item) : orbitFlowPath(item)}
              pathLength="1"
              style={{
                opacity: fade * draw,
                strokeDashoffset: 1 - draw,
                strokeWidth: `${(compact ? 1.45 : 1.85 - item.absT * 0.65).toFixed(2)}px`,
              }}
            />
          );
        })}
        <path
          className="lp-halo-trunk-line"
          d={trunkPath}
          pathLength="1"
          style={{ strokeDashoffset: 1 - trunkProgress, opacity: trunkProgress }}
        />
        {!compact && connected.map((item) => (
          <circle
            key={`${item.name}-port`}
            className="lp-halo-flow-port"
            cx={item.cx}
            cy={item.cy + 48 * item.scale + 8}
            r={Math.max(1.4, 2.5 - item.absT * 1.6)}
            style={{ opacity: Math.max(0.10, 1 - item.absT * 1.7) * branchBase }}
          />
        ))}
      </svg>
    );
  };

  const Integrations = () => {
    const t = useVxT();
    const isCompact = useCompactViewport();
    const sectionRef = useRef(null);
    const flowProgress = useFlowProgress(sectionRef);

    // Order: ghosts (left) → featured (centre) → ghosts (right).
    // 5 + 9 + 5 = 19 positions total. Center index = 9.
    const left  = GHOSTS.slice(0, 5);
    const right = GHOSTS.slice(5, 10);
    const items = [
      ...left.map((g)  => ({ ...g, ghost: true })),
      ...FEATURED.map((f) => ({ ...f, ghost: false })),
      ...right.map((g) => ({ ...g, ghost: true })),
    ];
    const N = items.length;
    const positionedItems = isCompact
      ? FEATURED.map((item, i) => ({
        ...item,
        ghost: false,
        ...layoutCompactTile(i),
      }))
      : items.map((item, i) => ({
        ...item,
        ...layoutTile(i, N),
      }));
    const coreLabel = t("int.coreAria", "WisAI, connected workspace hub for every app");

    return (
      <section className="lp-halo" id="integrations" ref={sectionRef}>
        <div className="lp-shell lp-halo-shell">
          <header className="lp-halo-header">
            <span className="lp-eyebrow"><span className="num">02</span>{t("int.eyebrow", "Connected workspace").replace(/^02/, "")}</span>
            <h2>{t("int.headline", "An Agentic Platform that operates every app your team runs on.")}</h2>
            <p>{t("int.lede", "Bring familiar apps like Gmail, Outlook, SharePoint, Calendar, Teams, Power BI, Xero and QuickBooks into one connected operating layer.")}</p>
          </header>

          <div className={`lp-halo-stage ${isCompact ? "is-compact" : ""}`} role="img" aria-label={t("int.ariaHalo", "Wisbid integrations halo")}>
            {/* Decorative arc lines — soft elliptical guides behind tiles */}
            <span className="lp-halo-arc lp-halo-arc--a" aria-hidden="true" />
            <span className="lp-halo-arc lp-halo-arc--b" aria-hidden="true" />
            <span className="lp-halo-glow" aria-hidden="true" />
            <FlowLines items={positionedItems} progress={flowProgress} compact={isCompact} />
            <WisAICore
              label={coreLabel}
              progress={flowProgress}
              style={{
                left: `${(FLOW.centerX / FLOW.width) * 100}%`,
                top: `${(FLOW.coreY / FLOW.height) * 100}%`,
              }}
            />

            {positionedItems.map((item, i) => {
              const { scale, z, absT, cx, cy } = item;
              // Ghosts: a touch softer, more blurred, more transparent at all distances
              const opacity = item.ghost
                ? Math.max(0.10, 0.42 - absT * 0.28)
                : Math.max(0.88, 1 - absT * 0.12);
              const blur = item.ghost
                ? 3.5 + absT * 7.0
                : 0;
              return (
                <div
                  key={i}
                  className={`lp-halo-tile ${item.ghost ? "is-ghost" : "is-featured"}`}
                  style={{
                    left: `${(cx / FLOW.width) * 100}%`,
                    top: `${(cy / FLOW.height) * 100}%`,
                    transform: `translate(-50%, -50%) scale(${scale})`,
                    opacity,
                    filter: blur > 0.4 ? `blur(${blur.toFixed(2)}px)` : undefined,
                    zIndex: z,
                    animationDelay: `${(0.06 * i).toFixed(2)}s`,
                  }}
                  title={!item.ghost ? item.name : undefined}
                  aria-label={!item.ghost ? item.name : undefined}
                >
                  {item.ghost ? (
                    <span className="lp-halo-ghost" style={{ background: item.tone }}>
                      <span>{item.mark}</span>
                    </span>
                  ) : (
                    <img src={item.src} alt={item.name} />
                  )}
                </div>
              );
            })}
          </div>
        </div>
      </section>
    );
  };

  window.Integrations = Integrations;
})();
