/* NEXABOT — React wrapper: mounts the Three.js module scene, or falls back to 2D canvas */

function s3dInitialFallback() {
  try {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return true;
    if (document.body.classList.contains("no-anim")) return true;
    if (window.matchMedia("(pointer: coarse)").matches && window.innerWidth < 820) return true;
    const c = document.createElement("canvas");
    const gl = c.getContext("webgl") || c.getContext("experimental-webgl");
    if (!gl) return true;
  } catch (e) { return true; }
  return false;
}

/* File de montage : une scène WebGL par frame, pour ne jamais geler le compteur du loader */
let s3dQueue = Promise.resolve();
function s3dEnqueue(fn) {
  s3dQueue = s3dQueue
    .then(() => new Promise((next) => requestAnimationFrame(() => { fn(); next(); })))
    .catch(() => {});
}

function Scene3D({ variant = "hero", scene = "network", className = "" }) {
  const ref = React.useRef(null);
  const [fb, setFb] = React.useState(s3dInitialFallback);
  // seul le hero doit être prêt pendant le boot (il est la cible du warp) ;
  // manifesto (terrain) et portfolio sont hors écran → montage après le warp
  const deferred = scene === "terrain" || variant === "portfolio";

  React.useEffect(() => {
    if (fb) return;
    let cleanup = () => {};
    let cancelled = false;
    let started = false;
    let tries = 0;
    let timer, deferTimer, safetyTimer;
    let offBoot = () => {};
    const tryMount = () => {
      if (cancelled || started) return;
      if (window.NexaScene3D && ref.current) {
        started = true;
        s3dEnqueue(() => {
          if (cancelled || !ref.current) return;
          const cv = ref.current;
          try { cleanup = window.NexaScene3D.mount(cv, { variant, scene }) || (() => {}); }
          catch (e) { console.warn("Scene3D mount failed", e); setFb(true); return; }
          requestAnimationFrame(() => cv.removeAttribute("data-s3d-pending"));
        });
        return;
      }
      if (tries++ > 80) { setFb(true); return; }
      timer = setTimeout(tryMount, 50);
    };
    if (!deferred) {
      tryMount();
    } else {
      const stagger = variant === "portfolio" ? 1400 : 900;
      const arm = () => { deferTimer = setTimeout(tryMount, stagger); };
      if (window.__nexaBooted) arm();
      else {
        const onBoot = () => { offBoot(); arm(); };
        window.addEventListener("nexa-boot-done", onBoot);
        offBoot = () => window.removeEventListener("nexa-boot-done", onBoot);
        safetyTimer = setTimeout(tryMount, 9000); // ceinture : montage garanti
      }
    }
    return () => {
      cancelled = true; offBoot();
      clearTimeout(timer); clearTimeout(deferTimer); clearTimeout(safetyTimer);
      cleanup();
    };
  }, [fb, variant]);

  if (fb) return React.createElement(window.Backdrop, { scene: "flow", intensity: 1, className });
  return <canvas ref={ref} className={className} data-s3d-pending={deferred ? "" : undefined} />;
}

window.Scene3D = Scene3D;
