/* SunHero3D — true 3D sphere via Three.js, equirectangular sun map wrapped
   on a SphereGeometry. Rotates around a tilted axis so the motion reads
   diagonally instead of as a horizontal slide.

   Behind the canvas sit the existing CSS corona divs (`.sun-corona-outer`
   and `.sun-corona-mid`) so the whole halo system stays consistent with
   the rest of the page.

   Pinned dep: three @ 0.160 (UMD build, exposes window.THREE).               */
function SunHero3D({ progress }) {
  const scale = 1 - progress * 0.4;
  const opacity = 1 - Math.min(progress * 1.4, 0.85);
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || !window.THREE) return;

    const THREE = window.THREE;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    // Renderer — transparent so the corona divs underneath bleed through.
    const renderer = new THREE.WebGLRenderer({
      canvas, alpha: true, antialias: true, premultipliedAlpha: false,
    });
    renderer.setPixelRatio(dpr);
    renderer.outputColorSpace = THREE.SRGBColorSpace;

    // Square stage; sized via ResizeObserver so we always render at the
    // canvas's actual CSS box.
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(28, 1, 0.1, 100);
    camera.position.set(0, 0, 4.2);

    // Sun sphere — emissive map so the texture lights itself; no real light
    // needed. MeshBasicMaterial samples the texture directly with no shading.
    const geom = new THREE.SphereGeometry(1, 96, 64);
    const tex = new THREE.TextureLoader().load('assets/sun_equi.jpg');
    tex.colorSpace = THREE.SRGBColorSpace;
    tex.anisotropy = renderer.capabilities.getMaxAnisotropy?.() ?? 4;
    const mat = new THREE.MeshBasicMaterial({ map: tex });
    const sun = new THREE.Mesh(geom, mat);

    // Diagonal tilt — Z axis tilt of ~23° + a small X tilt so the texture's
    // poles aren't aligned with the visible top/bottom. Combined with the
    // Y-axis spin this makes the surface flow diagonally.
    sun.rotation.z = 0.40;  // ~23°
    sun.rotation.x = 0.18;  // tip the visible pole slightly toward camera
    scene.add(sun);

    // (No billboard rim plane — earlier versions added one, but a rectangular
    // plane behind a sphere produced visible corner-glow artifacts. The CSS
    // corona divs handle the halo cleanly.)

    // ResizeObserver keeps the renderer sized to the CSS box.
    const resize = () => {
      const w = canvas.clientWidth || 1;
      const h = canvas.clientHeight || 1;
      renderer.setSize(w, h, false);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(canvas);

    // Animation loop — slow Y-axis spin combined with the static tilt
    // produces a diagonal surface drift. ~120s per full revolution.
    const startedAt = performance.now();
    let raf = 0;
    const tick = (now) => {
      const t = (now - startedAt) / 1000;
      sun.rotation.y = (t / 120) * Math.PI * 2;
      renderer.render(scene, camera);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);

    return () => {
      cancelAnimationFrame(raf);
      ro.disconnect();
      geom.dispose();
      mat.dispose();
      tex.dispose();
      renderer.dispose();
    };
  }, []);

  return (
    <div className="planet-stage" style={{ transform: `scale(${scale})`, opacity }}>
      <div className="sun-stage">
        {/* Layered halo — far haze, mid wash, and a tight rim ring that
            hugs the sphere's silhouette for a stronger limb gradient. */}
        <div className="sun-corona-outer" />
        <div className="sun-corona-mid" />
        <div className="sun-corona-rim" />
        <canvas ref={canvasRef} className="sun-canvas"
                style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none' }} />
      </div>
    </div>
  );
}

window.SunHero3D = SunHero3D;
