// particles.jsx — Three.js particle field with mouse parallax
const { useEffect: pUseEffect, useRef: pUseRef } = React;

function Particles({ intensity = 1.0 }) {
  const mountRef = pUseRef(null);

  pUseEffect(() => {
    if (!window.THREE) return;
    const THREE = window.THREE;
    const mount = mountRef.current;
    const w = mount.clientWidth, h = mount.clientHeight;

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(70, w / h, 1, 4000);
    camera.position.z = 900;
    const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(w, h);
    renderer.setClearColor(0x000000, 0);
    mount.appendChild(renderer.domElement);

    // Particle geometry — clouds of points
    const count = 2400;
    const positions = new Float32Array(count * 3);
    const colors = new Float32Array(count * 3);
    const sizes = new Float32Array(count);

    const c1 = new THREE.Color("#ff3366");
    const c2 = new THREE.Color("#ff7a3d");
    const c3 = new THREE.Color("#ffffff");

    for (let i = 0; i < count; i++) {
      // Distribute in a 3D wedge biased toward center plane
      const r = Math.pow(Math.random(), 0.7) * 1100;
      const theta = Math.random() * Math.PI * 2;
      const phi = (Math.random() - 0.5) * Math.PI * 0.6;
      positions[i * 3]     = Math.cos(theta) * Math.cos(phi) * r;
      positions[i * 3 + 1] = Math.sin(phi) * r * 0.8;
      positions[i * 3 + 2] = Math.sin(theta) * Math.cos(phi) * r;

      const mix = Math.random();
      const col = mix < 0.55 ? c3 : (mix < 0.85 ? c1 : c2);
      colors[i * 3]     = col.r;
      colors[i * 3 + 1] = col.g;
      colors[i * 3 + 2] = col.b;

      sizes[i] = Math.random() * 2.4 + 0.6;
    }

    const geom = new THREE.BufferGeometry();
    geom.setAttribute("position", new THREE.BufferAttribute(positions, 3));
    geom.setAttribute("color", new THREE.BufferAttribute(colors, 3));
    geom.setAttribute("size", new THREE.BufferAttribute(sizes, 1));

    // Shader for round, glowing points
    const material = new THREE.ShaderMaterial({
      uniforms: { uTime: { value: 0 }, uPixelRatio: { value: renderer.getPixelRatio() } },
      vertexShader: `
        attribute float size;
        varying vec3 vColor;
        uniform float uTime;
        uniform float uPixelRatio;
        void main() {
          vColor = color;
          vec3 p = position;
          p.x += sin(uTime * 0.4 + position.y * 0.002) * 12.0;
          p.y += cos(uTime * 0.3 + position.x * 0.002) * 10.0;
          vec4 mvPosition = modelViewMatrix * vec4(p, 1.0);
          gl_PointSize = size * uPixelRatio * (300.0 / -mvPosition.z);
          gl_Position = projectionMatrix * mvPosition;
        }
      `,
      fragmentShader: `
        varying vec3 vColor;
        void main() {
          float d = distance(gl_PointCoord, vec2(0.5));
          if (d > 0.5) discard;
          float a = smoothstep(0.5, 0.0, d);
          gl_FragColor = vec4(vColor, a * 0.95);
        }
      `,
      vertexColors: true,
      transparent: true,
      depthWrite: false,
      blending: THREE.AdditiveBlending
    });

    const points = new THREE.Points(geom, material);
    scene.add(points);

    // Subtle wireframe rings for depth cue
    const ringGeo = new THREE.RingGeometry(420, 422, 96);
    const ringMat = new THREE.MeshBasicMaterial({ color: 0xff3366, side: THREE.DoubleSide, transparent: true, opacity: 0.18 });
    const ring1 = new THREE.Mesh(ringGeo, ringMat);
    ring1.rotation.x = Math.PI / 2.3;
    const ring2 = new THREE.Mesh(ringGeo, ringMat.clone());
    ring2.material.opacity = 0.1;
    ring2.rotation.x = Math.PI / 1.9; ring2.rotation.z = 0.3;
    scene.add(ring1); scene.add(ring2);

    // Pointer-driven parallax
    const mouse = { x: 0, y: 0, tx: 0, ty: 0 };
    const onMove = (e) => {
      const r = mount.getBoundingClientRect();
      mouse.tx = ((e.clientX - r.left) / r.width - 0.5) * 2;
      mouse.ty = ((e.clientY - r.top) / r.height - 0.5) * 2;
    };
    window.addEventListener("mousemove", onMove);

    let raf, t0 = performance.now();
    const tick = () => {
      const t = (performance.now() - t0) / 1000;
      material.uniforms.uTime.value = t;
      mouse.x += (mouse.tx - mouse.x) * 0.045;
      mouse.y += (mouse.ty - mouse.y) * 0.045;
      points.rotation.y = t * 0.04 + mouse.x * 0.4;
      points.rotation.x = mouse.y * 0.25;
      ring1.rotation.z += 0.0015;
      ring2.rotation.z -= 0.001;
      camera.position.x = mouse.x * 80;
      camera.position.y = -mouse.y * 60;
      camera.lookAt(0, 0, 0);
      renderer.render(scene, camera);
      raf = requestAnimationFrame(tick);
    };
    tick();

    const onResize = () => {
      const w = mount.clientWidth, h = mount.clientHeight;
      renderer.setSize(w, h);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    };
    window.addEventListener("resize", onResize);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("resize", onResize);
      renderer.dispose();
      geom.dispose();
      material.dispose();
      if (mount.contains(renderer.domElement)) mount.removeChild(renderer.domElement);
    };
  }, []);

  return <div ref={mountRef} className="hero__canvas"></div>;
}

window.Particles = Particles;
