// ============================================================
// SHARD 3D HERO — a faceted crystal shard with golden kintsugi
// seams, rendered in three.js. Falls back to the 2D SVG mark
// when WebGL is unavailable or motion is off.
//
// Design notes:
// - Geometry: icosahedron (detail 0) stretched vertically, with
//   deterministic per-vertex displacement so it reads as a shard,
//   not a gem-store asset.
// - Facets: dark navy physical material, flat-shaded, slight
//   clearcoat so the gold lights catch the faces as it turns.
// - Seams: EdgesGeometry rendered as gold LineSegments — the
//   kintsugi metaphor carried into 3D.
// - Motion: slow auto-rotate + mouse parallax (lerped), gentle
//   breathing scale. Everything gated behind `motion`.
// ============================================================

function ShardHero3D({ size = 420, motion = true }) {
  const theme = window.useActiveTheme();
  const mountRef = React.useRef(null);
  const [webglOk, setWebglOk] = React.useState(true);

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

    let renderer;
    try {
      renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    } catch (e) {
      setWebglOk(false);
      return;
    }

    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    renderer.setPixelRatio(dpr);
    renderer.setSize(size, size);
    renderer.outputEncoding = THREE.sRGBEncoding;
    mount.appendChild(renderer.domElement);

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(38, 1, 0.1, 50);
    // Pulled back so the elongated shard + drift + breathing never clip the
    // frame as it rotates. Visible half-height ~2.6 vs shard half-extent ~2.0.
    camera.position.set(0, 0, 7.6);

    // --- Geometry: stretched icosahedron with deterministic jitter ---
    const geo = new THREE.IcosahedronGeometry(1.35, 0);
    geo.scale(0.92, 1.45, 0.92);
    {
      // Seeded displacement: same shard every load.
      const pos = geo.attributes.position;
      const seeded = (i) => {
        const x = Math.sin(i * 127.1 + 311.7) * 43758.5453;
        return x - Math.floor(x); // 0..1
      };
      for (let i = 0; i < pos.count; i++) {
        const k = 0.88 + seeded(i) * 0.26;
        pos.setXYZ(i, pos.getX(i) * k, pos.getY(i) * k, pos.getZ(i) * k);
      }
      geo.computeVertexNormals();
    }

    const accent = new THREE.Color(theme.accent);
    const facetColor = new THREE.Color(theme.dark ? "#101a36" : "#e8dcba");

    const facetMat = new THREE.MeshPhysicalMaterial({
      color: facetColor,
      metalness: 0.35,
      roughness: 0.38,
      clearcoat: 0.6,
      clearcoatRoughness: 0.35,
      flatShading: true,
      transparent: true,
      opacity: 0.96,
    });
    const shard = new THREE.Mesh(geo, facetMat);

    // --- Gold seams along every facet boundary ---
    const edges = new THREE.EdgesGeometry(geo, 1);
    const seamMat = new THREE.LineBasicMaterial({
      color: accent,
      transparent: true,
      opacity: 0.9,
    });
    const seams = new THREE.LineSegments(edges, seamMat);
    seams.scale.setScalar(1.002);
    shard.add(seams);

    // --- Vertex nodes: small gold points at facet junctions ---
    const nodeGeo = new THREE.BufferGeometry();
    nodeGeo.setAttribute("position", geo.attributes.position.clone());
    const nodeMat = new THREE.PointsMaterial({
      color: accent,
      size: 0.055,
      transparent: true,
      opacity: 0.95,
      sizeAttenuation: true,
    });
    const nodes = new THREE.Points(nodeGeo, nodeMat);
    nodes.scale.setScalar(1.004);
    shard.add(nodes);

    const group = new THREE.Group();
    group.add(shard);
    scene.add(group);

    // --- Ambient gold dust drifting around the shard ---
    const DUST = 90;
    const dustPos = new Float32Array(DUST * 3);
    const dustSeed = [];
    for (let i = 0; i < DUST; i++) {
      const r = 2.2 + (i % 9) * 0.22;
      const a = (i / DUST) * Math.PI * 2 * 7.3;
      const y = ((i * 37) % 100) / 100 * 4.4 - 2.2;
      dustPos[i * 3] = Math.cos(a) * r;
      dustPos[i * 3 + 1] = y;
      dustPos[i * 3 + 2] = Math.sin(a) * r;
      dustSeed.push(a);
    }
    const dustGeo = new THREE.BufferGeometry();
    dustGeo.setAttribute("position", new THREE.BufferAttribute(dustPos, 3));
    const dustMat = new THREE.PointsMaterial({
      color: accent,
      size: 0.03,
      transparent: true,
      opacity: 0.55,
      sizeAttenuation: true,
    });
    const dust = new THREE.Points(dustGeo, dustMat);
    scene.add(dust);

    // --- Lighting: dim ambient, warm gold key, cool rim ---
    scene.add(new THREE.AmbientLight(0xffffff, theme.dark ? 0.25 : 0.55));
    const key = new THREE.PointLight(accent.getHex(), 1.5, 18);
    key.position.set(3.2, 2.4, 3.4);
    scene.add(key);
    const rim = new THREE.PointLight(theme.dark ? 0x7aa3ff : 0xffffff, 0.7, 18);
    rim.position.set(-3.4, -1.6, 2.2);
    scene.add(rim);
    const under = new THREE.PointLight(accent.getHex(), 0.5, 14);
    under.position.set(0, -3.2, 1.2);
    scene.add(under);

    // --- Interaction state ---
    const target = { x: 0, y: 0 };
    const onPointer = (e) => {
      const r = mount.getBoundingClientRect();
      const cx = r.left + r.width / 2;
      const cy = r.top + r.height / 2;
      target.y = ((e.clientX - cx) / window.innerWidth) * 1.1;
      target.x = ((e.clientY - cy) / window.innerHeight) * 0.7;
    };
    if (motion) window.addEventListener("pointermove", onPointer);

    // --- Render loop ---
    let raf = 0;
    let t = 0;
    let autoRotY = 0;
    const eased = { x: 0, y: 0 }; // lerped parallax
    const renderOnce = () => {
      group.rotation.y = 0.5;
      group.rotation.x = 0.1;
      renderer.render(scene, camera);
    };

    const tick = () => {
      t += 0.016;
      // auto-rotate accumulates; pointer parallax lerps in as an offset
      autoRotY += 0.0035;
      eased.x += (target.x - eased.x) * 0.04;
      eased.y += (target.y - eased.y) * 0.04;
      group.rotation.y = autoRotY + eased.y;
      group.rotation.x = eased.x + Math.sin(t * 0.4) * 0.05;
      group.rotation.z = Math.sin(t * 0.23) * 0.04;
      const breathe = 1 + Math.sin(t * 0.8) * 0.012;
      group.scale.setScalar(breathe);
      group.position.y = Math.sin(t * 0.35) * 0.08;

      // dust slowly orbits
      dust.rotation.y = t * 0.05;
      dust.rotation.x = Math.sin(t * 0.1) * 0.05;

      // key light gently swings so facets glint as it turns
      key.position.x = Math.cos(t * 0.3) * 3.4;
      key.position.z = Math.sin(t * 0.3) * 3.4 + 1.2;

      renderer.render(scene, camera);
      raf = requestAnimationFrame(tick);
    };

    if (motion) {
      raf = requestAnimationFrame(tick);
    } else {
      renderOnce();
    }

    // Pause rendering when scrolled offscreen (battery on mobile)
    let observer;
    if (motion && "IntersectionObserver" in window) {
      observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            if (!raf) raf = requestAnimationFrame(tick);
          } else {
            cancelAnimationFrame(raf);
            raf = 0;
          }
        });
      });
      observer.observe(mount);
    }

    return () => {
      cancelAnimationFrame(raf);
      if (observer) observer.disconnect();
      if (motion) window.removeEventListener("pointermove", onPointer);
      geo.dispose();
      edges.dispose();
      nodeGeo.dispose();
      dustGeo.dispose();
      facetMat.dispose();
      seamMat.dispose();
      nodeMat.dispose();
      dustMat.dispose();
      renderer.dispose();
      if (renderer.domElement.parentNode === mount) {
        mount.removeChild(renderer.domElement);
      }
    };
  }, [size, motion, theme.dark, theme.accent]);

  // Fallback to the 2D SVG mark when WebGL isn't available.
  if (!webglOk) {
    const { KintsugiMark } = window;
    return <KintsugiMark size={size} drawIn={motion} motion={motion} />;
  }

  return (
    <div
      style={{
        position: "relative",
        width: size,
        height: size,
      }}
    >
      {/* soft gold halo behind the canvas */}
      <div
        aria-hidden
        style={{
          position: "absolute",
          inset: "-12%",
          background: `radial-gradient(circle at 50% 50%, ${theme.accent}2e, ${theme.accent}08 42%, transparent 68%)`,
          filter: "blur(16px)",
          pointerEvents: "none",
        }}
      />
      <div
        ref={mountRef}
        aria-label="Shard — rotating faceted crystal mark"
        role="img"
        style={{ position: "relative", width: size, height: size }}
      />
    </div>
  );
}

window.ShardHero3D = ShardHero3D;
