"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import * as THREE from "three";

/**
 * "Your digital world" — a slowly turning globe of data points with
 * orbital connection rings, in the brand's azure/cyan. Used in inner-page
 * heros. Pauses offscreen and honors reduced motion.
 */

const POINTS = 1500;
const RADIUS = 2.3;

function Globe({ paused }: { paused: boolean }) {
  const group = useRef<THREE.Group>(null);
  const pointer = useRef({ x: 0, y: 0 });

  const positions = useMemo(() => {
    const arr = new Float32Array(POINTS * 3);
    // fibonacci sphere for even coverage
    const phi = Math.PI * (3 - Math.sqrt(5));
    for (let i = 0; i < POINTS; i++) {
      const y = 1 - (i / (POINTS - 1)) * 2;
      const r = Math.sqrt(1 - y * y);
      const theta = phi * i;
      arr[i * 3] = Math.cos(theta) * r * RADIUS;
      arr[i * 3 + 1] = y * RADIUS;
      arr[i * 3 + 2] = Math.sin(theta) * r * RADIUS;
    }
    return arr;
  }, []);

  const rings = useMemo(() => {
    const out: { rot: [number, number, number]; scale: number; opacity: number }[] = [];
    for (let i = 0; i < 7; i++) {
      out.push({
        rot: [(i * 0.9) % Math.PI, (i * 1.7) % Math.PI, (i * 0.6) % Math.PI],
        scale: 1 + (i % 3) * 0.001,
        opacity: 0.12 + (i % 3) * 0.05,
      });
    }
    return out;
  }, []);

  useEffect(() => {
    const onMove = (e: PointerEvent) => {
      pointer.current.x = (e.clientX / window.innerWidth) * 2 - 1;
      pointer.current.y = (e.clientY / window.innerHeight) * 2 - 1;
    };
    window.addEventListener("pointermove", onMove, { passive: true });
    return () => window.removeEventListener("pointermove", onMove);
  }, []);

  useFrame((state, delta) => {
    const g = group.current;
    if (!g || paused) return;
    g.rotation.y += delta * 0.12;
    g.rotation.x += (pointer.current.y * 0.12 + 0.18 - g.rotation.x) * 0.03;
    g.rotation.z += (pointer.current.x * 0.05 - g.rotation.z) * 0.03;
  });

  return (
    <group ref={group} rotation={[0.18, 0, 0]}>
      <points>
        <bufferGeometry>
          <bufferAttribute attach="attributes-position" args={[positions, 3]} />
        </bufferGeometry>
        <pointsMaterial
          color="#4FC3FF"
          size={0.028}
          sizeAttenuation
          transparent
          opacity={0.85}
          depthWrite={false}
        />
      </points>
      {rings.map((r, i) => (
        <mesh key={i} rotation={r.rot} scale={r.scale}>
          <torusGeometry args={[RADIUS * 1.02, 0.004, 6, 128]} />
          <meshBasicMaterial color={i % 2 ? "#2E8BF7" : "#7FB8F0"} transparent opacity={r.opacity} />
        </mesh>
      ))}
      {/* equator highlight */}
      <mesh rotation={[Math.PI / 2, 0, 0]}>
        <torusGeometry args={[RADIUS * 1.02, 0.007, 6, 160]} />
        <meshBasicMaterial color="#4FC3FF" transparent opacity={0.35} />
      </mesh>
    </group>
  );
}

export default function DataGlobe({ className }: { className?: string }) {
  const wrap = useRef<HTMLDivElement>(null);
  const [visible, setVisible] = useState(true);
  const [reduced, setReduced] = useState(false);
  const [hidden, setHidden] = useState(false);

  useEffect(() => {
    setReduced(window.matchMedia("(prefers-reduced-motion: reduce)").matches);
    const el = wrap.current;
    if (!el) return;
    const io = new IntersectionObserver(([e]) => setVisible(e.isIntersecting), { threshold: 0 });
    io.observe(el);
    const onVis = () => setHidden(document.hidden);
    document.addEventListener("visibilitychange", onVis);
    return () => {
      io.disconnect();
      document.removeEventListener("visibilitychange", onVis);
    };
  }, []);

  const paused = reduced || !visible || hidden;

  return (
    <div ref={wrap} className={`pointer-events-none ${className ?? ""}`} aria-hidden="true">
      <Canvas
        camera={{ position: [0, 0, 6.4], fov: 42 }}
        dpr={[1, 1.6]}
        gl={{ antialias: true, alpha: true }}
        frameloop={paused ? "demand" : "always"}
        style={{ pointerEvents: "none" }}
      >
        <Globe paused={paused} />
      </Canvas>
    </div>
  );
}
