import { useMemo, useEffect, useRef, useCallback } from 'react'
import Map, { Source, Layer } from 'react-map-gl'
import type { MapRef } from 'react-map-gl'
import type { Map as MapboxMap } from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'
import { useReplaySituation } from '@/hooks/useReplaySituation'
import { config } from '@/config'
import {
  ATTACKED_TARGETS,
  ALLIED_STRIKE_LOCATIONS,
  LINCOLN_COORDS,
  LINCOLN_STRIKE_TARGETS,
  FORD_COORDS,
  FORD_STRIKE_TARGETS,
  ISRAEL_STRIKE_SOURCE,
  ISRAEL_STRIKE_TARGETS,
} from '@/data/mapLocations'

const MAPBOX_TOKEN = config.mapboxAccessToken || ''

// 相关区域 bbox：伊朗、以色列、胡塞区 (minLng, minLat, maxLng, maxLat)，覆盖红蓝区域
const THEATER_BBOX = [22, 11, 64, 41] as const
/** 移动端/小屏时 fitBounds 使区域完整显示 */
const THEATER_BOUNDS: [[number, number], [number, number]] = [
  [THEATER_BBOX[0], THEATER_BBOX[1]],
  [THEATER_BBOX[2], THEATER_BBOX[3]],
]
const THEATER_CENTER = {
  longitude: (THEATER_BBOX[0] + THEATER_BBOX[2]) / 2,
  latitude: (THEATER_BBOX[1] + THEATER_BBOX[3]) / 2,
}
const DEFAULT_VIEW = { ...THEATER_CENTER, zoom: 4.2 }

const COUNTRIES_GEOJSON =
  'https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_admin_0_countries.geojson'

// 胡塞武装失控区 [lng, lat] 闭环
const HOUTHI_POLYGON: [number, number][] = [
  [42.7, 15.8],
  [43.3, 16.5],
  [45.1, 17.2],
  [45.8, 15.1],
  [44.2, 13.5],
  [42.7, 15.8],
]

const IRAN_ADMIN = 'Iran'
const ALLIES_ADMIN = [
  'Qatar',
  'Bahrain',
  'Kuwait',
  'United Arab Emirates',
  'Saudi Arabia',
  'Iraq',
  'Syria',
  'Jordan',
  'Turkey',
  'Israel',
  'Oman',
  'Egypt',
  'Djibouti',
]

// 伊朗攻击源 德黑兰 [lng, lat]
const TEHRAN_SOURCE: [number, number] = [51.389, 35.6892]

/** 二次贝塞尔曲线路径，更平滑的弧线 height 控制弧高 */
function parabolaPath(
  start: [number, number],
  end: [number, number],
  height = 3
): [number, number][] {
  const ctrl: [number, number] = [
    (start[0] + end[0]) / 2,
    (start[1] + end[1]) / 2 + height,
  ]
  // 生成多段点使曲线更平滑
  const pts: [number, number][] = [start]
  for (let i = 1; i < 12; i++) {
    const s = i / 12
    const t = 1 - s
    const x = t * t * start[0] + 2 * t * s * ctrl[0] + s * s * end[0]
    const y = t * t * start[1] + 2 * t * s * ctrl[1] + s * s * end[1]
    pts.push([x, y])
  }
  pts.push(end)
  return pts
}

/** 沿路径插值，t ∈ [0,1]，支持多点路径 */
function interpolateOnPath(path: [number, number][], t: number): [number, number] {
  if (t <= 0) return path[0]
  if (t >= 1) return path[path.length - 1]
  const n = path.length - 1
  const seg = Math.min(Math.floor(t * n), n - 1)
  const u = (t * n) - seg
  const a = path[seg]
  const b = path[seg + 1]
  return [a[0] + u * (b[0] - a[0]), a[1] + u * (b[1] - a[1])]
}

type BaseStatus = 'operational' | 'damaged' | 'attacked'

interface KeyLoc {
  name: string
  lat: number
  lng: number
  type?: string
  status?: BaseStatus
  damage_level?: number
}

function toFeature(loc: KeyLoc, side: 'us' | 'iran', status?: BaseStatus) {
  return {
    type: 'Feature' as const,
    properties: {
      side,
      name: loc.name,
      status: status ?? (loc as KeyLoc & { status?: BaseStatus }).status ?? 'operational',
    },
    geometry: {
      type: 'Point' as const,
      coordinates: [loc.lng, loc.lat] as [number, number],
    },
  }
}

