import React, { useEffect, useRef, useState } from 'react';
import Globe from 'globe.gl';
import * as THREE from 'three';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { TileTextureManager } from '../utils/tileRenderer';

interface Props {
  data: { planes: any[]; satellites: any[]; news?: any[]; gpsInterference?: any[]; webcams?: any[]; ships?: any[]; aiAnalysis?: any; emergencySquawks?: any[]; conflicts?: any[]; cyber_attacks?: any[]; };
  selectedItem: any;
  onSelectItem: (item: any) => void;
  onPovChange?: (pov: { lat: number; lng: number; altitude: number }) => void;
}

const DEG_TO_RAD = Math.PI / 180;
const GLOBE_RADIUS = 100;
const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json';

function predictPlanePos(p: any, s: number) {
  if (!p.velocity || p.heading == null || s <= 0 || s > 120) return p;
  const cLat = Math.cos(p.lat * DEG_TO_RAD); if (Math.abs(cLat) < 0.001) return p;
  return { ...p, lat: p.lat + (p.velocity * Math.cos(p.heading * DEG_TO_RAD) * s) / 111320, lon: (p.lon ?? p.lng) + (p.velocity * Math.sin(p.heading * DEG_TO_RAD) * s) / (111320 * cLat) };
}
function predictShipPos(p: any, s: number) {
  if (!p.velocity || p.heading == null || s <= 0 || s > 600) return p;
  const cLat = Math.cos(p.lat * DEG_TO_RAD); if (Math.abs(cLat) < 0.001) return p;
  return { ...p, lat: p.lat + (p.velocity * Math.cos(p.heading * DEG_TO_RAD) * s) / 111320, lon: (p.lon ?? p.lng) + (p.velocity * Math.sin(p.heading * DEG_TO_RAD) * s) / (111320 * cLat) };
}
function predictSatPos(p: any, s: number) {
  if (!isFinite(p.lat) || !isFinite(p.lon ?? p.lng)) return p;
  return { ...p, lon: ((p.lon ?? p.lng) + (0.067 * s) + 180) % 360 - 180 };
}
function polar2xyz(lat: number, lng: number, alt: number): [number, number, number] {
  const phi = (90 - lat) * DEG_TO_RAD, theta = (90 - lng) * DEG_TO_RAD, r = GLOBE_RADIUS * (1 + alt);
  return [r * Math.sin(phi) * Math.cos(theta), r * Math.cos(phi), r * Math.sin(phi) * Math.sin(theta)];
}
function validCoord(la: any, lo: any) { return typeof la === 'number' && typeof lo === 'number' && isFinite(la) && isFinite(lo); }
function hexGeoJson(lat: number, lon: number, radiusDeg: number) {
  const cosLat = Math.cos((lat * Math.PI) / 180); const verts: [number, number][] = [];
  for (let i = 0; i < 6; i++) { const ang = ((i * 60 - 90) * Math.PI) / 180; verts.push([lon + (radiusDeg / cosLat) * Math.sin(ang), lat + radiusDeg * Math.cos(ang)]); }
  verts.push(verts[0]); return { type: 'Polygon' as const, coordinates: [verts] };
}

function createPlaneGeo() { const geo = new THREE.ConeGeometry(0.55, 2.2, 3); geo.rotateX(Math.PI / 2); return geo; }
function createShipGeo() { return new THREE.BoxGeometry(0.5, 0.35, 1.8); }
function createSatGeo() { return new THREE.OctahedronGeometry(0.75); }

// Altitude-coded aircraft colors (WorldView style)
function getPlaneColor(item: any): [number, number, number] {
  if (item.military) return [1.0, 0.15, 0.05];   // red — military
  const alt = item.alt || 0;
  if (alt > 10000) return [0.0, 0.85, 1.0];       // cyan — high altitude
  if (alt > 5000)  return [0.2, 1.0, 0.5];        // green — cruise
  if (alt > 2000)  return [1.0, 0.7, 0.0];        // amber — low
  if (alt > 500)   return [1.0, 0.4, 0.0];        // orange — very low
  return [1.0, 1.0, 1.0];                         // white — ground/unknown
}
function getShipColor(item: any): [number, number, number] {
  const t = (item.type || item.vessel_type || '').toLowerCase();
  if (item.military || t.includes('military') || t.includes('naval')) return [1.0, 0.2, 0.1];
  if (t.includes('tanker') || t.includes('lng')) return [1.0, 0.65, 0.0];
  return [0.0, 0.7, 1.0];
}

