/* DottedSurface — Three.js animated wave of dots, scoped to its container */
const { useEffect: useEffectDS, useRef: useRefDS } = React;

function DottedSurface({ className = '', style = {}, dark = false, density = 1 }) {
  const containerRef = useRefDS(null);

  useEffectDS(() => {
    const container = containerRef.current;
    if (!container || !window.THREE) return;
    const THREE = window.THREE;

    const SEPARATION = 150;
    const AMOUNTX = Math.round(40 * density);
    const AMOUNTY = Math.round(60 * density);

    // Initial size from container
    const getSize = () => ({
      w: container.clientWidth || window.innerWidth,
      h: container.clientHeight || 600
    });
    let { w, h } = getSize();

    const scene = new THREE.Scene();
    scene.fog = new THREE.Fog(0xffffff, 2000, 10000);

    const camera = new THREE.PerspectiveCamera(60, w / h, 1, 10000);
    camera.position.set(0, 355, 1220);

    const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(w, h);
    renderer.setClearColor(0xffffff, 0);
    renderer.domElement.style.display = 'block';
    container.appendChild(renderer.domElement);

    // Particles
    const positions = [];
    const colors = [];
    const geometry = new THREE.BufferGeometry();

    for (let ix = 0; ix < AMOUNTX; ix++) {
      for (let iy = 0; iy < AMOUNTY; iy++) {
        const x = ix * SEPARATION - (AMOUNTX * SEPARATION) / 2;
        const y = 0;
        const z = iy * SEPARATION - (AMOUNTY * SEPARATION) / 2;
        positions.push(x, y, z);
        if (dark) {
          colors.push(0.78, 0.88, 0.90); // soft cyan-white
        } else {
          colors.push(0.04, 0.06, 0.10); // near-ink dark
        }
      }
    }

    geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

    const material = new THREE.PointsMaterial({
      size: 7,
      vertexColors: true,
      transparent: true,
      opacity: dark ? 0.65 : 0.55,
      sizeAttenuation: true
    });

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

    let count = 0;
    let rafId = 0;
    let stopped = false;

    const animate = () => {
      if (stopped) return;
      rafId = requestAnimationFrame(animate);

      const posAttr = geometry.attributes.position;
      const pos = posAttr.array;

      let i = 0;
      for (let ix = 0; ix < AMOUNTX; ix++) {
        for (let iy = 0; iy < AMOUNTY; iy++) {
          const idx = i * 3;
          pos[idx + 1] =
            Math.sin((ix + count) * 0.3) * 50 +
            Math.sin((iy + count) * 0.5) * 50;
          i++;
        }
      }
      posAttr.needsUpdate = true;

      renderer.render(scene, camera);
      count += 0.08;
    };

    const handleResize = () => {
      const sz = getSize();
      w = sz.w; h = sz.h;
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
      renderer.setSize(w, h);
    };

    let ro;
    if (window.ResizeObserver) {
      ro = new ResizeObserver(handleResize);
      ro.observe(container);
    } else {
      window.addEventListener('resize', handleResize);
    }

    animate();

    return () => {
      stopped = true;
      cancelAnimationFrame(rafId);
      if (ro) ro.disconnect();
      else window.removeEventListener('resize', handleResize);

      scene.traverse(obj => {
        if (obj.isPoints) {
          obj.geometry.dispose();
          if (Array.isArray(obj.material)) obj.material.forEach(m => m.dispose());
          else obj.material.dispose();
        }
      });
      renderer.dispose();
      if (renderer.domElement && container.contains(renderer.domElement)) {
        container.removeChild(renderer.domElement);
      }
    };
  }, [dark, density]);

  return (
    <div
      ref={containerRef}
      className={`dotted-surface ${className}`}
      style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        overflow: 'hidden',
        ...style
      }}
      aria-hidden="true"
    />
  );
}

window.DottedSurface = DottedSurface;