const FLIGHT_DURATION_MS = 2500 // 光点飞行单程时间

export function WarMap() {
  const mapRef = useRef<MapRef>(null)
  const containerRef = useRef<HTMLDivElement>(null)
  const animRef = useRef<number>(0)
  const startRef = useRef<number>(0)
  const attackPathsRef = useRef<[number, number][][]>([])
  const lincolnPathsRef = useRef<[number, number][][]>([])
  const fordPathsRef = useRef<[number, number][][]>([])
  const israelPathsRef = useRef<[number, number][][]>([])
  const situation = useReplaySituation()
  const { usForces, iranForces, conflictEvents = [] } = situation

  const usLocs = (usForces.keyLocations || []) as KeyLoc[]
  const irLocs = (iranForces.keyLocations || []) as KeyLoc[]

  const { usNaval, usBaseOp, usBaseDamaged, usBaseAttacked, labelsGeoJson } = useMemo(() => {
    const naval: GeoJSON.Feature<GeoJSON.Point>[] = []
    const op: GeoJSON.Feature<GeoJSON.Point>[] = []
    const damaged: GeoJSON.Feature<GeoJSON.Point>[] = []
    const attacked: GeoJSON.Feature<GeoJSON.Point>[] = []
    const labels: GeoJSON.Feature<GeoJSON.Point>[] = []

    for (const loc of usLocs as KeyLoc[]) {
      const f = toFeature(loc, 'us')
      labels.push({ ...f, properties: { ...f.properties, name: loc.name } })
      if (loc.type === 'Base') {
        const s = (loc.status ?? 'operational') as BaseStatus
        if (s === 'attacked') attacked.push(f)
        else if (s === 'damaged') damaged.push(f)
        else op.push(f)
      } else {
        naval.push(f)
      }
    }

    for (const loc of irLocs) {
      const f = toFeature(loc, 'iran')
      labels.push({ ...f, properties: { ...f.properties, name: loc.name } })
    }

    return {
      usNaval: { type: 'FeatureCollection' as const, features: naval },
      usBaseOp: { type: 'FeatureCollection' as const, features: op },
      usBaseDamaged: { type: 'FeatureCollection' as const, features: damaged },
      usBaseAttacked: { type: 'FeatureCollection' as const, features: attacked },
      labelsGeoJson: { type: 'FeatureCollection' as const, features: labels },
    }
  }, [usForces.keyLocations, iranForces.keyLocations])

  // 德黑兰到 27 个被袭目标的攻击路径（静态线条）
  const attackPaths = useMemo(
    () => ATTACKED_TARGETS.map((target) => parabolaPath(TEHRAN_SOURCE, target as [number, number])),
    []
  )

  attackPathsRef.current = attackPaths

  const lincolnPaths = useMemo(
    () => LINCOLN_STRIKE_TARGETS.map((t) => parabolaPath(LINCOLN_COORDS, t)),
    []
  )
  const fordPaths = useMemo(
    () => FORD_STRIKE_TARGETS.map((t) => parabolaPath(FORD_COORDS, t)),
    []
  )
  const israelPaths = useMemo(
    () => ISRAEL_STRIKE_TARGETS.map((t) => parabolaPath(ISRAEL_STRIKE_SOURCE, t)),
    []
  )
  lincolnPathsRef.current = lincolnPaths
  fordPathsRef.current = fordPaths
  israelPathsRef.current = israelPaths

  const lincolnLinesGeoJson = useMemo(
    () => ({
      type: 'FeatureCollection' as const,
      features: lincolnPaths.map((coords) => ({
        type: 'Feature' as const,
        properties: {},
        geometry: { type: 'LineString' as const, coordinates: coords },
      })),
    }),
    [lincolnPaths]
  )
  const fordLinesGeoJson = useMemo(
    () => ({
      type: 'FeatureCollection' as const,
      features: fordPaths.map((coords) => ({
        type: 'Feature' as const,
        properties: {},
        geometry: { type: 'LineString' as const, coordinates: coords },
      })),
    }),
    [fordPaths]
  )
  const israelLinesGeoJson = useMemo(
    () => ({
      type: 'FeatureCollection' as const,
      features: israelPaths.map((coords) => ({
        type: 'Feature' as const,
        properties: {},
        geometry: { type: 'LineString' as const, coordinates: coords },
      })),
    }),
    [israelPaths]
  )

  const attackLinesGeoJson = useMemo(
    () => ({
      type: 'FeatureCollection' as const,
      features: attackPaths.map((coords) => ({
        type: 'Feature' as const,
        properties: {},
        geometry: { type: 'LineString' as const, coordinates: coords },
      })),
    }),
    [attackPaths]
  )

  // GDELT 冲突事件：1–3 绿, 4–6 橙闪, 7–10 红脉
  const { conflictEventsGreen, conflictEventsOrange, conflictEventsRed } = useMemo(() => {
    const green: GeoJSON.Feature<GeoJSON.Point>[] = []
    const orange: GeoJSON.Feature<GeoJSON.Point>[] = []
    const red: GeoJSON.Feature<GeoJSON.Point>[] = []
    for (const e of conflictEvents) {
      const score = e.impact_score ?? 1
      const f: GeoJSON.Feature<GeoJSON.Point> = {
        type: 'Feature',
        properties: { event_id: e.event_id, impact_score: score },
        geometry: { type: 'Point', coordinates: [e.lng, e.lat] },
      }
      if (score <= 3) green.push(f)
      else if (score <= 6) orange.push(f)
      else red.push(f)
    }
    return {
      conflictEventsGreen: { type: 'FeatureCollection' as const, features: green },
      conflictEventsOrange: { type: 'FeatureCollection' as const, features: orange },
      conflictEventsRed: { type: 'FeatureCollection' as const, features: red },
    }
  }, [conflictEvents])

  const hideNonBelligerentLabels = (map: MapboxMap) => {
    const labelLayers = [
      'country-label',
      'state-label',
      'place-label',
      'place-label-capital',
      'place-label-city',
      'place-label-town',
      'place-label-village',
      'poi-label',
    ]
    for (const id of labelLayers) {
      try {
        if (map.getLayer(id)) map.setLayoutProperty(id, 'visibility', 'none')
      } catch (_) {}
    }
  }

  const initAnimation = useRef<(map: MapboxMap) => void>(null!)
  initAnimation.current = (map: MapboxMap) => {
    startRef.current = performance.now()

    const tick = (t: number) => {
      const elapsed = t - startRef.current
      const zoom = map.getZoom()
      const zoomScale = Math.max(0.5, zoom / 4.2) // 随镜头缩放：放大变大、缩小变小（4.2 为默认 zoom）
      try {
        // 光点从起点飞向目标的循环动画
        const src = map.getSource('attack-dots') as { setData: (d: GeoJSON.FeatureCollection) => void } | undefined
        const paths = attackPathsRef.current
        if (src && paths.length > 0) {
          const features: GeoJSON.Feature<GeoJSON.Point>[] = paths.map((path, i) => {
            const progress = ((elapsed / FLIGHT_DURATION_MS + i / paths.length) % 1)
            const coord = interpolateOnPath(path, progress)
            return {
              type: 'Feature' as const,
              properties: {},
              geometry: { type: 'Point' as const, coordinates: coord },
            }
          })
          src.setData({ type: 'FeatureCollection', features })
        }
        // damaged: 橙色闪烁 opacity 0.5 ~ 1, 约 1s 周期
        if (map.getLayer('points-damaged')) {
          const blink = 0.5 + 0.5 * Math.sin(elapsed * 0.003)
          map.setPaintProperty('points-damaged', 'circle-opacity', blink)
        }
        // attacked: 红色脉冲 2s 循环, 半径随 zoom 缩放
        if (map.getLayer('points-attacked-pulse')) {
          const cycle = 2000
          const phase = (elapsed % cycle) / cycle
          const r = 40 * phase * zoomScale
          const opacity = 1 - phase
          map.setPaintProperty('points-attacked-pulse', 'circle-radius', r)
          map.setPaintProperty('points-attacked-pulse', 'circle-opacity', opacity)
        }
        // 林肯号打击伊朗：蓝色光点
        const lincolnSrc = map.getSource('allied-strike-dots-lincoln') as
          | { setData: (d: GeoJSON.FeatureCollection) => void }
          | undefined
        const lincolnPaths = lincolnPathsRef.current
        if (lincolnSrc && lincolnPaths.length > 0) {
          const features: GeoJSON.Feature<GeoJSON.Point>[] = lincolnPaths.map(
            (path, i) => {
              const progress =
                (elapsed / FLIGHT_DURATION_MS + 0.5 + i / Math.max(lincolnPaths.length, 1)) % 1
              const coord = interpolateOnPath(path, progress)
              return {
                type: 'Feature' as const,
                properties: {},
                geometry: { type: 'Point' as const, coordinates: coord },
              }
            }
          )
          lincolnSrc.setData({ type: 'FeatureCollection', features })
        }
        // 福特号打击伊朗：青色光点
        const fordSrc = map.getSource('allied-strike-dots-ford') as
          | { setData: (d: GeoJSON.FeatureCollection) => void }
          | undefined
        const fordPaths = fordPathsRef.current
        if (fordSrc && fordPaths.length > 0) {
          const features: GeoJSON.Feature<GeoJSON.Point>[] = fordPaths.map(
            (path, i) => {
              const progress =
                (elapsed / FLIGHT_DURATION_MS + 0.3 + i / Math.max(fordPaths.length, 1)) % 1
              const coord = interpolateOnPath(path, progress)
              return {
                type: 'Feature' as const,
                properties: {},
                geometry: { type: 'Point' as const, coordinates: coord },
              }
            }
          )
          fordSrc.setData({ type: 'FeatureCollection', features })
        }
        // 以色列打击伊朗：浅青/白色光点
        const israelSrc = map.getSource('allied-strike-dots-israel') as
          | { setData: (d: GeoJSON.FeatureCollection) => void }
          | undefined
        const israelPaths = israelPathsRef.current
        if (israelSrc && israelPaths.length > 0) {
          const features: GeoJSON.Feature<GeoJSON.Point>[] = israelPaths.map(
            (path, i) => {
              const progress =
                (elapsed / FLIGHT_DURATION_MS + 0.1 + i / Math.max(israelPaths.length, 1)) % 1
              const coord = interpolateOnPath(path, progress)
              return {
                type: 'Feature' as const,
                properties: {},
                geometry: { type: 'Point' as const, coordinates: coord },
              }
            }
          )
          israelSrc.setData({ type: 'FeatureCollection', features })
        }
        // 伊朗被打击目标：蓝色脉冲 (2s 周期), 半径随 zoom 缩放
        if (map.getLayer('allied-strike-targets-pulse')) {
          const cycle = 2000
          const phase = (elapsed % cycle) / cycle
          const r = 35 * phase * zoomScale
          const opacity = Math.max(0, 1 - phase * 1.2)
          map.setPaintProperty('allied-strike-targets-pulse', 'circle-radius', r)
          map.setPaintProperty('allied-strike-targets-pulse', 'circle-opacity', opacity)
        }
        // GDELT 橙色 (4–6)：闪烁
        if (map.getLayer('gdelt-events-orange')) {
          const blink = 0.5 + 0.5 * Math.sin(elapsed * 0.004)
          map.setPaintProperty('gdelt-events-orange', 'circle-opacity', blink)
        }
        // GDELT 红色 (7–10)：脉冲扩散, 半径随 zoom 缩放
        if (map.getLayer('gdelt-events-red-pulse')) {
          const cycle = 2200
          const phase = (elapsed % cycle) / cycle
          const r = 30 * phase * zoomScale
          const opacity = Math.max(0, 1 - phase * 1.1)
          map.setPaintProperty('gdelt-events-red-pulse', 'circle-radius', r)
          map.setPaintProperty('gdelt-events-red-pulse', 'circle-opacity', opacity)
        }
      } catch (_) {}
      animRef.current = requestAnimationFrame(tick)
    }

    const start = () => {
      hideNonBelligerentLabels(map)
      map.fitBounds(
        [[THEATER_BBOX[0], THEATER_BBOX[1]], [THEATER_BBOX[2], THEATER_BBOX[3]]],
        { padding: 40, maxZoom: 5, duration: 0 }
      )
      const hasAnim =
        (map.getSource('attack-dots') && attackPathsRef.current.length > 0) ||
        (map.getSource('allied-strike-dots-lincoln') && lincolnPathsRef.current.length > 0) ||
        (map.getSource('allied-strike-dots-ford') && fordPathsRef.current.length > 0) ||
        (map.getSource('allied-strike-dots-israel') && israelPathsRef.current.length > 0) ||
        map.getSource('gdelt-events-green') ||
        map.getSource('gdelt-events-orange') ||
        map.getSource('gdelt-events-red')
      if (hasAnim) {
        animRef.current = requestAnimationFrame(tick)
      } else {
        animRef.current = requestAnimationFrame(start)
      }
    }
    start()
  }

  useEffect(() => {
    return () => cancelAnimationFrame(animRef.current)
  }, [])

  // 容器尺寸变化时 fitBounds，保证区域完整显示（移动端自适应）
  const fitToTheater = useCallback(() => {
    const map = mapRef.current?.getMap()
    if (!map) return
    map.fitBounds(THEATER_BOUNDS, { padding: 32, maxZoom: 6, duration: 0 })
  }, [])

  useEffect(() => {
    const el = containerRef.current
    if (!el) return
    const ro = new ResizeObserver(() => fitToTheater())
    ro.observe(el)
    return () => ro.disconnect()
  }, [fitToTheater])

  if (!MAPBOX_TOKEN) {
    return (
      <div className="flex h-full w-full items-center justify-center bg-military-dark">
        <div className="rounded-lg border border-military-border bg-military-panel/95 p-8 text-center shadow-lg">
          <p className="font-orbitron text-sm font-medium text-military-text-primary">地图需要 Mapbox 令牌</p>
          <p className="mt-2 text-xs text-military-text-secondary">
            复制 .env.example 为 .env，填入令牌后重启
          </p>
          <a
            href="https://account.mapbox.com/access-tokens/"
            target="_blank"
            rel="noopener noreferrer"
            className="mt-1 inline-block text-[10px] text-military-accent hover:underline"
          >
            免费申请 Mapbox 令牌 →
          </a>
        </div>
      </div>
    )
  }

  return (
    <div ref={containerRef} className="relative h-full w-full min-w-0">
      {/* 图例 - 随容器自适应，避免遮挡 */}
      <div className="absolute bottom-2 left-2 z-10 flex flex-wrap gap-x-3 gap-y-1 rounded bg-black/70 px-2 py-1.5 text-[9px] sm:text-[10px]">
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#22C55E]" /> 基地
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#EF4444]" /> 遭袭
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#3B82F6]" /> 海军
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#EF4444]" /> 伊朗
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-sm bg-red-500/40" /> 胡塞武装
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#3B82F6]" /> 林肯打击
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#06B6D4]" /> 福特打击
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#22D3EE]" /> 以色列打击
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#22C55E]" /> 低烈度
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#F97316]" /> 中烈度
        </span>
        <span className="flex items-center gap-1">
          <span className="h-1.5 w-1.5 rounded-full bg-[#EF4444]" /> 高烈度
        </span>
      </div>
      <Map
        ref={mapRef}
        initialViewState={DEFAULT_VIEW}
        mapStyle="mapbox://styles/mapbox/dark-v11"
        mapboxAccessToken={MAPBOX_TOKEN}
        attributionControl={false}
        dragRotate={false}
        touchRotate={false}
        style={{ width: '100%', height: '100%' }}
        onLoad={(e) => {
          fitToTheater()
          setTimeout(() => initAnimation.current(e.target), 150)
        }}
      >
        {/* 矢量标记：zoom 拉远变小，拉近变大 */}
        <Source id="points-us-naval" type="geojson" data={usNaval}>
          <Layer
            id="points-us-naval"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 3, 1, 5, 2, 7, 3.5, 10, 6],
              'circle-color': '#3B82F6',
              'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 3, 0.5, 7, 1, 10, 1.5],
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>

        <Source id="points-us-base-op" type="geojson" data={usBaseOp}>
          <Layer
            id="points-us-base-op"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 3, 1, 5, 2, 7, 3.5, 10, 6],
              'circle-color': '#22C55E',
              'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 3, 0.5, 7, 1, 10, 1.5],
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>

        <Source id="points-us-base-damaged" type="geojson" data={usBaseDamaged}>
          <Layer
            id="points-damaged"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 3, 1, 5, 2, 7, 3.5, 10, 6],
              'circle-color': '#F97316',
              'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 3, 0.5, 7, 1, 10, 1.5],
              'circle-stroke-color': '#fff',
              'circle-opacity': 1,
            }}
          />
        </Source>

        <Source id="points-us-base-attacked" type="geojson" data={usBaseAttacked}>
          <Layer
            id="points-attacked-dot"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 3, 1, 5, 2, 7, 3.5, 10, 6],
              'circle-color': '#EF4444',
              'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 3, 0.5, 7, 1, 10, 1.5],
              'circle-stroke-color': '#fff',
            }}
          />
          <Layer
            id="points-attacked-pulse"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 4, 8, 12, 12, 24],
              'circle-color': '#EF4444',
              'circle-opacity': 0,
            }}
          />
        </Source>

        <Source
          id="points-iran"
          type="geojson"
          data={{
            type: 'FeatureCollection',
            features: irLocs.map((loc) => toFeature(loc, 'iran')),
          }}
        >
          <Layer
            id="points-iran"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 3, 1, 5, 2, 7, 3.5, 10, 6],
              'circle-color': '#EF4444',
              'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 3, 0.5, 7, 1, 10, 1.5],
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>

        {/* GDELT 冲突事件：1–3 绿点, 4–6 橙闪, 7–10 红脉 */}
        <Source id="gdelt-events-green" type="geojson" data={conflictEventsGreen}>
          <Layer
            id="gdelt-events-green"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 2, 8, 4, 12, 6],
              'circle-color': '#22C55E',
              'circle-stroke-width': 0.5,
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>
        <Source id="gdelt-events-orange" type="geojson" data={conflictEventsOrange}>
          <Layer
            id="gdelt-events-orange"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 3, 8, 5, 12, 8],
              'circle-color': '#F97316',
              'circle-opacity': 0.8,
            }}
          />
        </Source>
        <Source id="gdelt-events-red" type="geojson" data={conflictEventsRed}>
          <Layer
            id="gdelt-events-red-dot"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 2, 8, 4, 12, 6],
              'circle-color': '#EF4444',
              'circle-stroke-width': 0.5,
              'circle-stroke-color': '#fff',
            }}
          />
          <Layer
            id="gdelt-events-red-pulse"
            type="circle"
            paint={{
              'circle-radius': 0,
              'circle-color': 'rgba(239, 68, 68, 0.5)',
              'circle-opacity': 0,
            }}
          />
        </Source>

        {/* 美以联军打击伊朗：路径线 */}
        <Source id="allied-strike-lines-lincoln" type="geojson" data={lincolnLinesGeoJson}>
          <Layer
            id="allied-strike-lines-lincoln"
            type="line"
            paint={{
              'line-color': 'rgba(96, 165, 250, 0.45)',
              'line-width': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1, 12, 2],
            }}
          />
        </Source>
        <Source id="allied-strike-lines-ford" type="geojson" data={fordLinesGeoJson}>
          <Layer
            id="allied-strike-lines-ford"
            type="line"
            paint={{
              'line-color': 'rgba(6, 182, 212, 0.45)',
              'line-width': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1, 12, 2],
            }}
          />
        </Source>
        <Source id="allied-strike-lines-israel" type="geojson" data={israelLinesGeoJson}>
          <Layer
            id="allied-strike-lines-israel"
            type="line"
            paint={{
              'line-color': 'rgba(34, 211, 238, 0.45)',
              'line-width': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1, 12, 2],
            }}
          />
        </Source>
        {/* 林肯号打击光点 */}
        <Source
          id="allied-strike-dots-lincoln"
          type="geojson"
          data={{
            type: 'FeatureCollection',
            features: lincolnPaths.map((path) => ({
              type: 'Feature' as const,
              properties: {},
              geometry: { type: 'Point' as const, coordinates: path[0] },
            })),
          }}
        >
          <Layer
            id="allied-strike-dots-lincoln-glow"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 3, 8, 6, 12, 10],
              'circle-color': 'rgba(96, 165, 250, 0.6)',
              'circle-blur': 0.3,
            }}
          />
          <Layer
            id="allied-strike-dots-lincoln-core"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 1, 8, 2, 12, 4],
              'circle-color': '#3B82F6',
              'circle-stroke-width': 0.5,
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>
        {/* 福特号打击光点 */}
        <Source
          id="allied-strike-dots-ford"
          type="geojson"
          data={{
            type: 'FeatureCollection',
            features: fordPaths.map((path) => ({
              type: 'Feature' as const,
              properties: {},
              geometry: { type: 'Point' as const, coordinates: path[0] },
            })),
          }}
        >
          <Layer
            id="allied-strike-dots-ford-glow"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 3, 8, 6, 12, 10],
              'circle-color': 'rgba(6, 182, 212, 0.6)',
              'circle-blur': 0.3,
            }}
          />
          <Layer
            id="allied-strike-dots-ford-core"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 1, 8, 2, 12, 4],
              'circle-color': '#06B6D4',
              'circle-stroke-width': 0.5,
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>
        {/* 以色列打击光点 */}
        <Source
          id="allied-strike-dots-israel"
          type="geojson"
          data={{
            type: 'FeatureCollection',
            features: israelPaths.map((path) => ({
              type: 'Feature' as const,
              properties: {},
              geometry: { type: 'Point' as const, coordinates: path[0] },
            })),
          }}
        >
          <Layer
            id="allied-strike-dots-israel-glow"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 3, 8, 6, 12, 10],
              'circle-color': 'rgba(34, 211, 238, 0.6)',
              'circle-blur': 0.3,
            }}
          />
          <Layer
            id="allied-strike-dots-israel-core"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 1, 8, 2, 12, 4],
              'circle-color': '#22D3EE',
              'circle-stroke-width': 0.5,
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>
        {/* 美军打击目标点位 (蓝色) */}
        <Source
          id="allied-strike-targets"
          type="geojson"
          data={{
            type: 'FeatureCollection',
            features: ALLIED_STRIKE_LOCATIONS.map((s) => ({
              type: 'Feature' as const,
              properties: { name: s.name },
              geometry: { type: 'Point' as const, coordinates: s.coords },
            })),
          }}
        >
          <Layer
            id="allied-strike-targets-circle"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 3, 1.5, 5, 2.5, 8, 4],
              'circle-color': '#3B82F6',
              'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 3, 0.5, 7, 1],
              'circle-stroke-color': '#fff',
            }}
          />
          <Layer
            id="allied-strike-targets-label"
            type="symbol"
            layout={{
              'text-field': ['get', 'name'],
              'text-size': ['interpolate', ['linear'], ['zoom'], 3, 6, 5, 8, 7, 10, 10, 13],
              'text-anchor': 'top',
              'text-offset': [0, 0.8],
            }}
            paint={{
              'text-color': '#60A5FA',
              'text-halo-width': 0,
            }}
          />
          <Layer
            id="allied-strike-targets-pulse"
            type="circle"
            paint={{
              'circle-radius': 0,
              'circle-color': 'rgba(96, 165, 250, 0.5)',
              'circle-opacity': 0,
            }}
          />
        </Source>

        {/* 伊朗攻击路径：细线 (矢量) */}
        <Source id="attack-lines" type="geojson" data={attackLinesGeoJson}>
          <Layer
            id="attack-lines"
            type="line"
            paint={{
              'line-color': 'rgba(255, 100, 100, 0.4)',
              'line-width': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1, 12, 2],
            }}
          />
        </Source>
        {/* 光点飞行动画：从德黑兰飞向各目标 */}
        <Source
          id="attack-dots"
          type="geojson"
          data={{
            type: 'FeatureCollection',
            features: attackPaths.map((path) => ({
              type: 'Feature' as const,
              properties: {},
              geometry: {
                type: 'Point' as const,
                coordinates: path[0],
              },
            })),
          }}
        >
          <Layer
            id="attack-dots-glow"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 3, 8, 6, 12, 10],
              'circle-color': 'rgba(255, 100, 100, 0.6)',
              'circle-blur': 0.3,
            }}
          />
          <Layer
            id="attack-dots-core"
            type="circle"
            paint={{
              'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 1, 8, 2, 12, 4],
              'circle-color': '#ff4444',
              'circle-stroke-width': 0.5,
              'circle-stroke-color': '#fff',
            }}
          />
        </Source>

        {/* 中文标注 - 随 zoom 自适应大小 */}
        <Source id="labels" type="geojson" data={labelsGeoJson}>
          <Layer
            id="labels"
            type="symbol"
            layout={{
              'text-field': ['get', 'name'],
              'text-size': ['interpolate', ['linear'], ['zoom'], 3, 6, 5, 8, 7, 10, 10, 13],
              'text-anchor': 'top',
              'text-offset': [0, 0.8],
            }}
            paint={{
              'text-color': '#E5E7EB',
              'text-halo-width': 0,
            }}
          />
        </Source>

        {/* 胡塞武装失控区 - 伊朗红 */}
        <Source
          id="houthi-area"
          type="geojson"
          data={{
            type: 'Feature',
            properties: { name: '胡塞武装' },
            geometry: {
              type: 'Polygon',
              coordinates: [HOUTHI_POLYGON],
            },
          }}
        >
          <Layer
            id="houthi-fill"
            type="fill"
            paint={{
              'fill-color': 'rgba(239, 68, 68, 0.2)',
              'fill-outline-color': '#EF4444',
              'fill-opacity': 0.4,
            }}
          />
        </Source>
        {/* 胡塞武装标注 */}
        <Source
          id="houthi-label"
          type="geojson"
          data={{
            type: 'Feature',
            properties: { name: '胡塞武装' },
            geometry: { type: 'Point', coordinates: [44, 15.5] },
          }}
        >
          <Layer
            id="houthi-label-text"
            type="symbol"
            layout={{
              'text-field': '胡塞武装',
              'text-size': ['interpolate', ['linear'], ['zoom'], 4, 9, 8, 12],
              'text-anchor': 'center',
            }}
            paint={{
              'text-color': '#EF4444',
              'text-halo-width': 0,
            }}
          />
        </Source>

        {/* 伊朗标注 */}
        <Source
          id="iran-label"
          type="geojson"
          data={{
            type: 'Feature',
            properties: { name: '伊朗' },
            geometry: { type: 'Point', coordinates: [53.5, 32.5] },
          }}
        >
          <Layer
            id="iran-label-text"
            type="symbol"
            layout={{
              'text-field': '伊朗',
              'text-size': ['interpolate', ['linear'], ['zoom'], 4, 11, 8, 16],
              'text-anchor': 'center',
            }}
            paint={{
              'text-color': '#EF4444',
              'text-halo-width': 0,
            }}
          />
        </Source>
        {/* 以色列标注 */}
        <Source
          id="israel-label"
          type="geojson"
          data={{
            type: 'Feature',
            properties: { name: '以色列' },
            geometry: { type: 'Point', coordinates: [35, 31] },
          }}
        >
          <Layer
            id="israel-label-text"
            type="symbol"
            layout={{
              'text-field': '以色列',
              'text-size': ['interpolate', ['linear'], ['zoom'], 4, 11, 8, 16],
              'text-anchor': 'center',
            }}
            paint={{
              'text-color': '#60A5FA',
              'text-halo-width': 0,
            }}
          />
        </Source>

        <Source id="countries" type="geojson" data={COUNTRIES_GEOJSON}>
          {/* 伊朗区域填充 - 红色系 */}
          <Layer
            id="iran-fill"
            type="fill"
            filter={['==', ['get', 'ADMIN'], IRAN_ADMIN]}
            paint={{
              'fill-color': 'rgba(239, 68, 68, 0.15)',
              'fill-outline-color': '#EF4444',
              'fill-opacity': 0.5,
            }}
          />
          <Layer
            id="iran-outline"
            type="line"
            filter={['==', ['get', 'ADMIN'], IRAN_ADMIN]}
            paint={{
              'line-color': '#EF4444',
              'line-width': 2,
              'line-opacity': 0.9,
            }}
          />
          {/* 以色列区域填充 - 蓝色系 */}
          <Layer
            id="israel-fill"
            type="fill"
            filter={['==', ['get', 'ADMIN'], 'Israel']}
            paint={{
              'fill-color': 'rgba(96, 165, 250, 0.25)',
              'fill-outline-color': '#60A5FA',
              'fill-opacity': 0.6,
            }}
          />
          <Layer
            id="allies-outline"
            type="line"
            filter={['in', ['get', 'ADMIN'], ['literal', ALLIES_ADMIN]]}
            paint={{
              'line-color': '#3B82F6',
              'line-width': 1.5,
              'line-opacity': 0.8,
            }}
          />
        </Source>
      </Map>
    </div>
  )
}
