// 3D Hero Scene — Three.js wireframe core with mouse-driven parallax + particle field.
// Mounted into a <div ref={mountRef}/> inside the Hero React component.

function Hero3D({ accent = "#ff1a1a" }) {
  const mountRef = React.useRef(null);
  const stateRef = React.useRef({});

  React.useEffect(() => {
    if (!window.THREE) return;
    const THREE = window.THREE;
    const mount = mountRef.current;
    if (!mount) return;

    const W = () => mount.clientWidth;
    const H = () => mount.clientHeight;

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(45, W()/H(), 0.1, 100);
    camera.position.set(0, 0, 6);

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(W(), H());
    renderer.setClearColor(0x000000, 0);
    mount.appendChild(renderer.domElement);
    renderer.domElement.style.display = "block";
    renderer.domElement.style.width = "100%";
    renderer.domElement.style.height = "100%";

    const accentColor = new THREE.Color(accent);
    const whiteColor = new THREE.Color(0xffffff);

    // ---- Group root for parallax tilt
    const root = new THREE.Group();
    scene.add(root);

    // ---- Inner glowing core (sphere)
    const coreGeo = new THREE.SphereGeometry(0.85, 64, 64);
    const coreMat = new THREE.MeshBasicMaterial({ color: accentColor });
    const core = new THREE.Mesh(coreGeo, coreMat);
    root.add(core);

    // soft inner halo (additive sprite-ish layer using a large transparent sphere)
    const haloGeo = new THREE.SphereGeometry(1.05, 48, 48);
    const haloMat = new THREE.MeshBasicMaterial({
      color: accentColor, transparent: true, opacity: 0.18,
      blending: THREE.AdditiveBlending, depthWrite: false,
    });
    const halo = new THREE.Mesh(haloGeo, haloMat);
    root.add(halo);

    const halo2Mat = new THREE.MeshBasicMaterial({
      color: accentColor, transparent: true, opacity: 0.08,
      blending: THREE.AdditiveBlending, depthWrite: false,
    });
    const halo2 = new THREE.Mesh(new THREE.SphereGeometry(1.5, 32, 32), halo2Mat);
    root.add(halo2);

    // ---- Outer wireframe icosahedron (subdivided)
    const icoGeo = new THREE.IcosahedronGeometry(1.8, 2);
    const icoEdges = new THREE.EdgesGeometry(icoGeo);
    const icoMat = new THREE.LineBasicMaterial({
      color: accentColor, transparent: true, opacity: 0.7,
    });
    const ico = new THREE.LineSegments(icoEdges, icoMat);
    root.add(ico);

    // a second, slightly larger, dimmer icosa for layered feel
    const icoGeo2 = new THREE.IcosahedronGeometry(2.4, 1);
    const icoEdges2 = new THREE.EdgesGeometry(icoGeo2);
    const icoMat2 = new THREE.LineBasicMaterial({
      color: whiteColor, transparent: true, opacity: 0.15,
    });
    const ico2 = new THREE.LineSegments(icoEdges2, icoMat2);
    root.add(ico2);

    // ---- Orbital ring (torus)
    const ringGeo = new THREE.TorusGeometry(2.6, 0.005, 8, 200);
    const ringMat = new THREE.MeshBasicMaterial({
      color: accentColor, transparent: true, opacity: 0.5,
    });
    const ring = new THREE.Mesh(ringGeo, ringMat);
    ring.rotation.x = Math.PI / 2.6;
    root.add(ring);

    const ring2 = new THREE.Mesh(
      new THREE.TorusGeometry(3.1, 0.003, 8, 200),
      new THREE.MeshBasicMaterial({ color: whiteColor, transparent: true, opacity: 0.18 })
    );
    ring2.rotation.x = Math.PI / 1.8;
    ring2.rotation.y = Math.PI / 4;
    root.add(ring2);

    // ---- Particles
    const pCount = 600;
    const pGeo = new THREE.BufferGeometry();
    const positions = new Float32Array(pCount * 3);
    const speeds = new Float32Array(pCount);
    for (let i = 0; i < pCount; i++) {
      const r = 3 + Math.random() * 5;
      const theta = Math.random() * Math.PI * 2;
      const phi = Math.acos(2 * Math.random() - 1);
      positions[i*3]   = r * Math.sin(phi) * Math.cos(theta);
      positions[i*3+1] = r * Math.sin(phi) * Math.sin(theta);
      positions[i*3+2] = r * Math.cos(phi);
      speeds[i] = 0.0005 + Math.random() * 0.002;
    }
    pGeo.setAttribute("position", new THREE.BufferAttribute(positions, 3));
    const pMat = new THREE.PointsMaterial({
      color: whiteColor, size: 0.025, transparent: true, opacity: 0.7,
      blending: THREE.AdditiveBlending, depthWrite: false,
    });
    const particles = new THREE.Points(pGeo, pMat);
    scene.add(particles);

    // a small group of accent-colored bright particles
    const pCount2 = 60;
    const pGeo2 = new THREE.BufferGeometry();
    const positions2 = new Float32Array(pCount2 * 3);
    for (let i = 0; i < pCount2; i++) {
      const r = 2.2 + Math.random() * 1.8;
      const theta = Math.random() * Math.PI * 2;
      const phi = Math.acos(2 * Math.random() - 1);
      positions2[i*3]   = r * Math.sin(phi) * Math.cos(theta);
      positions2[i*3+1] = r * Math.sin(phi) * Math.sin(theta);
      positions2[i*3+2] = r * Math.cos(phi);
    }
    pGeo2.setAttribute("position", new THREE.BufferAttribute(positions2, 3));
    const pMat2 = new THREE.PointsMaterial({
      color: accentColor, size: 0.06, transparent: true, opacity: 0.9,
      blending: THREE.AdditiveBlending, depthWrite: false,
    });
    const particles2 = new THREE.Points(pGeo2, pMat2);
    scene.add(particles2);

    // ---- Mouse parallax
    let targetX = 0, targetY = 0, curX = 0, curY = 0;
    const onMove = (e) => {
      const rect = mount.getBoundingClientRect();
      const nx = ((e.clientX - rect.left) / rect.width) * 2 - 1;
      const ny = ((e.clientY - rect.top)  / rect.height) * 2 - 1;
      targetX = nx;
      targetY = ny;
    };
    window.addEventListener("pointermove", onMove);

    // ---- Resize
    const onResize = () => {
      camera.aspect = W()/H();
      camera.updateProjectionMatrix();
      renderer.setSize(W(), H());
    };
    const ro = new ResizeObserver(onResize);
    ro.observe(mount);

    // ---- Animation loop
    let raf;
    const clock = new THREE.Clock();
    let alive = true;
    const tick = () => {
      if (!alive) return;
      raf = requestAnimationFrame(tick);
      const t = clock.getElapsedTime();
      const dt = clock.getDelta();

      // smooth mouse follow
      curX += (targetX - curX) * 0.06;
      curY += (targetY - curY) * 0.06;

      // root tilt based on mouse
      root.rotation.y = curX * 0.5 + t * 0.08;
      root.rotation.x = -curY * 0.4 + Math.sin(t * 0.3) * 0.05;

      // counter-rotate inner geometry slightly
      ico.rotation.y -= 0.002;
      ico.rotation.x += 0.001;
      ico2.rotation.y += 0.0015;
      ico2.rotation.z -= 0.001;

      // core pulse
      const pulse = 1 + Math.sin(t * 1.4) * 0.04;
      core.scale.setScalar(pulse);
      halo.scale.setScalar(1 + Math.sin(t * 1.4) * 0.06);
      halo2.scale.setScalar(1 + Math.sin(t * 0.9 + 1) * 0.08);

      // particles orbit
      particles.rotation.y += 0.0008;
      particles.rotation.x += 0.0003;
      particles2.rotation.y -= 0.0014;
      particles2.rotation.z += 0.0006;

      // camera subtle parallax
      camera.position.x = curX * 0.3;
      camera.position.y = -curY * 0.2;
      camera.lookAt(0, 0, 0);

      renderer.render(scene, camera);
    };
    tick();

    // ---- Accent color update hook
    stateRef.current = {
      setAccent: (c) => {
        const col = new THREE.Color(c);
        coreMat.color = col;
        haloMat.color = col;
        halo2Mat.color = col;
        icoMat.color = col;
        ringMat.color = col;
        pMat2.color = col;
      },
    };

    // ---- Cleanup
    return () => {
      alive = false;
      cancelAnimationFrame(raf);
      window.removeEventListener("pointermove", onMove);
      ro.disconnect();
      renderer.dispose();
      mount.removeChild(renderer.domElement);
      [coreGeo, haloGeo, icoGeo, icoEdges, icoGeo2, icoEdges2, ringGeo, pGeo, pGeo2].forEach(g => g.dispose());
      [coreMat, haloMat, halo2Mat, icoMat, icoMat2, ringMat, pMat, pMat2].forEach(m => m.dispose());
    };
  }, []);

  // Live accent updates
  React.useEffect(() => {
    if (stateRef.current.setAccent) stateRef.current.setAccent(accent);
  }, [accent]);

  return (
    <div className="hero-3d-mount" ref={mountRef}>
      <span className="corner-bracket cb-tl" />
      <span className="corner-bracket cb-tr" />
      <span className="corner-bracket cb-bl" />
      <span className="corner-bracket cb-br" />
      <div className="hero-readout">
        <span className="live">SYSTEM ONLINE</span>
        <span style={{margin: "0 10px"}}>·</span>
        <span>DREAMIT CORE v3.2.1</span>
        <span style={{margin: "0 10px"}}>·</span>
        <span>NODES: 2,481</span>
      </div>
    </div>
  );
}

window.Hero3D = Hero3D;
