import { useRef, useState, useEffect, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Map, NavigationControl, Marker, Popup, Source, Layer } from 'react-map-gl/maplibre';
import type { MapRef } from 'react-map-gl/maplibre';
import { ScatterplotLayer, TextLayer } from '@deck.gl/layers';
import { DeckGLOverlay } from '../layers/DeckGLOverlay';
import { useAnalysisDeckLayers } from '../../hooks/useAnalysisDeckLayers';
import { useStaticDeckLayers } from '../../hooks/useStaticDeckLayers';
import type { StaticPickInfo } from '../../hooks/useStaticDeckLayers';
import fishingZonesData from '../../data/zones/fishing-zones-wgs84.json';
import { ShipLayer } from '../layers/ShipLayer';
import { InfraLayer } from './InfraLayer';
import { SatelliteLayer } from '../layers/SatelliteLayer';
import { AircraftLayer } from '../layers/AircraftLayer';
import { SubmarineCableLayer } from './SubmarineCableLayer';
import { CctvLayer } from './CctvLayer';
// 정적 레이어들은 useStaticDeckLayers로 전환됨
import { OsintMapLayer } from './OsintMapLayer';
import { EezLayer } from './EezLayer';
// PiracyLayer, WindFarmLayer, PortLayer, MilitaryBaseLayer, GovBuildingLayer,
// NKLaunchLayer, NKMissileEventLayer → useStaticDeckLayers로 전환됨
import { ChineseFishingOverlay } from './ChineseFishingOverlay';
// HazardFacilityLayer, CnFacilityLayer, JpFacilityLayer → useStaticDeckLayers로 전환됨
import { AnalysisOverlay } from './AnalysisOverlay';
import { FleetClusterLayer } from './FleetClusterLayer';
import type { SelectedGearGroupData, SelectedFleetData } from './FleetClusterLayer';
import { FishingZoneLayer } from './FishingZoneLayer';
import { AnalysisStatsPanel } from './AnalysisStatsPanel';
import { getMarineTrafficCategory } from '../../utils/marineTraffic';
import { classifyFishingZone } from '../../utils/fishingAnalysis';
import { fetchKoreaInfra } from '../../services/infra';
import type { PowerFacility } from '../../services/infra';
import type { Ship, Aircraft, SatellitePosition } from '../../types';
import type { OsintItem } from '../../services/osint';
import type { UseVesselAnalysisResult } from '../../hooks/useVesselAnalysis';
import { countryLabelsGeoJSON } from '../../data/countryLabels';
import { useLocalStorage } from '../../hooks/useLocalStorage';
import 'maplibre-gl/dist/maplibre-gl.css';

export interface KoreaFiltersState {
  illegalFishing: boolean;
  illegalTransship: boolean;
  darkVessel: boolean;
  cableWatch: boolean;
  dokdoWatch: boolean;
  ferryWatch: boolean;
}

interface Props {
  ships: Ship[];
  allShips?: Ship[];
  aircraft: Aircraft[];
  satellites: SatellitePosition[];
  layers: Record<string, boolean>;
  osintFeed: OsintItem[];
  currentTime: number;
  koreaFilters: KoreaFiltersState;
  transshipSuspects: Set<string>;
  cableWatchSuspects: Set<string>;
  dokdoWatchSuspects: Set<string>;
  dokdoAlerts: { mmsi: string; name: string; dist: number; time: number }[];
  vesselAnalysis?: UseVesselAnalysisResult;
}

// MarineTraffic-style: satellite + dark ocean + nautical overlay
const MAP_STYLE = {
  version: 8 as const,
  sources: {
    'satellite': {
      type: 'raster' as const,
      tiles: [
        'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
      ],
      tileSize: 256,
      maxzoom: 19,
      attribution: '&copy; Esri, Maxar',
    },
    'carto-dark': {
      type: 'raster' as const,
      tiles: [
        'https://a.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png',
        'https://b.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png',
        'https://c.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png',
      ],
      tileSize: 256,
    },
    'opensea': {
      type: 'raster' as const,
      tiles: [
        'https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png',
      ],
      tileSize: 256,
      maxzoom: 18,
    },
  },
  layers: [
    { id: 'background', type: 'background' as const, paint: { 'background-color': '#0d1f3c' } },
    { id: 'satellite-base', type: 'raster' as const, source: 'satellite', paint: { 'raster-brightness-max': 0.75, 'raster-saturation': -0.1, 'raster-contrast': 0.05 } },
    { id: 'dark-overlay', type: 'raster' as const, source: 'carto-dark', paint: { 'raster-opacity': 0.25 } },
    { id: 'seamark', type: 'raster' as const, source: 'opensea', paint: { 'raster-opacity': 0.5 } },
  ],
};

// Korea-centered view
const KOREA_MAP_CENTER = { longitude: 127.5, latitude: 36 };
const KOREA_MAP_ZOOM = 6;

const FILTER_ICON: Record<string, string> = {
  illegalFishing: '\u{1F6AB}\u{1F41F}',
  illegalTransship: '\u2693',
  darkVessel: '\u{1F47B}',
  cableWatch: '\u{1F50C}',
  dokdoWatch: '\u{1F3DD}\uFE0F',
  ferryWatch: '\u{1F6A2}',
};

const FILTER_COLOR: Record<string, string> = {
  illegalFishing: '#ef4444',
  illegalTransship: '#f97316',
  darkVessel: '#8b5cf6',
  cableWatch: '#00e5ff',
  dokdoWatch: '#22c55e',
  ferryWatch: '#2196f3',
};

