"use client";

import { Suspense, useEffect, useRef, useState } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { OrbitControls, Sphere, Line } from "@react-three/drei";
import * as THREE from "three";

const LAND_TEXTURE_URL = "https://yefranchisees.b-cdn.net/frontend/About/img-02.png";

/* ================= Locations ================= */
type Location = {
  lat: number;
  lon: number;
};

/* ================= Utils ================= */
function latLngToVector3(lat: number, lon: number, r: number = 2.2) {
  const phi = (90 - lat) * (Math.PI / 180);
  const theta = (lon + 180) * (Math.PI / 180);

  return new THREE.Vector3(
    -r * Math.sin(phi) * Math.cos(theta),
    r * Math.cos(phi),
    r * Math.sin(phi) * Math.sin(theta)
  );
}

/* 🔹 NEW: lat/lon → rotation */
function latLngToRotation(lat: number, lon: number) {
  return {
    x: (lat * Math.PI) / 180,
    y: (-lon * Math.PI) / 180,
  };
}

/* ================= Grid ================= */
function GlobeGrid() {
  const lines: THREE.Vector3[][] = [];

  for (let lat = -80; lat <= 80; lat += 20) {
    const points: THREE.Vector3[] = [];
    for (let lon = 0; lon <= 360; lon += 5) {
      points.push(latLngToVector3(lat, lon));
    }
    lines.push(points);
  }

  for (let lon = 0; lon < 360; lon += 20) {
    const points: THREE.Vector3[] = [];
    for (let lat = -90; lat <= 90; lat += 5) {
      points.push(latLngToVector3(lat, lon));
    }
    lines.push(points);
  }

  return (
    <>
      {lines.map((points, i) => (
        <Line
          key={i}
          points={points}
          color="#E0E0E0"
          transparent
          opacity={0.25}
        />
      ))}
    </>
  );
}

/*==============LocationPin==================*/
function LocationPin({
  lat,
  lon,
  radius = 2.25,
}: {
  lat: number;
  lon: number;
  radius?: number;
}) {
  const ref = useRef<THREE.Group>(null);
  const position = latLngToVector3(lat, lon, radius);

  useFrame(() => {
    if (!ref.current) return;
    ref.current.lookAt(0, 0, 0);
  });

  return (
    <group ref={ref} position={position}>
      {/* Stem */}
      <mesh position={[0, -0.08, 0]}>
        <cylinderGeometry args={[0.01, 0.01, 0.1, 8]} />
        <meshStandardMaterial color="#F39300" />
      </mesh>

      {/* Ring */}
      <mesh position={[0, 0.02, 0]}>
        <torusGeometry args={[0.055, 0.012, 16, 32]} />
        <meshStandardMaterial color="#F39300" />
      </mesh>

      {/* Center dot */}
      <mesh position={[0, 0.02, 0]}>
        <circleGeometry args={[0.02, 16]} />
        <meshStandardMaterial color="#FFED00" />
      </mesh>
    </group>
  );
}

/* ================= Land mask (texture is loaded imperatively, never throws) ================= */
function LandSphere() {
  const [landTexture, setLandTexture] = useState<THREE.Texture | null>(null);

  useEffect(() => {
    const loader = new THREE.TextureLoader();
    loader.setCrossOrigin("anonymous");
    let cancelled = false;
    loader.load(
      LAND_TEXTURE_URL,
      (tex) => {
        if (cancelled) return;
        tex.colorSpace = THREE.SRGBColorSpace;
        setLandTexture(tex);
      },
      undefined,
      (err) => {
        console.warn("[StyledGlobe] Land texture failed to load:", err);
      }
    );
    return () => {
      cancelled = true;
    };
  }, []);

  if (!landTexture) return null;

  return (
    <Sphere args={[2.201, 64, 64]}>
      <meshStandardMaterial map={landTexture} transparent opacity={1} color="#E0E0E0" />
    </Sphere>
  );
}

