/* global React, THREE */
// Dotted Surface — three.js animated grid of dots forming sine waves.
// Adapted from the shadcn/Next demo to our React-CDN setup.
// Renders into the parent container (absolute-positioned, fills parent),
// not the whole viewport. Color is driven by a CSS-style `dotColor` prop
// or, by default, the brand gold (--gold).

const { useEffect: __useEffect_ds, useRef: __useRef_ds } = React;

function DottedSurface({ className = "", dotColor, opacity = 0.55, ...props }){
  const containerRef = __useRef_ds(null);
  const sceneRef = __useRef_ds(null);

  __useEffect_ds(() => {
    const container = containerRef.current;
    if (!container || typeof THREE === "undefined") return;

    const SEPARATION = 150;
    const AMOUNTX    = 40;
    const AMOUNTY    = 60;

    // Resolve dot color (hex string -> THREE.Color)
    let resolved = dotColor;
    if (!resolved){
      const g = getComputedStyle(document.documentElement).getPropertyValue("--gold").trim();
      resolved = g || "#D4B36A";
    }
    const baseColor = new THREE.Color(resolved);

    // Renderer sized to the container
    const getSize = () => {
      const r = container.getBoundingClientRect();
      return { w: Math.max(1, r.width), h: Math.max(1, r.height) };
    };

    const scene = new THREE.Scene();

    const { w: w0, h: h0 } = getSize();
    const camera = new THREE.PerspectiveCamera(60, w0 / h0, 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(w0, h0);
    renderer.setClearColor(0x000000, 0);
    renderer.domElement.style.position = "absolute";
    renderer.domElement.style.inset = "0";
    renderer.domElement.style.width = "100%";
    renderer.domElement.style.height = "100%";
    container.appendChild(renderer.domElement);

    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);
        // Fade dots toward edges so the surface dissolves into the page
        const fx = Math.abs(ix - AMOUNTX/2) / (AMOUNTX/2);
        const fz = Math.abs(iy - AMOUNTY/2) / (AMOUNTY/2);
        const k = 1 - Math.min(1, Math.hypot(fx, fz) * 0.7);
        colors.push(baseColor.r * k, baseColor.g * k, baseColor.b * k);
      }
    }

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

    const material = new THREE.PointsMaterial({
      size: 8,
      vertexColors: true,
      transparent: true,
      opacity,
      sizeAttenuation: true,
      depthWrite: false,
    });

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

    let count = 0;
    let raf = 0;

    const animate = () => {
      raf = requestAnimationFrame(animate);
      const posAttr = geometry.attributes.position;
      const arr = posAttr.array;
      let i = 0;
      for (let ix = 0; ix < AMOUNTX; ix++){
        for (let iy = 0; iy < AMOUNTY; iy++){
          const idx = i * 3;
          arr[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 { w, h } = getSize();
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
      renderer.setSize(w, h);
    };

    const ro = new ResizeObserver(handleResize);
    ro.observe(container);

    animate();

    sceneRef.current = { scene, camera, renderer, raf, ro, geometry, material, points };

    return () => {
      cancelAnimationFrame(raf);
      ro.disconnect();
      try { container.removeChild(renderer.domElement); } catch(e) {}
      geometry.dispose();
      material.dispose();
      renderer.dispose();
    };
  }, [dotColor, opacity]);

  return (
    <div
      ref={containerRef}
      className={`dotted-surface ${className}`}
      aria-hidden="true"
      {...props}
    />
  );
}

window.DottedSurface = DottedSurface;