const FILTER_I18N_KEY: Record<string, string> = {
  illegalFishing: 'filters.illegalFishingMonitor',
  illegalTransship: 'filters.illegalTransshipMonitor',
  darkVessel: 'filters.darkVesselMonitor',
  cableWatch: 'filters.cableWatchMonitor',
  dokdoWatch: 'filters.dokdoWatchMonitor',
  ferryWatch: 'filters.ferryWatchMonitor',
};

export function KoreaMap({ ships, allShips, aircraft, satellites, layers, osintFeed, currentTime, koreaFilters, transshipSuspects, cableWatchSuspects, dokdoWatchSuspects, dokdoAlerts, vesselAnalysis }: Props) {
  const { t } = useTranslation();
  const mapRef = useRef<MapRef>(null);
  const [infra, setInfra] = useState<PowerFacility[]>([]);
  const [flyToTarget, setFlyToTarget] = useState<{ lng: number; lat: number; zoom: number } | null>(null);
  const [selectedAnalysisMmsi, setSelectedAnalysisMmsi] = useState<string | null>(null);
  const [trackCoords, setTrackCoords] = useState<[number, number][] | null>(null);
  const [selectedGearData, setSelectedGearData] = useState<SelectedGearGroupData | null>(null);
  const [selectedFleetData, setSelectedFleetData] = useState<SelectedFleetData | null>(null);
  const [zoomLevel, setZoomLevel] = useState(KOREA_MAP_ZOOM);
  const [staticPickInfo, setStaticPickInfo] = useState<StaticPickInfo | null>(null);
  const [analysisPanelOpen, setAnalysisPanelOpen] = useLocalStorage('analysisPanelOpen', false);

  useEffect(() => {
    fetchKoreaInfra().then(setInfra).catch(() => {});
  }, []);

  useEffect(() => {
    if (flyToTarget && mapRef.current) {
      mapRef.current.flyTo({ center: [flyToTarget.lng, flyToTarget.lat], zoom: flyToTarget.zoom, duration: 1500 });
      setFlyToTarget(null);
    }
  }, [flyToTarget]);

  useEffect(() => {
    if (!selectedAnalysisMmsi) setTrackCoords(null);
  }, [selectedAnalysisMmsi]);

  const handleAnalysisShipSelect = useCallback((mmsi: string) => {
    setSelectedAnalysisMmsi(mmsi);
    const ship = (allShips ?? ships).find(s => s.mmsi === mmsi);
    if (ship) setFlyToTarget({ lng: ship.lng, lat: ship.lat, zoom: 12 });
  }, [allShips, ships]);

  const handleTrackLoad = useCallback((_mmsi: string, coords: [number, number][]) => {
    setTrackCoords(coords);
  }, []);

  const handleFleetZoom = useCallback((bounds: { minLat: number; maxLat: number; minLng: number; maxLng: number }) => {
    mapRef.current?.fitBounds(
      [[bounds.minLng, bounds.minLat], [bounds.maxLng, bounds.maxLat]],
      { padding: 60, duration: 1500 },
    );
  }, []);

  // 줌 레벨별 아이콘/심볼 스케일 배율 — z4=1.0x 기준, 2단계씩 상향
  // 줌 레벨별 아이콘/심볼 스케일 배율 — z4=0.8x, z6=1.0x 시작, 2단계씩 상향
  const zoomScale = useMemo(() => {
    if (zoomLevel <= 4) return 0.8;
    if (zoomLevel <= 5) return 0.9;
    if (zoomLevel <= 6) return 1.0;
    if (zoomLevel <= 7) return 1.2;
    if (zoomLevel <= 8) return 1.5;
    if (zoomLevel <= 9) return 1.8;
    if (zoomLevel <= 10) return 2.2;
    if (zoomLevel <= 11) return 2.5;
    if (zoomLevel <= 12) return 2.8;
    if (zoomLevel <= 13) return 3.5;
    return 4.2;
  }, [zoomLevel]);

  // 불법어선 강조 — deck.gl ScatterplotLayer + TextLayer
  const illegalFishingData = useMemo(() => {
    if (!koreaFilters.illegalFishing) return [];
    return (allShips ?? ships).filter(s => {
      const mtCat = getMarineTrafficCategory(s.typecode, s.category);
      if (mtCat !== 'fishing' || s.flag === 'KR') return false;
      return classifyFishingZone(s.lat, s.lng).zone !== 'OUTSIDE';
    }).slice(0, 200);
  }, [koreaFilters.illegalFishing, allShips, ships]);

  const illegalFishingLayer = useMemo(() => new ScatterplotLayer({
    id: 'illegal-fishing-highlight',
    data: illegalFishingData,
    getPosition: (d) => [d.lng, d.lat],
    getRadius: 800 * zoomScale,
    getFillColor: [239, 68, 68, 40],
    getLineColor: [239, 68, 68, 200],
    getLineWidth: 2,
    stroked: true,
    filled: true,
    radiusUnits: 'meters',
    lineWidthUnits: 'pixels',
  }), [illegalFishingData, zoomScale]);

  const illegalFishingLabelLayer = useMemo(() => new TextLayer({
    id: 'illegal-fishing-labels',
    data: illegalFishingData,
    getPosition: (d) => [d.lng, d.lat],
    getText: (d) => d.name || d.mmsi,
    getSize: 10 * zoomScale,
    getColor: [239, 68, 68, 255],
    getTextAnchor: 'middle',
    getAlignmentBaseline: 'top',
    getPixelOffset: [0, 14],
    fontFamily: 'monospace',
    outlineWidth: 2,
    outlineColor: [0, 0, 0, 200],
    billboard: false,
    characterSet: 'auto',
  }), [illegalFishingData, zoomScale]);

  // 수역 라벨 TextLayer — illegalFishing 필터 활성 시만 표시
  const zoneLabelsLayer = useMemo(() => {
    if (!koreaFilters.illegalFishing) return null;
    const data = (fishingZonesData as GeoJSON.FeatureCollection).features.map(f => {
      const geom = f.geometry as GeoJSON.MultiPolygon;
      let sLng = 0, sLat = 0, n = 0;
      for (const poly of geom.coordinates) {
        for (const ring of poly) {
          for (const [lng, lat] of ring) {
            sLng += lng; sLat += lat; n++;
          }
        }
      }
      return {
        name: (f.properties as { name: string }).name,
        lng: n > 0 ? sLng / n : 0,
        lat: n > 0 ? sLat / n : 0,
      };
    });
    return new TextLayer({
      id: 'fishing-zone-labels',
      data,
      getPosition: (d: { lng: number; lat: number }) => [d.lng, d.lat],
      getText: (d: { name: string }) => d.name,
      getSize: 12 * zoomScale,
      getColor: [255, 255, 255, 220],
      getTextAnchor: 'middle',
      getAlignmentBaseline: 'center',
      fontFamily: 'monospace',
      fontWeight: 700,
      outlineWidth: 3,
      outlineColor: [0, 0, 0, 200],
      billboard: false,
      characterSet: 'auto',
    });
  }, [koreaFilters.illegalFishing, zoomScale]);

  // 정적 레이어 (deck.gl) — 항구, 공항, 군사기지, 어항경고 등
  const staticDeckLayers = useStaticDeckLayers({
    ports: layers.ports ?? false,
    coastGuard: layers.coastGuard ?? false,
    windFarm: layers.windFarm ?? false,
    militaryBases: layers.militaryBases ?? false,
    govBuildings: layers.govBuildings ?? false,
    airports: layers.airports ?? false,
    navWarning: layers.navWarning ?? false,
    nkLaunch: layers.nkLaunch ?? false,
    nkMissile: layers.nkMissile ?? false,
    piracy: layers.piracy ?? false,
    infra: layers.infra ?? false,
    infraFacilities: infra,
    hazardTypes: [
      ...(layers.hazardPetrochemical ? ['petrochemical' as const] : []),
      ...(layers.hazardLng ? ['lng' as const] : []),
      ...(layers.hazardOilTank ? ['oilTank' as const] : []),
      ...(layers.hazardPort ? ['hazardPort' as const] : []),
      ...(layers.energyNuclear ? ['nuclear' as const] : []),
      ...(layers.energyThermal ? ['thermal' as const] : []),
      ...(layers.industryShipyard ? ['shipyard' as const] : []),
      ...(layers.industryWastewater ? ['wastewater' as const] : []),
      ...(layers.industryHeavy ? ['heavyIndustry' as const] : []),
    ],
    cnPower: !!layers.cnPower,
    cnMilitary: !!layers.cnMilitary,
    jpPower: !!layers.jpPower,
    jpMilitary: !!layers.jpMilitary,
    onPick: (info) => setStaticPickInfo(info),
    sizeScale: zoomScale,
  });

  // 선택된 어구 그룹 — 어구 아이콘 + 모선 강조 (deck.gl)
  const selectedGearLayers = useMemo(() => {
    if (!selectedGearData) return [];
    const { parent, gears, groupName } = selectedGearData;
    const layers = [];

    // 어구 위치 — 주황 원형 마커
    layers.push(new ScatterplotLayer({
      id: 'selected-gear-items',
      data: gears,
      getPosition: (d: Ship) => [d.lng, d.lat],
      getRadius: 6 * zoomScale,
      getFillColor: [249, 115, 22, 180],
      getLineColor: [255, 255, 255, 220],
      stroked: true,
      filled: true,
      radiusUnits: 'pixels',
      lineWidthUnits: 'pixels',
      getLineWidth: 1.5,
    }));

    // 어구 이름 라벨
    layers.push(new TextLayer({
      id: 'selected-gear-labels',
      data: gears,
      getPosition: (d: Ship) => [d.lng, d.lat],
      getText: (d: Ship) => d.name || d.mmsi,
      getSize: 9 * zoomScale,
      getColor: [249, 115, 22, 255],
      getTextAnchor: 'middle' as const,
      getAlignmentBaseline: 'top' as const,
      getPixelOffset: [0, 10],
      fontFamily: 'monospace',
      outlineWidth: 2,
      outlineColor: [0, 0, 0, 220],
      billboard: false,
      characterSet: 'auto',
    }));

    // 모선 강조 — 큰 원 + 라벨
    if (parent) {
      layers.push(new ScatterplotLayer({
        id: 'selected-gear-parent',
        data: [parent],
        getPosition: (d: Ship) => [d.lng, d.lat],
        getRadius: 14 * zoomScale,
        getFillColor: [249, 115, 22, 80],
        getLineColor: [249, 115, 22, 255],
        stroked: true,
        filled: true,
        radiusUnits: 'pixels',
        lineWidthUnits: 'pixels',
        getLineWidth: 3,
      }));
      layers.push(new TextLayer({
        id: 'selected-gear-parent-label',
        data: [parent],
        getPosition: (d: Ship) => [d.lng, d.lat],
        getText: (d: Ship) => `▼ ${d.name || groupName} (모선)`,
        getSize: 11 * zoomScale,
        getColor: [249, 115, 22, 255],
        getTextAnchor: 'middle' as const,
        getAlignmentBaseline: 'top' as const,
        getPixelOffset: [0, 18],
        fontFamily: 'monospace',
        fontWeight: 700,
        outlineWidth: 3,
        outlineColor: [0, 0, 0, 220],
        billboard: false,
        characterSet: 'auto',
      }));
    }

    return layers;
  }, [selectedGearData, zoomScale]);

  // 선택된 선단 소속 선박 강조 레이어 (deck.gl)
  const selectedFleetLayers = useMemo(() => {
    if (!selectedFleetData) return [];
    const { ships: fleetShips, clusterId } = selectedFleetData;
    if (fleetShips.length === 0) return [];

    // HSL→RGB 인라인 변환 (선단 색상)
    const hue = (clusterId * 137) % 360;
    const h = hue / 360; const s = 0.7; const l = 0.6;
    const hue2rgb = (p: number, q: number, t: number) => { if (t < 0) t += 1; if (t > 1) t -= 1; return t < 1/6 ? p + (q-p)*6*t : t < 1/2 ? q : t < 2/3 ? p + (q-p)*(2/3-t)*6 : p; };
    const q = l < 0.5 ? l * (1+s) : l + s - l*s; const p = 2*l - q;
    const r = Math.round(hue2rgb(p, q, h + 1/3) * 255);
    const g = Math.round(hue2rgb(p, q, h) * 255);
    const b = Math.round(hue2rgb(p, q, h - 1/3) * 255);
    const color: [number, number, number, number] = [r, g, b, 255];
    const fillColor: [number, number, number, number] = [r, g, b, 80];

    const result: Layer[] = [];

    // 소속 선박 — 강조 원형
    result.push(new ScatterplotLayer({
      id: 'selected-fleet-items',
      data: fleetShips,
      getPosition: (d: Ship) => [d.lng, d.lat],
      getRadius: 8 * zoomScale,
      getFillColor: fillColor,
      getLineColor: color,
      stroked: true,
      filled: true,
      radiusUnits: 'pixels',
      lineWidthUnits: 'pixels',
      getLineWidth: 2,
    }));

    // 소속 선박 이름 라벨
    result.push(new TextLayer({
      id: 'selected-fleet-labels',
      data: fleetShips,
      getPosition: (d: Ship) => [d.lng, d.lat],
      getText: (d: Ship) => {
        const dto = vesselAnalysis?.analysisMap.get(d.mmsi);
        const role = dto?.algorithms.fleetRole.role;
        const prefix = role === 'LEADER' ? '★ ' : '';
        return `${prefix}${d.name || d.mmsi}`;
      },
      getSize: 9 * zoomScale,
      getColor: color,
      getTextAnchor: 'middle' as const,
      getAlignmentBaseline: 'top' as const,
      getPixelOffset: [0, 12],
      fontFamily: 'monospace',
      fontWeight: 600,
      outlineWidth: 2,
      outlineColor: [0, 0, 0, 220],
      billboard: false,
      characterSet: 'auto',
    }));

    // 리더 선박 추가 강조 (큰 외곽 링)
    const leaders = fleetShips.filter(s => {
      const dto = vesselAnalysis?.analysisMap.get(s.mmsi);
      return dto?.algorithms.fleetRole.isLeader;
    });
    if (leaders.length > 0) {
      result.push(new ScatterplotLayer({
        id: 'selected-fleet-leaders',
        data: leaders,
        getPosition: (d: Ship) => [d.lng, d.lat],
        getRadius: 16 * zoomScale,
        getFillColor: [0, 0, 0, 0],
        getLineColor: color,
        stroked: true,
        filled: false,
        radiusUnits: 'pixels',
        lineWidthUnits: 'pixels',
        getLineWidth: 3,
      }));
    }

    return result;
  }, [selectedFleetData, zoomScale, vesselAnalysis]);

  // 분석 결과 deck.gl 레이어
  const analysisActiveFilter = koreaFilters.illegalFishing ? 'illegalFishing'
    : koreaFilters.darkVessel ? 'darkVessel'
    : layers.cnFishing ? 'cnFishing'
    : null;

  const analysisDeckLayers = useAnalysisDeckLayers(
    vesselAnalysis?.analysisMap ?? new Map(),
    allShips ?? ships,
    analysisActiveFilter,
    zoomScale,
  );

  return (
    <Map
      ref={mapRef}
      initialViewState={{ ...KOREA_MAP_CENTER, zoom: KOREA_MAP_ZOOM }}
      style={{ width: '100%', height: '100%' }}
      mapStyle={MAP_STYLE}
      onZoom={e => setZoomLevel(Math.floor(e.viewState.zoom))}
    >
      <NavigationControl position="top-right" />

      <Source id="country-labels" type="geojson" data={countryLabelsGeoJSON()}>
        <Layer
          id="country-label-lg"
          type="symbol"
          filter={['==', ['get', 'rank'], 1]}
          layout={{
            'text-field': ['get', 'name'],
            'text-size': 15,
            'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
            'text-allow-overlap': false,
            'text-ignore-placement': false,
            'text-padding': 6,
          }}
          paint={{
            'text-color': '#e2e8f0',
            'text-halo-color': '#000000',
            'text-halo-width': 2,
            'text-opacity': 0.9,
          }}
        />
        <Layer
          id="country-label-md"
          type="symbol"
          filter={['==', ['get', 'rank'], 2]}
          layout={{
            'text-field': ['get', 'name'],
            'text-size': 12,
            'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
            'text-allow-overlap': false,
            'text-ignore-placement': false,
            'text-padding': 4,
          }}
          paint={{
            'text-color': '#94a3b8',
            'text-halo-color': '#000000',
            'text-halo-width': 1.5,
            'text-opacity': 0.85,
          }}
        />
        <Layer
          id="country-label-sm"
          type="symbol"
          filter={['==', ['get', 'rank'], 3]}
          minzoom={5}
          layout={{
            'text-field': ['get', 'name'],
            'text-size': 10,
            'text-font': ['Open Sans Regular', 'Arial Unicode MS Regular'],
            'text-allow-overlap': false,
            'text-ignore-placement': false,
            'text-padding': 2,
          }}
          paint={{
            'text-color': '#64748b',
            'text-halo-color': '#000000',
            'text-halo-width': 1,
            'text-opacity': 0.75,
          }}
        />
      </Source>

      {layers.ships && <ShipLayer ships={ships} militaryOnly={layers.militaryOnly} analysisMap={vesselAnalysis?.analysisMap} />}
      {/* Transship suspect labels — Marker DOM, inline styles kept for dynamic border color */}
      {transshipSuspects.size > 0 && ships.filter(s => transshipSuspects.has(s.mmsi)).map(s => (
        <Marker key={`ts-${s.mmsi}`} longitude={s.lng} latitude={s.lat} anchor="bottom">
          <div
            className="rounded-sm text-[9px] font-bold font-mono whitespace-nowrap animate-pulse"
            style={{
              background: 'rgba(249,115,22,0.9)', color: '#fff',
              padding: '1px 5px',
              border: '1px solid #f97316',
              textShadow: '0 0 2px #000',
            }}
          >
            {`\u26A0 ${t('korea.transshipSuspect')}`}
          </div>
        </Marker>
      ))}
      {/* Cable watch suspect labels */}
      {cableWatchSuspects.size > 0 && ships.filter(s => cableWatchSuspects.has(s.mmsi)).map(s => (
        <Marker key={`cw-${s.mmsi}`} longitude={s.lng} latitude={s.lat} anchor="bottom">
          <div
            className="rounded-sm text-[9px] font-bold font-mono whitespace-nowrap animate-pulse"
            style={{
              background: 'rgba(0,229,255,0.9)', color: '#000',
              padding: '1px 5px',
              border: '1px solid #00e5ff',
              textShadow: '0 0 2px rgba(255,255,255,0.5)',
            }}
          >
            {`\u{1F50C} ${t('korea.cableDanger')}`}
          </div>
        </Marker>
      ))}
      {/* Dokdo watch labels (Japanese vessels) */}
      {dokdoWatchSuspects.size > 0 && ships.filter(s => dokdoWatchSuspects.has(s.mmsi)).map(s => {
        const dist = Math.round(Math.hypot(
          (s.lng - 131.8647) * Math.cos((37.2417 * Math.PI) / 180),
          s.lat - 37.2417,
        ) * 111);
        const inTerritorial = dist < 22;
        return (
          <Marker key={`dk-${s.mmsi}`} longitude={s.lng} latitude={s.lat} anchor="bottom">
            <div
              className="rounded-sm text-[9px] font-bold font-mono whitespace-nowrap animate-pulse"
              style={{
                background: inTerritorial ? 'rgba(239,68,68,0.95)' : 'rgba(234,179,8,0.9)',
                color: '#fff',
                padding: '2px 6px',
                border: `1px solid ${inTerritorial ? '#ef4444' : '#eab308'}`,
                textShadow: '0 0 2px #000',
              }}
            >
              {inTerritorial ? '\u{1F6A8}' : '\u26A0'} {'\u{1F1EF}\u{1F1F5}'} {inTerritorial ? t('korea.dokdoIntrusion') : t('korea.dokdoApproach')} {`${dist}km`}
            </div>
          </Marker>
        );
      })}
      {layers.infra && infra.length > 0 && <InfraLayer facilities={infra} />}
      {layers.satellites && satellites.length > 0 && <SatelliteLayer satellites={satellites} />}
      {layers.aircraft && aircraft.length > 0 && <AircraftLayer aircraft={aircraft} militaryOnly={layers.militaryOnly} />}
      {layers.cables && <SubmarineCableLayer />}
      {layers.cctv && <CctvLayer />}
      {/* 정적 레이어들은 deck.gl DeckGLOverlay로 전환됨 — 아래 DOM 레이어 제거 */}
      {(koreaFilters.illegalFishing || layers.cnFishing) && <FishingZoneLayer />}
      {layers.cnFishing && <ChineseFishingOverlay ships={ships} analysisMap={vesselAnalysis?.analysisMap} />}
      {/* HazardFacility, CnFacility, JpFacility → useStaticDeckLayers (deck.gl GPU) 전환 완료 */}
      {layers.cnFishing && (
        <FleetClusterLayer
          ships={allShips ?? ships}
          analysisMap={vesselAnalysis ? vesselAnalysis.analysisMap : undefined}
          clusters={vesselAnalysis ? vesselAnalysis.clusters : undefined}
          onShipSelect={handleAnalysisShipSelect}
          onFleetZoom={handleFleetZoom}
          onSelectedGearChange={setSelectedGearData}
          onSelectedFleetChange={setSelectedFleetData}
        />
      )}
      {vesselAnalysis && vesselAnalysis.analysisMap.size > 0 && (
        <AnalysisOverlay
          ships={allShips ?? ships}
          analysisMap={vesselAnalysis.analysisMap}
          clusters={vesselAnalysis.clusters}
          activeFilter={analysisActiveFilter}
        />
      )}

      {/* deck.gl GPU 오버레이 — 불법어선 강조 + 분석 위험도 마커 */}
      <DeckGLOverlay layers={[
        ...staticDeckLayers,
        illegalFishingLayer,
        illegalFishingLabelLayer,
        zoneLabelsLayer,
        ...selectedGearLayers,
        ...selectedFleetLayers,
        ...(analysisPanelOpen ? analysisDeckLayers : []),
      ].filter(Boolean)} />
      {/* 정적 마커 클릭 Popup — 통합 리치 디자인 */}
      {staticPickInfo && (() => {
        const obj = staticPickInfo.object;
        const kind = staticPickInfo.kind;
        const lat = obj.lat ?? obj.launchLat ?? 0;
        const lng = obj.lng ?? obj.launchLng ?? 0;
        if (!lat || !lng) return null;

        // ── kind + subType 기반 메타 결정 ──
        const SUB_META: Record<string, Record<string, { icon: string; color: string; label: string }>> = {
          hazard: {
            petrochemical: { icon: '🏭', color: '#f97316', label: '석유화학단지' },
            lng:           { icon: '🔵', color: '#06b6d4', label: 'LNG저장기지' },
            oilTank:       { icon: '🛢️', color: '#eab308', label: '유류저장탱크' },
            hazardPort:    { icon: '⚠️', color: '#ef4444', label: '위험물항만하역' },
            nuclear:       { icon: '☢️', color: '#a855f7', label: '원자력발전소' },
            thermal:       { icon: '🔥', color: '#64748b', label: '화력발전소' },
            shipyard:      { icon: '🚢', color: '#0ea5e9', label: '조선소' },
            wastewater:    { icon: '💧', color: '#10b981', label: '폐수처리장' },
            heavyIndustry: { icon: '⚙️', color: '#94a3b8', label: '시멘트/제철소' },
          },
          overseas: {
            nuclear: { icon: '☢️', color: '#ef4444', label: '핵발전소' },
            thermal: { icon: '🔥', color: '#f97316', label: '화력발전소' },
            naval:   { icon: '⚓', color: '#3b82f6', label: '해군기지' },
            airbase: { icon: '✈️', color: '#22d3ee', label: '공군기지' },
            army:    { icon: '🪖', color: '#22c55e', label: '육군기지' },
            shipyard:{ icon: '🚢', color: '#94a3b8', label: '조선소' },
          },
          militaryBase: {
            naval:   { icon: '⚓', color: '#3b82f6', label: '해군기지' },
            airforce:{ icon: '✈️', color: '#22d3ee', label: '공군기지' },
            army:    { icon: '🪖', color: '#22c55e', label: '육군기지' },
            missile: { icon: '🚀', color: '#ef4444', label: '미사일기지' },
            joint:   { icon: '⭐', color: '#f59e0b', label: '합동사령부' },
          },
          govBuilding: {
            executive:    { icon: '🏛️', color: '#f59e0b', label: '행정부' },
            legislature:  { icon: '🏛️', color: '#3b82f6', label: '입법부' },
            military_hq:  { icon: '⭐', color: '#ef4444', label: '군사령부' },
            intelligence: { icon: '🔍', color: '#8b5cf6', label: '정보기관' },
            foreign:      { icon: '🌐', color: '#06b6d4', label: '외교부' },
            maritime:     { icon: '⚓', color: '#0ea5e9', label: '해양기관' },
            defense:      { icon: '🛡️', color: '#dc2626', label: '국방부' },
          },
          nkLaunch: {
            icbm:      { icon: '🚀', color: '#dc2626', label: 'ICBM 발사장' },
            irbm:      { icon: '🚀', color: '#ef4444', label: 'IRBM/MRBM' },
            srbm:      { icon: '🎯', color: '#f97316', label: '단거리탄도미사일' },
            slbm:      { icon: '🔱', color: '#3b82f6', label: 'SLBM 발사' },
            cruise:    { icon: '✈️', color: '#8b5cf6', label: '순항미사일' },
            artillery: { icon: '💥', color: '#eab308', label: '해안포/장사정포' },
            mlrs:      { icon: '💥', color: '#f59e0b', label: '방사포(MLRS)' },
          },
          coastGuard: {
            hq:         { icon: '🏢', color: '#3b82f6', label: '본청' },
            regional:   { icon: '🏢', color: '#60a5fa', label: '지방청' },
            station:    { icon: '🚔', color: '#22d3ee', label: '해양경찰서' },
            substation: { icon: '🏠', color: '#94a3b8', label: '파출소' },
            vts:        { icon: '📡', color: '#f59e0b', label: 'VTS센터' },
            navy:       { icon: '⚓', color: '#3b82f6', label: '해군부대' },
          },
          airport: {
            international: { icon: '✈️', color: '#a78bfa', label: '국제공항' },
            domestic:      { icon: '🛩️', color: '#60a5fa', label: '국내공항' },
            military:      { icon: '✈️', color: '#ef4444', label: '군용비행장' },
          },
          navWarning: {
            danger:  { icon: '⚠️', color: '#ef4444', label: '위험' },
            caution: { icon: '⚠️', color: '#eab308', label: '주의' },
            info:    { icon: 'ℹ️', color: '#3b82f6', label: '정보' },
          },
          piracy: {
            critical: { icon: '☠️', color: '#ef4444', label: '극고위험' },
            high:     { icon: '☠️', color: '#f97316', label: '고위험' },
            moderate: { icon: '☠️', color: '#eab308', label: '주의' },
          },
        };

        const KIND_DEFAULT: Record<string, { icon: string; color: string; label: string }> = {
          port:         { icon: '⚓', color: '#3b82f6', label: '항구' },
          windFarm:     { icon: '🌀', color: '#00bcd4', label: '풍력단지' },
          militaryBase: { icon: '🪖', color: '#ef4444', label: '군사시설' },
          govBuilding:  { icon: '🏛️', color: '#f59e0b', label: '정부기관' },
          nkLaunch:     { icon: '🚀', color: '#dc2626', label: '북한 발사장' },
          nkMissile:    { icon: '💣', color: '#ef4444', label: '미사일 낙하' },
          coastGuard:   { icon: '🚔', color: '#4dabf7', label: '해양경찰' },
          airport:      { icon: '✈️', color: '#a78bfa', label: '공항' },
          navWarning:   { icon: '⚠️', color: '#eab308', label: '항행경보' },
          piracy:       { icon: '☠️', color: '#ef4444', label: '해적위험' },
          infra:        { icon: '⚡', color: '#ffeb3b', label: '발전/변전' },
          hazard:       { icon: '⚠️', color: '#ef4444', label: '위험시설' },
          cnFacility:   { icon: '📍', color: '#ef4444', label: '중국시설' },
          jpFacility:   { icon: '📍', color: '#f472b6', label: '일본시설' },
        };

        // subType 키 결정
        const subKey = obj.type ?? obj.subType ?? obj.level ?? '';
        const subGroup = kind === 'cnFacility' || kind === 'jpFacility' ? 'overseas' : kind;
        const meta = SUB_META[subGroup]?.[subKey] ?? KIND_DEFAULT[kind] ?? { icon: '📍', color: '#64748b', label: kind };

        // 국가 플래그
        const COUNTRY_FLAG: Record<string, string> = { CN: '🇨🇳', JP: '🇯🇵', KP: '🇰🇵', KR: '🇰🇷', TW: '🇹🇼' };
        const flag = kind === 'cnFacility' ? '🇨🇳' : kind === 'jpFacility' ? '🇯🇵' : COUNTRY_FLAG[obj.country] ?? '';
        const countryName = kind === 'cnFacility' ? '중국' : kind === 'jpFacility' ? '일본'
          : { CN: '중국', JP: '일본', KP: '북한', KR: '한국', TW: '대만' }[obj.country] ?? '';

        // 이름 결정
        const title = obj.nameKo || obj.name || obj.launchNameKo || obj.title || kind;

        return (
          <Popup longitude={lng} latitude={lat} anchor="bottom"
            onClose={() => setStaticPickInfo(null)} closeOnClick={false}
            maxWidth="280px" className="gl-popup"
          >
            <div className="popup-body-sm" style={{ minWidth: 200 }}>
              {/* 컬러 헤더 */}
              <div className="popup-header" style={{ background: meta.color, color: '#000', gap: 6, padding: '4px 8px' }}>
                <span>{meta.icon}</span> {title}
              </div>
              {/* 배지 행 */}
              <div style={{ display: 'flex', gap: 4, marginBottom: 6, flexWrap: 'wrap' }}>
                <span style={{
                  background: meta.color, color: '#000',
                  padding: '1px 6px', borderRadius: 3, fontSize: 10, fontWeight: 700,
                }}>
                  {meta.label}
                </span>
                {flag && (
                  <span style={{ background: '#333', color: '#ccc', padding: '1px 6px', borderRadius: 3, fontSize: 10 }}>
                    {flag} {countryName}
                  </span>
                )}
                {kind === 'hazard' && (
                  <span style={{
                    background: 'rgba(239,68,68,0.15)', color: '#ef4444',
                    padding: '1px 6px', borderRadius: 3, fontSize: 10, fontWeight: 600,
                    border: '1px solid rgba(239,68,68,0.3)',
                  }}>⚠️ 위험시설</span>
                )}
                {kind === 'port' && (
                  <span style={{ background: '#333', color: '#ccc', padding: '1px 6px', borderRadius: 3, fontSize: 10 }}>
                    {obj.type === 'major' ? '주요항' : '중소항'}
                  </span>
                )}
                {kind === 'airport' && obj.intl && (
                  <span style={{ background: '#333', color: '#ccc', padding: '1px 6px', borderRadius: 3, fontSize: 10 }}>국제선</span>
                )}
              </div>
              {/* 설명 */}
              {obj.description && (
                <div style={{ fontSize: 10, color: '#999', marginBottom: 4, lineHeight: 1.5 }}>{obj.description}</div>
              )}
              {obj.detail && (
                <div style={{ fontSize: 10, color: '#888', marginBottom: 4, lineHeight: 1.4 }}>{obj.detail}</div>
              )}
              {obj.note && (
                <div style={{ fontSize: 10, color: '#888', marginBottom: 4, lineHeight: 1.4 }}>{obj.note}</div>
              )}
              {/* 필드 그리드 */}
              <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                {obj.operator && <div><span className="popup-label">운영: </span>{obj.operator}</div>}
                {obj.capacity && <div><span className="popup-label">규모: </span><strong>{obj.capacity}</strong></div>}
                {obj.output && <div><span className="popup-label">출력: </span><strong>{obj.output}</strong></div>}
                {obj.source && <div><span className="popup-label">연료: </span>{obj.source}</div>}
                {obj.capacityMW && <div><span className="popup-label">용량: </span><strong>{obj.capacityMW}MW</strong></div>}
                {obj.turbines && <div><span className="popup-label">터빈: </span>{obj.turbines}기</div>}
                {obj.status && <div><span className="popup-label">상태: </span>{obj.status}</div>}
                {obj.year && <div><span className="popup-label">연도: </span>{obj.year}년</div>}
                {obj.region && <div><span className="popup-label">지역: </span>{obj.region}</div>}
                {obj.org && <div><span className="popup-label">기관: </span>{obj.org}</div>}
                {obj.area && <div><span className="popup-label">해역: </span>{obj.area}</div>}
                {obj.altitude && <div><span className="popup-label">고도: </span>{obj.altitude}</div>}
                {obj.address && <div><span className="popup-label">주소: </span>{obj.address}</div>}
                {obj.recentUse && <div><span className="popup-label">최근 사용: </span>{obj.recentUse}</div>}
                {obj.recentIncidents != null && <div><span className="popup-label">최근 1년: </span><strong>{obj.recentIncidents}건</strong></div>}
                {obj.icao && <div><span className="popup-label">ICAO: </span>{obj.icao}</div>}
                {kind === 'nkMissile' && (
                  <>
                    {obj.typeKo && <div><span className="popup-label">미사일: </span>{obj.typeKo}</div>}
                    {obj.date && <div><span className="popup-label">발사일: </span>{obj.date} {obj.time}</div>}
                    {obj.distanceKm && <div><span className="popup-label">사거리: </span>{obj.distanceKm}km</div>}
                    {obj.altitudeKm && <div><span className="popup-label">최고고도: </span>{obj.altitudeKm}km</div>}
                    {obj.flightMin && <div><span className="popup-label">비행시간: </span>{obj.flightMin}분</div>}
                    {obj.launchNameKo && <div><span className="popup-label">발사지: </span>{obj.launchNameKo}</div>}
                  </>
                )}
                {obj.name && obj.nameKo && obj.name !== obj.nameKo && (
                  <div><span className="popup-label">영문: </span>{obj.name}</div>
                )}
                <div style={{ fontSize: 9, color: '#666', marginTop: 2 }}>
                  {lat.toFixed(4)}°N, {lng.toFixed(4)}°E
                </div>
              </div>
            </div>
          </Popup>
        );
      })()}
      {layers.osint && <OsintMapLayer osintFeed={osintFeed} currentTime={currentTime} />}
      {layers.eez && <EezLayer />}

      {/* Filter Status Banner */}
      {(() => {
        const active = (Object.keys(koreaFilters) as (keyof KoreaFiltersState)[]).filter(k => koreaFilters[k]);
        if (active.length === 0) return null;
        return (
          <div className="absolute top-2.5 left-1/2 -translate-x-1/2 z-20 flex gap-1.5 backdrop-blur-lg">
            {active.map(k => {
              const color = FILTER_COLOR[k];
              return (
                <div
                  key={k}
                  className="rounded-lg px-3 py-1.5 font-mono text-[11px] font-bold flex items-center gap-1.5 animate-pulse"
                  style={{
                    background: `${color}22`, border: `1px solid ${color}88`,
                    color,
                  }}
                >
                  <span className="text-[13px]">{FILTER_ICON[k]}</span>
                  {t(FILTER_I18N_KEY[k])}
                </div>
              );
            })}
            <div className="rounded-lg px-3 py-1.5 font-mono text-xs font-bold flex items-center bg-kcg-glass border border-kcg-border-light text-white">
              {t('korea.detected', { count: ships.length })}
            </div>
          </div>
        );
      })()}

      {/* Dokdo alert panel */}
      {dokdoAlerts.length > 0 && koreaFilters.dokdoWatch && (
        <div className="absolute top-2.5 right-[50px] z-20 rounded-lg border border-kcg-danger px-2.5 py-2 font-mono text-[11px] min-w-[220px] max-h-[200px] overflow-y-auto bg-kcg-overlay backdrop-blur-lg shadow-[0_0_20px_rgba(239,68,68,0.3)]">
          <div className="font-bold text-[10px] text-kcg-danger mb-1.5 tracking-widest flex items-center gap-1">
            {`\u{1F6A8} ${t('korea.dokdoAlerts')}`}
          </div>
          {dokdoAlerts.map((a, i) => (
            <div key={`${a.mmsi}-${i}`} className="flex flex-col gap-0.5" style={{
              padding: '4px 0', borderBottom: i < dokdoAlerts.length - 1 ? '1px solid #222' : 'none',
            }}>
              <div className="flex justify-between items-center">
                <span className="font-bold text-[10px]" style={{ color: a.dist < 22 ? '#ef4444' : '#eab308' }}>
                  {a.dist < 22 ? `\u{1F6A8} ${t('korea.territorialIntrusion')}` : `\u26A0 ${t('korea.approachWarning')}`}
                </span>
                <span className="text-kcg-dim text-[9px]">
                  {new Date(a.time).toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
                </span>
              </div>
              <div className="text-kcg-text-secondary text-[10px]">
                {`\u{1F1EF}\u{1F1F5} ${a.name} \u2014 ${t('korea.dokdoDistance', { dist: a.dist })}`}
              </div>
            </div>
          ))}
        </div>
      )}

      {/* 선택된 분석 선박 항적 — tracks API 응답 기반 */}
      {trackCoords && trackCoords.length > 1 && (
        <Source id="analysis-trail" type="geojson" data={{
          type: 'FeatureCollection',
          features: [{
            type: 'Feature',
            properties: {},
            geometry: {
              type: 'LineString',
              coordinates: trackCoords,
            },
          }],
        }}>
          <Layer id="analysis-trail-line" type="line" paint={{
            'line-color': '#00e5ff',
            'line-width': 2.5,
            'line-opacity': 0.8,
          }} />
        </Source>
      )}

      {/* AI Analysis Stats Panel — 항상 표시 */}
      {vesselAnalysis && (
        <AnalysisStatsPanel
          stats={vesselAnalysis.stats}
          lastUpdated={vesselAnalysis.lastUpdated}
          isLoading={vesselAnalysis.isLoading}
          analysisMap={vesselAnalysis.analysisMap}
          ships={allShips ?? ships}
          allShips={allShips ?? ships}
          onShipSelect={handleAnalysisShipSelect}
          onTrackLoad={handleTrackLoad}
          onExpandedChange={setAnalysisPanelOpen}
        />
      )}
    </Map>
  );
}