/* ================= Globe ================= */
function Globe({ latitude, longitude, locations = [] }: { latitude?: string; longitude?: string; locations?: Location[] }) {
  const globeRef = useRef<THREE.Group | null>(null);

  /* 🌍 Set initial rotation ONCE */
  useEffect(() => {
    if (!globeRef.current) return;

    // 🔥 Pacific-centered texture fix
    const TEXTURE_OFFSET = Math.PI / 2;

    const setRotation = (lat: number, lon: number) => {
      const latRad = THREE.MathUtils.degToRad(lat);
      const lonRad = THREE.MathUtils.degToRad(lon);

      globeRef.current!.rotation.x = latRad;
      globeRef.current!.rotation.y = Math.PI - lonRad + TEXTURE_OFFSET;
    };

    // Priority: tenant latitude/longitude > browser geolocation > fallback India
    if (latitude && longitude) {
      setRotation(parseFloat(latitude), parseFloat(longitude));
    } else if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        (pos) => {
          setRotation(pos.coords.latitude, pos.coords.longitude);
        },
        () => {
          // fallback → India
          setRotation(20.5937, 78.9629);
        }
      );
    } else {
      setRotation(20.5937, 78.9629);
    }
  }, [latitude, longitude]);

  /* 🔄 Continuous rotation */
  useFrame(() => {
    if (!globeRef.current) return;
    globeRef.current.rotation.y += 0.0009;
  });

  return (
    <group ref={globeRef}>
      {/* Gradient Sphere */}
      <Sphere args={[2.2, 64, 64]}>
        <shaderMaterial
          uniforms={{
            colorTop: { value: new THREE.Color("#00416A") },
            colorBottom: { value: new THREE.Color("#007BC4") },
          }}
          vertexShader={`
            varying vec3 vPosition;
            void main() {
              vPosition = position;
              gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
          `}
          fragmentShader={`
            uniform vec3 colorTop;
            uniform vec3 colorBottom;
            varying vec3 vPosition;
            void main() {
              float gradient = normalize(vPosition).y * 0.5 + 0.5;
              vec3 color = mix(colorBottom, colorTop, gradient);
              gl_FragColor = vec4(color, 1.0);
            }
          `}
        />
      </Sphere>

      {/* Land — wrapped so a texture failure can't take down the whole scene */}
      <LandSphere />

      <GlobeGrid />

      {locations.map((loc, index) => (
        <LocationPin key={index} lat={loc.lat} lon={loc.lon} />
      ))}
    </group>
  );
}



/* ================= Canvas ================= */
export default function StyledGlobe({
  latitude,
  longitude,
  locations = [],
}: {
  latitude?: string;
  longitude?: string;
  locations?: Location[];
} = {}) {
  const wrapperRef = useRef<HTMLDivElement>(null);
  // Pause the WebGL render loop while the globe is off-screen to free the GPU
  // (otherwise it keeps rendering at full frame-rate behind other sections).
  const [active, setActive] = useState(true);

  useEffect(() => {
    const el = wrapperRef.current;
    if (!el || typeof IntersectionObserver === "undefined") return;
    const io = new IntersectionObserver(
      ([entry]) => setActive(entry.isIntersecting),
      { threshold: 0.01 },
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);

  // The container is pulled over the "OUR MISSION" copy with mb-[-290px] on
  // mobile, so the full-size transparent canvas also sits on top of that text —
  // dragging there used to rotate the globe instead of scrolling.
  //
  // So the canvas itself is made non-interactive (globals.css) and OrbitControls
  // is bound to `hitEl` below: a circle matching the rendered globe. Only drags
  // that actually start on the globe rotate it; everywhere else the page
  // scrolls normally.
  //
  // The globe is a radius-2.2 sphere at camera z=6 (fov 50), so its projected
  // diameter is ~79% of the canvas height — hence the sizing on that element.
  const [hitEl, setHitEl] = useState<HTMLDivElement | null>(null);

  return (
    <div
      ref={wrapperRef}
      className="globe-canvas"
      style={{ width: "100%", height: "100%", position: "relative" }}
    >
    <Canvas
      camera={{ position: [0, 0, 6] }}
      // Render only while visible; cap DPR so retina screens don't render at 2-3x.
      frameloop={active ? "always" : "never"}
      dpr={[1, 1.5]}
      gl={{ alpha: true, antialias: true, preserveDrawingBuffer: false, powerPreference: "high-performance" }}
      style={{ background: "transparent" }}
      onCreated={({ gl }) => {
        gl.setClearColor(0x000000, 0);
        gl.domElement.style.touchAction = "pan-y";
      }}
    >
      <ambientLight intensity={1.4} />
      <directionalLight position={[5, 3, 5]} intensity={1.6} />
      <Suspense fallback={null}>
        <Globe latitude={latitude} longitude={longitude} locations={locations} />
      </Suspense>
      <OrbitControls
        enableZoom={false}
        enablePan={false}
        // Bound to the globe-sized hit area, not the full canvas.
        domElement={hitEl ?? undefined}
        touches={{ ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_ROTATE }}
      />
    </Canvas>
      {/* Drag target: a circle the size of the rendered globe. Everything
          outside it (including the text the canvas overlaps) scrolls normally. */}
      <div
        ref={setHitEl}
        aria-hidden="true"
        className="globe-hit absolute left-1/2 top-1/2 h-[79%] aspect-square -translate-x-1/2 -translate-y-1/2 rounded-full"
      />
    </div>
  );
}
