// SPACEWALKER v3 — sticky scroll stage (hero + cards + tubes)
const { useEffect, useRef, useState } = React;

const CARDS = [
  // top arc
  { x: 12, y: 22, icon: "code" },
  { x: 34, y: 14, icon: "shield" },
  { x: 66, y: 14, icon: "ai" },
  { x: 88, y: 22, icon: "rocket" },
  // bottom arc
  { x: 12, y: 76, icon: "trade" },
  { x: 34, y: 84, icon: "phone" },
  { x: 66, y: 84, icon: "pentest" },
  { x: 88, y: 76, icon: "bolt" },
];

const clamp = (v, a, b) => Math.min(b, Math.max(a, v));
const lerp = (a, b, t) => a + (b - a) * t;
const easeOutCubic = t => 1 - Math.pow(1 - t, 3);
const easeOutBack = (t, s = 1.4) => 1 + (s + 1) * Math.pow(t - 1, 3) + s * Math.pow(t - 1, 2);

function Stage() {
  const wrapRef = useRef(null);
  const canvasRef = useRef(null);
  const tubeRef = useRef(null);
  const cardsRef = useRef([]);
  const heroRef = useRef(null);
  const phaseRef = useRef(null);

  const [phase, setPhase] = useState(1);
  const [taglineIdx, setTaglineIdx] = useState(0);
  const fullTag = "Build. Secure. Ship.";

  // typewriter
  useEffect(() => {
    let i = 0;
    const id = setInterval(() => {
      i++;
      setTaglineIdx(i);
      if (i >= fullTag.length) clearInterval(id);
    }, 80);
    return () => clearInterval(id);
  }, []);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || !window.THREE) return;
    const THREE = window.THREE;

    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    const W = () => canvas.clientWidth, H = () => canvas.clientHeight;
    renderer.setSize(W(), H(), false);
    renderer.setClearColor(0x000000, 0);

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(45, W()/H(), 0.1, 5000);
    camera.position.set(0, 18, 88);
    camera.lookAt(0, -4, 0);

    // Lights
    scene.add(new THREE.AmbientLight(0x18305f, 0.6));
    const rim = new THREE.PointLight(0x2060E0, 6, 220);
    rim.position.set(0, 0, 10);
    scene.add(rim);

    // Confetti particles
    const N = 420;
    const pGeom = new THREE.BufferGeometry();
    const pos = new Float32Array(N * 3);
    const sizes = new Float32Array(N);
    const cols = new Float32Array(N * 3);
    const seeds = new Float32Array(N);
    const cBlue = new THREE.Color(0x4488FF);
    const cMist = new THREE.Color(0x7AAAFF);
    const cPurp = new THREE.Color(0x6644CC);
    for (let i = 0; i < N; i++) {
      pos[i*3]     = (Math.random() - 0.5) * 320;
      pos[i*3 + 1] = (Math.random() - 0.5) * 180;
      pos[i*3 + 2] = (Math.random() - 0.5) * 500 - 60;
      sizes[i] = Math.random() * 2.4 + 0.6;
      const r = Math.random();
      const c = r < 0.55 ? cBlue : r < 0.85 ? cMist : cPurp;
      cols[i*3] = c.r; cols[i*3+1] = c.g; cols[i*3+2] = c.b;
      seeds[i] = Math.random();
    }
    pGeom.setAttribute("position", new THREE.BufferAttribute(pos, 3));
    pGeom.setAttribute("size", new THREE.BufferAttribute(sizes, 1));
    pGeom.setAttribute("color", new THREE.BufferAttribute(cols, 3));
    pGeom.setAttribute("seed", new THREE.BufferAttribute(seeds, 1));

    const pMat = new THREE.ShaderMaterial({
      uniforms: { time: { value: 0 }, spread: { value: 0 } },
      vertexShader: `
        attribute float size; attribute vec3 color; attribute float seed;
        varying vec3 vColor; varying float vSeed;
        uniform float time; uniform float spread;
        void main() {
          vColor = color; vSeed = seed;
          vec3 p = position;
          p.y += sin(time * 0.4 + seed * 9.0) * 2.6;
          p.x += cos(time * 0.3 + seed * 7.0) * 1.6;
          vec3 dir = normalize(p + vec3(0.001));
          p += dir * spread * (40.0 + seed * 60.0);
          vec4 mv = modelViewMatrix * vec4(p, 1.0);
          gl_Position = projectionMatrix * mv;
          gl_PointSize = size * (260.0 / -mv.z);
        }`,
      fragmentShader: `
        varying vec3 vColor; varying float vSeed;
        void main() {
          vec2 c = gl_PointCoord - 0.5;
          float a;
          if (vSeed > 0.55) {
            float m = max(abs(c.x), abs(c.y));
            a = step(m, 0.42);
          } else {
            a = smoothstep(0.5, 0.25, length(c));
          }
          if (a < 0.05) discard;
          gl_FragColor = vec4(vColor, a * 0.9);
        }`,
      transparent: true,
      blending: THREE.AdditiveBlending,
      depthWrite: false,
    });
    const particles = new THREE.Points(pGeom, pMat);
    scene.add(particles);

    // Resize
    const onResize = () => {
      renderer.setSize(W(), H(), false);
      camera.aspect = W() / H();
      camera.updateProjectionMatrix();
    };
    window.addEventListener("resize", onResize);

    const computeProgress = () => {
      const wrap = wrapRef.current;
      if (!wrap) return 0;
      const rect = wrap.getBoundingClientRect();
      const total = wrap.offsetHeight - window.innerHeight;
      if (total <= 0) return 0;
      const scrolled = -rect.top;
      return clamp(scrolled / total, 0, 1);
    };

    let t = 0, rafId;

    const update = () => {
      t += 0.016;
      const progress = computeProgress();

      // Phases:
      // 1 — logo arrival (0..0.20)
      // 2 — services cards (0.20..0.45)
      // 3 — tube connectors (0.45..0.72)
      // 4 — release / next section (0.78..1)
      const p1 = clamp(progress / 0.20, 0, 1);
      const p1e = easeOutCubic(p1);
      const p2 = clamp((progress - 0.20) / 0.25, 0, 1);
      const p2e = easeOutCubic(p2);
      const p3 = clamp((progress - 0.45) / 0.27, 0, 1);
      const p4 = clamp((progress - 0.78) / 0.22, 0, 1);
      const fade = 1 - p4;

      pMat.uniforms.time.value = t;
      pMat.uniforms.spread.value = p2e * 0.4 + p4 * 0.5;

      canvas.style.opacity = (0.55 + 0.45 * fade);

      // Logo
      const logoEl = document.querySelector(".stage-logo");
      if (logoEl) {
        const scale = lerp(0.05, 1, p1e) * lerp(1, 0.78, p2e);
        const blur = lerp(20, 0, p1e);
        const float = Math.sin(t * 0.9) * 5 * p2;
        const rotY = Math.sin(t * 0.4) * 3;
        logoEl.style.transform = `translate(-50%, -50%) translateY(${float}px) scale(${scale}) perspective(800px) rotateY(${rotY}deg)`;
        logoEl.style.filter = `blur(${blur}px) drop-shadow(0 0 28px rgba(68,136,255,${0.55 * p1e * fade}))`;
        logoEl.style.opacity = p1e * fade;
      }
      const haloEl = document.querySelector(".stage-logo-halo");
      const ringsEl = document.querySelector(".stage-logo-rings");
      if (haloEl) haloEl.style.opacity = p1e * fade * (0.5 + 0.5 * Math.sin(t * 2.2));
      if (ringsEl) ringsEl.style.opacity = p1e * fade;

      // Hero text (visible early, fades during phase 4) — typewriter handle only,
      // since the wordmark moved out of the stage. Keep ref no-op safe.
      const heroEl = heroRef.current;
      if (heroEl) {
        heroEl.style.opacity = 0;
      }

      // Cards
      const cardEls = cardsRef.current;
      cardEls.forEach((el, i) => {
        if (!el) return;
        const startAt = 0.20 + i * 0.022;
        const k = clamp((progress - startAt) / 0.14, 0, 1);
        const ke = easeOutBack(k);
        const dx = (CARDS[i].x - 50) * 6;
        const dy = (CARDS[i].y - 50) * 6;
        const tx = lerp(dx, 0, ke);
        const ty = lerp(dy, 0, ke);
        const rot = lerp((CARDS[i].x < 50 ? -8 : 8), 0, ke);
        const op = clamp(k * 1.5, 0, 1) * fade;
        const bobP = clamp((progress - (startAt + 0.14)) / 0.1, 0, 1);
        const bob = Math.sin(t * 1.4 + i * 0.8) * 4 * bobP;
        el.style.transform = `translate(-50%, -50%) translate(${tx}px, ${ty + bob}px) rotate(${rot}deg)`;
        el.style.opacity = op;
      });

      // Tubes
      const tubeSvg = tubeRef.current;
      if (tubeSvg && p3 > 0) {
        const wr = tubeSvg.getBoundingClientRect();
        let cx = wr.width * 0.5, cy = wr.height * 0.42;
        const lEl = document.querySelector(".stage-logo");
        if (lEl) {
          const lr = lEl.getBoundingClientRect();
          cx = lr.left + lr.width / 2 - wr.left;
          cy = lr.top + lr.height / 2 - wr.top;
        }

        cardEls.forEach((el, i) => {
          if (!el) return;
          const tubePath = tubeSvg.querySelector(`#tube-${i}`);
          const flowPath = tubeSvg.querySelector(`#flow-${i}`);
          const nodeEl = el.querySelector(".node");
          if (!tubePath) return;
          const cr = el.getBoundingClientRect();
          const ecx = cr.left + cr.width / 2 - wr.left;
          const ecy = cr.top + cr.height / 2 - wr.top;
          const dx = ecx - cx, dy = ecy - cy;
          const len = Math.hypot(dx, dy) || 1;
          const ax = ecx - (dx / len) * (cr.width / 2 - 4);
          const ay = ecy - (dy / len) * (cr.height / 2 - 4);
          const logoR = (lEl ? Math.min(lEl.clientWidth, lEl.clientHeight) * 0.42 : 60);
          const sx = cx + (dx / len) * logoR;
          const sy = cy + (dy / len) * logoR;
          const mx = (sx + ax) / 2, my = (sy + ay) / 2;
          const perpX = -dy / len, perpY = dx / len;
          const sign = (i < 4 ? -1 : 1) * (CARDS[i].x < 50 ? 1 : -1);
          const ctlX = mx + perpX * 70 * sign;
          const ctlY = my + perpY * 70 * sign;
          const d = `M ${sx} ${sy} Q ${ctlX} ${ctlY} ${ax} ${ay}`;
          tubePath.setAttribute("d", d);
          if (flowPath) flowPath.setAttribute("d", d);

          const tubeStart = 0.45 + i * 0.014;
          const tk = clamp((progress - tubeStart) / 0.18, 0, 1);
          const tke = easeOutCubic(tk);
          const totalLen = tubePath.getTotalLength();
          tubePath.style.strokeDasharray = `${totalLen}`;
          tubePath.style.strokeDashoffset = `${totalLen * (1 - tke)}`;
          tubePath.style.opacity = fade;
          if (flowPath) {
            flowPath.style.strokeDasharray = "10 16";
            flowPath.style.strokeDashoffset = `${-t * 80}`;
            flowPath.style.opacity = tke * 0.95 * fade;
          }
          if (nodeEl) {
            nodeEl.style.opacity = tke * fade;
            const lx = ax - cr.left + wr.left;
            const ly = ay - cr.top + wr.top;
            nodeEl.style.left = `${lx}px`;
            nodeEl.style.top = `${ly}px`;
            nodeEl.style.transform = `translate(-50%, -50%)`;
          }
        });
      }

      // phase pill
      let phaseN;
      if (progress < 0.20) phaseN = 1;
      else if (progress < 0.45) phaseN = 2;
      else if (progress < 0.78) phaseN = 3;
      else phaseN = 4;
      if (phaseRef.current && phaseRef.current.dataset.phase !== String(phaseN)) {
        phaseRef.current.dataset.phase = String(phaseN);
        setPhase(phaseN);
      }

      renderer.render(scene, camera);
      rafId = requestAnimationFrame(update);
    };
    update();

    return () => {
      cancelAnimationFrame(rafId);
      window.removeEventListener("resize", onResize);
      renderer.dispose();
      pGeom.dispose();
    };
  }, []);

  const phaseLabel = {
    1: "PHASE 01 // ARRIVAL",
    2: "PHASE 02 // SERVICES",
    3: "PHASE 03 // INTERCONNECT",
    4: "PHASE 04 // RELEASE",
  }[phase];

  return (
    <div className="stage-wrap" ref={wrapRef}>
      <div className="stage">
        <canvas ref={canvasRef}></canvas>

        <div className="stage-logo-halo"></div>
        <div className="stage-logo">
          <div className="stage-logo-circle">
            <img src="snake-clean.png" alt="S" draggable="false"/>
          </div>
        </div>
        <div className="stage-logo-rings">
          <span></span><span></span><span></span>
        </div>

        <svg ref={tubeRef} className="tube-layer" preserveAspectRatio="none">
          {CARDS.map((_, i) => (
            <g key={i}>
              <path id={`tube-${i}`} className="tube" d=""/>
              <path id={`flow-${i}`} className="tube-flow" d=""/>
            </g>
          ))}
        </svg>

        <div className="card-layer">
          {CARDS.map((c, i) => {
            const Glyph = ICONS[c.icon];
            const labels = (typeof window !== "undefined" && window.I18N) ? (I18N[getLang()] || I18N.en).services.cards : null;
            const meta = labels ? labels[i] : { label: "", sub: "" };
            return (
              <div
                key={i}
                ref={el => cardsRef.current[i] = el}
                className="fcard"
                style={{left: `${c.x}%`, top: `${c.y}%`, opacity: 0}}
              >
                <div className="ico">{Glyph ? <Glyph/> : null}</div>
                <div className="lbl">{meta.label}<small>{meta.sub}</small></div>
                <span className="node" style={{opacity: 0}}></span>
              </div>
            );
          })}
        </div>

        <div className="phase-pill" ref={phaseRef}>
          <span className="pill-dot"></span>
          <span>{phaseLabel}</span>
        </div>

        <div className="hud">
          <span>NODE / SW-CORE-01</span>
          <span className="hud-val">● LINK STABLE</span>
          <span>LAT 48.8566°N</span>
        </div>
        <div className="hud-r">
          <span>UPTIME 99.998%</span>
          <span className="hud-val">v4.12.0</span>
          <span>BUILD #2086-04</span>
        </div>

        <div className="scroll-hint-2">
          <span>SCROLL</span><div className="ln"></div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Stage, HeroBelow });

// ─────────── HERO BLOCK (below the sticky stage) ───────────
function HeroBelow() {
  const [tr] = useLang();
  const [idx, setIdx] = React.useState(0);
  const full = tr.hero.tag;
  React.useEffect(() => {
    setIdx(0);
    let i = 0;
    const id = setInterval(() => {
      i++; setIdx(i);
      if (i >= full.length) clearInterval(id);
    }, 70);
    return () => clearInterval(id);
  }, [full]);
  return (
    <section className="hero-below">
      <div className="hero-below-inner">
        <div className="hero-tag">
          {full.slice(0, idx)}
          <span className="caret"></span>
        </div>
        <h1 className="hero-h1">{tr.hero.h1}</h1>
        <p className="hero-lead">{tr.hero.lead}</p>
        <div className="hero-ctas">
          <a className="btn btn-primary" href="#work">{tr.hero.cta1} <span>→</span></a>
          <a className="btn btn-ghost" href="#market">{tr.hero.cta2}</a>
        </div>
      </div>
    </section>
  );
}