const GlobeView: React.FC<Props> = ({ data, selectedItem, onSelectItem, onPovChange }) => {
  const globeRef = useRef<HTMLDivElement>(null), globeInstance = useRef<any>(null), mapContainerRef = useRef<HTMLDivElement>(null);
  const [isLoaded, setIsLoaded] = useState(false), [viewMode, setViewMode] = useState<'globe' | 'map'>('globe'), [mapReady, setMapReady] = useState(false);
  const viewModeRef = useRef<'globe' | 'map'>('globe');
  const MAX_PLANES = 20000, MAX_SHIPS = 10000, MAX_SATS = 3000;
  const pRef = useRef<any[]>([]), sRef = useRef<any[]>([]), saRef = useRef<any[]>([]), spRef = useRef<any[]>([]), ssRef = useRef<any[]>([]);
  const pT = useRef(Date.now()), sT = useRef(Date.now()), saT = useRef(Date.now());
  const pM = useRef<THREE.InstancedMesh>(null!), sM = useRef<THREE.InstancedMesh>(null!), saM = useRef<THREE.InstancedMesh>(null!), selM = useRef<THREE.Mesh>(null!);
  const currentPov = useRef({ lat: 25, lng: 20, altitude: 2.2 });
  const mapLibre = useRef<maplibregl.Map | null>(null);

  useEffect(() => { pRef.current = data.planes || []; pT.current = Date.now(); }, [data.planes]);
  useEffect(() => { sRef.current = data.ships || []; sT.current = Date.now(); }, [data.ships]);
  useEffect(() => { saRef.current = data.satellites || []; saT.current = Date.now(); }, [data.satellites]);

  useEffect(() => {
    viewModeRef.current = viewMode;
    // When returning to globe from map, reset altitude so controls
    // don't immediately re-trigger the map condition (altitude < 0.35)
    if (viewMode === 'globe' && globeInstance.current) {
      const safeAlt = 1.5;
      currentPov.current = { ...currentPov.current, altitude: safeAlt };
      globeInstance.current.pointOfView({ lat: currentPov.current.lat, lng: currentPov.current.lng, altitude: safeAlt }, 800);
    }
  }, [viewMode]);

  useEffect(() => {
    (window as any).__ARGUS_NEXUS_ON_SECTOR_DATA__ = (msg: any) => { spRef.current = msg.planes || []; ssRef.current = msg.ships || []; };
    return () => { (window as any).__ARGUS_NEXUS_ON_SECTOR_DATA__ = null; };
  }, []);

  useEffect(() => {
    if (!isLoaded || viewMode !== 'globe') return;
    const interval = setInterval(() => {
      const pov = currentPov.current;
      if (pov.altitude > 1.2) { spRef.current = []; ssRef.current = []; return; }
      const span = pov.altitude * 45;
      (window as any).__ARGUS_NEXUS_REQUEST_SECTOR__?.({ lamin: Math.max(-90, pov.lat-span), lamax: Math.min(90, pov.lat+span), lomin: pov.lng-span*1.5, lomax: pov.lng+span*1.5 });
    }, 2500);
    return () => clearInterval(interval);
  }, [isLoaded, viewMode]);

  useEffect(() => {
    if (!globeRef.current || globeInstance.current) return;
    const tileMgr = new TileTextureManager();
    const globe = new Globe(globeRef.current).width(window.innerWidth).height(window.innerHeight).backgroundColor('#020617').showGlobe(true)
      .globeMaterial(new THREE.MeshStandardMaterial({ map: tileMgr.createTexture(), roughness: 0.9, metalness: 0.2 }))
      .showAtmosphere(true).atmosphereColor('#0ea5e9').atmosphereAltitude(0.15);
    globe.pointOfView({ lat: 25, lng: 20, altitude: 2.2 }, 0); globeInstance.current = globe;
    const scene = globe.scene(); scene.add(new THREE.AmbientLight(0xffffff, 0.6));
    const sun = new THREE.DirectionalLight(0xffffff, 3.0); sun.position.set(500, 500, 500); scene.add(sun);
    const matPlane = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.2, metalness: 0.9, emissive: 0xffffff, emissiveIntensity: 0.4 });
    const matShip  = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.3, metalness: 0.7, emissive: 0xffffff, emissiveIntensity: 0.35 });
    const matSat   = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.1, metalness: 1.0, emissive: 0xffffff, emissiveIntensity: 0.5 });
    pM.current = new THREE.InstancedMesh(createPlaneGeo(), matPlane, MAX_PLANES);
    sM.current = new THREE.InstancedMesh(createShipGeo(), matShip, MAX_SHIPS);
    saM.current = new THREE.InstancedMesh(createSatGeo(), matSat, MAX_SATS);
    [pM.current, sM.current, saM.current].forEach((m) => { m.instanceMatrix.setUsage(THREE.DynamicDrawUsage); m.frustumCulled = false; scene.add(m); });
    selM.current = new THREE.Mesh(new THREE.RingGeometry(1.5, 1.8, 32), new THREE.MeshBasicMaterial({ color: 0x00ffff, side: THREE.DoubleSide, transparent: true, opacity: 0.9 }));
    selM.current.visible = false; scene.add(selM.current);
    globe.controls().addEventListener('change', () => {
      const pov = globe.pointOfView(); currentPov.current = pov;
      onPovChange?.(pov);
      if (pov.altitude < 0.35 && viewModeRef.current === 'globe') setViewMode('map');
    });
    const getHits = (e: PointerEvent) => {
      const rect = globeRef.current!.getBoundingClientRect(), mouse = new THREE.Vector2(((e.clientX - rect.left)/rect.width)*2-1, -((e.clientY-rect.top)/rect.height)*2+1);
      const rc = new THREE.Raycaster(); rc.setFromCamera(mouse, globe.camera());
      return rc.intersectObjects([pM.current, sM.current, saM.current]);
    };
    globeRef.current!.addEventListener('pointerup', (e) => {
      const hits = getHits(e); if (hits.length > 0 && hits[0].instanceId != null) (window as any).__ARGUS_NEXUS_HIT__ = { obj: hits[0].object, idx: hits[0].instanceId };
    });
    tileMgr.loadBaseLayer().catch(()=>{}); setIsLoaded(true);
    return () => { if (typeof globe._destructor === 'function') globe._destructor(); globeInstance.current = null; };
  }, []);

  useEffect(() => {
    if (!isLoaded || !globeInstance.current) return;
    const dummy = new THREE.Object3D(), up = new THREE.Vector3(0, 1, 0), basis = new THREE.Matrix4();
    const rendered: {p: any[], s: any[], sa: any[]} = { p: [], s: [], sa: [] };
    function animate() {
      if (viewModeRef.current !== 'globe') { requestAnimationFrame(animate); return; }
      const t = Date.now(), pe = (t-pT.current)/1000, se = (t-sT.current)/1000, sae = (t-saT.current)/1000, alt = currentPov.current.altitude;
      const planes = [...pRef.current]; if(spRef.current.length) { const ids = new Set(planes.map(x=>x.id)); spRef.current.forEach(x=>{if(!ids.has(x.id)) planes.push(x);}); }
      const ships = [...sRef.current]; if(ssRef.current.length) { const ids = new Set(ships.map(x=>x.id)); ssRef.current.forEach(x=>{if(!ids.has(x.id)) ships.push(x);}); }
      const sats = saRef.current;
      const lod = alt > 1.8 ? 10 : alt > 1.0 ? 3 : 1, isZ = alt < 1.2, pLat = currentPov.current.lat, pLng = currentPov.current.lng;
      [ { m: pM.current, d: planes, t: pe, lim: MAX_PLANES, type: 'p', f: predictPlanePos, r: rendered.p },
        { m: sM.current, d: ships, t: se, lim: MAX_SHIPS, type: 's', f: predictShipPos, r: rendered.s },
        { m: saM.current, d: sats, t: sae, lim: MAX_SATS, type: 'sa', f: predictSatPos, r: rendered.sa }
      ].forEach(l => {
        if (!l.m) return;
        let count = 0; l.r.length = 0;
        for (let i = 0; i < l.d.length && count < l.lim; i++) {
          const item = l.d[i], lat = item.lat, lon = item.lon ?? item.lng;
          if (!validCoord(lat, lon)) continue;
          if (isZ && l.type !== 'sa' && (Math.abs(lat - pLat) > 60 || Math.abs(((lon - pLng + 540) % 360) - 180) > 70)) continue;
          if (l.type !== 'sa' && !(item.military || item.vessel_type === 'Military') && (i % lod !== 0)) continue;
          const p = l.f(item, l.t), [x, y, z] = polar2xyz(p.lat, p.lon ?? p.lng, l.type === 'sa' ? 0.15 : 0.02);
          if (y === -1000) continue;
          const pos = new THREE.Vector3(x, y, z), norm = pos.clone().normalize();
          basis.makeBasis(new THREE.Vector3().crossVectors(up, norm).normalize(), new THREE.Vector3().crossVectors(norm, new THREE.Vector3().crossVectors(up, norm).normalize()).normalize(), norm);
          dummy.quaternion.setFromRotationMatrix(basis); dummy.position.copy(pos); dummy.rotateZ(-(item.heading || 0) * DEG_TO_RAD);
          const s = l.type === 'sa' ? 1.4 : (alt > 2.0 ? 1.6 : alt > 1.0 ? 1.2 : alt < 0.4 ? 0.6 : 0.9); dummy.scale.set(s, s, s);
          dummy.updateMatrix(); l.m.setMatrixAt(count, dummy.matrix);
          const c = l.type === 'p' ? getPlaneColor(item) : l.type === 's' ? getShipColor(item) : [0, 1, 0.5];
          l.m.setColorAt(count, new THREE.Color(c[0], c[1], c[2])); l.r[count] = item; count++;
        }
        l.m.instanceMatrix.needsUpdate = true; if (l.m.instanceColor) l.m.instanceColor.needsUpdate = true; l.m.count = count;
      });
      if (selectedItem && validCoord(selectedItem.lat, selectedItem.lon ?? selectedItem.lng)) {
        const [x, y, z] = polar2xyz(selectedItem.lat, selectedItem.lon ?? selectedItem.lng, selectedItem.dataType === 'satellite' ? 0.16 : 0.03);
        selM.current.position.set(x, y, z); selM.current.lookAt(0, 0, 0); selM.current.visible = true;
      } else selM.current.visible = false;
      const hit = (window as any).__ARGUS_NEXUS_HIT__;
      if (hit) {
        if (hit.obj === pM.current) onSelectItem({ ...rendered.p[hit.idx], dataType: 'plane' });
        else if (hit.obj === sM.current) onSelectItem({ ...rendered.s[hit.idx], dataType: 'ship' });
        else if (hit.obj === saM.current) onSelectItem({ ...rendered.sa[hit.idx], dataType: 'satellite' });
        (window as any).__ARGUS_NEXUS_HIT__ = null;
      }
      requestAnimationFrame(animate);
    }
    animate();
  }, [isLoaded]);

  useEffect(() => {
    if (!globeInstance.current || !isLoaded) return;
    const globe = globeInstance.current;
    globe.arcsData(data.cyber_attacks || []).arcStartLat('startLat').arcStartLng('startLng').arcEndLat('endLat').arcEndLng('endLng').arcColor((d: any) => d.color || '#ff003c').arcDashLength(0.5).arcDashGap(1).arcDashAnimateTime(1000).arcStroke(0.6).arcAltitudeAutoScale(0.3);
    const rData = [...(data.news || []).filter(n => n.lat).map(n => ({ ...n, _ringType: 'news' })), ...(data.emergencySquawks || []).filter(e => e.lat).map(e => ({ ...e, _ringType: 'emergency' }))];
    globe.ringsData(rData).ringLat('lat').ringLng((d: any) => d.lon ?? d.lng).ringColor((d: any) => d._ringType === 'emergency' ? (t: number) => `rgba(255,0,50,${1-t})` : (t: number) => `rgba(14,165,233,${0.4*(1-t)})`).ringMaxRadius(4);
    globe.polygonsData((data.gpsInterference || []).map(z => ({ ...z, _geo: hexGeoJson(z.lat, z.lon ?? z.lng, 1.2) }))).polygonGeoJsonGeometry((d: any) => d._geo).polygonCapColor(() => 'rgba(255,0,60,0.15)').polygonStrokeColor(() => '#ff003c').polygonAltitude(0.001);
  }, [data.news, data.gpsInterference, data.cyber_attacks, isLoaded]);

  // --- MAPLIBRE (2D) ---
  useEffect(() => {
    if (viewMode !== 'map' || !mapContainerRef.current) {
      setMapReady(false);
      if (mapLibre.current) { mapLibre.current.remove(); mapLibre.current = null; }
      return;
    }
    const map = new maplibregl.Map({ container: mapContainerRef.current, style: MAP_STYLE, center: [currentPov.current.lng, currentPov.current.lat], zoom: 9 });
    map.on('zoom', () => { if (map.getZoom() < 4) setViewMode('globe'); });
    map.on('moveend', () => { const c = map.getCenter(); currentPov.current = { ...currentPov.current, lat: c.lat, lng: c.lng }; });
    map.on('load', () => {
      map.addSource('p', { type: 'geojson', data: { type: 'FeatureCollection', features: [] } });
      map.addLayer({ id: 'p-layer', type: 'circle', source: 'p', paint: { 'circle-radius': 6, 'circle-color': '#eab308', 'circle-stroke-width': 1, 'circle-stroke-color': '#000' } });
      map.addSource('s', { type: 'geojson', data: { type: 'FeatureCollection', features: [] } });
      map.addLayer({ id: 's-layer', type: 'circle', source: 's', paint: { 'circle-radius': 5, 'circle-color': '#0ea5e9', 'circle-stroke-width': 1, 'circle-stroke-color': '#000' } });
      map.addSource('sa', { type: 'geojson', data: { type: 'FeatureCollection', features: [] } });
      map.addLayer({ id: 'sa-layer', type: 'circle', source: 'sa', paint: { 'circle-radius': 4, 'circle-color': '#22c55e', 'circle-stroke-width': 1, 'circle-stroke-color': '#000' } });
      map.on('click', 'p-layer', (e) => { if (e.features?.length) onSelectItem({ ...e.features[0].properties, dataType: 'plane' }); });
      map.on('click', 's-layer', (e) => { if (e.features?.length) onSelectItem({ ...e.features[0].properties, dataType: 'ship' }); });
      map.on('click', 'sa-layer', (e) => { if (e.features?.length) onSelectItem({ ...e.features[0].properties, dataType: 'satellite' }); });
      setMapReady(true);
    });
    mapLibre.current = map;
    return () => { setMapReady(false); if (mapLibre.current) { mapLibre.current.remove(); mapLibre.current = null; } };
  }, [viewMode]);

  useEffect(() => {
    const map = mapLibre.current;
    if (!mapReady || !map) return;
    const pGeo: any = { type: 'FeatureCollection', features: (data.planes || []).filter(x => validCoord(x.lat, x.lon)).map(x => ({ type: 'Feature', geometry: { type: 'Point', coordinates: [x.lon, x.lat] }, properties: { ...x } })) };
    const sGeo: any = { type: 'FeatureCollection', features: (data.ships || []).filter(x => validCoord(x.lat, x.lon??x.lng)).map(x => ({ type: 'Feature', geometry: { type: 'Point', coordinates: [x.lon??x.lng, x.lat] }, properties: { ...x } })) };
    const saGeo: any = { type: 'FeatureCollection', features: (data.satellites || []).filter(x => validCoord(x.lat, x.lon??x.lng)).map(x => ({ type: 'Feature', geometry: { type: 'Point', coordinates: [x.lon??x.lng, x.lat] }, properties: { ...x } })) };
    (map.getSource('p') as any)?.setData(pGeo);
    (map.getSource('s') as any)?.setData(sGeo);
    (map.getSource('sa') as any)?.setData(saGeo);
  }, [mapReady, data.planes, data.ships, data.satellites]);

  return (
    <div className="absolute inset-0 bg-[#020617]">
      <div ref={globeRef} style={{ width: '100%', height: '100%', position: 'absolute', top: 0, left: 0, visibility: viewMode === 'globe' ? 'visible' : 'hidden', pointerEvents: viewMode === 'globe' ? 'auto' : 'none' }} />
      <div ref={mapContainerRef} style={{ width: '100%', height: '100%', position: 'absolute', top: 0, zIndex: 10, display: viewMode === 'map' ? 'block' : 'none' }} />
      {viewMode === 'map' && (
        <button
          onClick={() => setViewMode('globe')}
          style={{ position: 'absolute', bottom: '48px', right: '12px', zIndex: 20 }}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-slate-900/90 border border-sky-500/50 text-sky-400 text-[10px] font-bold tracking-wider rounded-lg backdrop-blur-sm hover:bg-sky-500/20 transition-all shadow-lg"
        >
          ↩ 3D Globe
        </button>
      )}
    </div>
  );
};

export default React.memo(GlobeView);
