import { useState, useEffect, useCallback } from 'react'
import { LeftPanel } from './LeftPanel'
import { RightPanel } from './RightPanel'
import { MapView } from '@common/components/map/MapView'
import { AnalysisListTable, type Analysis } from './AnalysisListTable'
import { OilSpillTheoryView } from './OilSpillTheoryView'
import { BoomDeploymentTheoryView } from './BoomDeploymentTheoryView'
import { BacktrackModal } from './BacktrackModal'
import { RecalcModal } from './RecalcModal'
import { BacktrackReplayBar } from '@common/components/map/BacktrackReplayBar'
import { useSubMenu, navigateToTab, setReportGenCategory } from '@common/hooks/useSubMenu'
import type { BoomLine, AlgorithmSettings, ContainmentResult, BoomLineCoord } from '@common/types/boomLine'
import type { BacktrackPhase, BacktrackVessel, BacktrackConditions, ReplayShip, CollisionEvent } from '@common/types/backtrack'
import { TOTAL_REPLAY_FRAMES } from '@common/types/backtrack'
import { fetchBacktrackByAcdnt, createBacktrack, fetchPredictionDetail } from '../services/predictionApi'
import type { PredictionDetail } from '../services/predictionApi'
import { api } from '@common/services/api'
import { generateAIBoomLines } from '@common/utils/geo'

export type PredictionModel = 'KOSPS' | 'POSEIDON' | 'OpenDrift'

// ---------------------------------------------------------------------------
// 민감자원 타입 + 데모 데이터
// ---------------------------------------------------------------------------
export interface SensitiveResource {
  id: string
  name: string
  type: 'aquaculture' | 'beach' | 'ecology' | 'intake'
  lat: number
  lon: number
  radiusM: number
  arrivalTimeH: number
}

const DEMO_SENSITIVE_RESOURCES: SensitiveResource[] = [
  { id: 'aq-1', name: '여수 돌산 양식장', type: 'aquaculture', lat: 34.755, lon: 127.735, radiusM: 800, arrivalTimeH: 3 },
  { id: 'bc-1', name: '만성리 해수욕장', type: 'beach', lat: 34.765, lon: 127.765, radiusM: 400, arrivalTimeH: 6 },
  { id: 'ec-1', name: '오동도 생태보호구역', type: 'ecology', lat: 34.745, lon: 127.78, radiusM: 600, arrivalTimeH: 12 },
  { id: 'aq-2', name: '금오도 전복 양식장', type: 'aquaculture', lat: 34.70, lon: 127.75, radiusM: 700, arrivalTimeH: 8 },
  { id: 'bc-2', name: '방죽포 해수욕장', type: 'beach', lat: 34.72, lon: 127.81, radiusM: 350, arrivalTimeH: 10 },
]

// ---------------------------------------------------------------------------
// 데모 궤적 생성 (seeded PRNG — deterministic)
// ---------------------------------------------------------------------------
function mulberry32(seed: number) {
  return () => {
    seed |= 0; seed = seed + 0x6D2B79F5 | 0
    let t = Math.imul(seed ^ seed >>> 15, 1 | seed)
    t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t
    return ((t ^ t >>> 14) >>> 0) / 4294967296
  }
}

const DEG2RAD = Math.PI / 180

function generateDemoTrajectory(
  incident: { lat: number; lon: number },
  models: PredictionModel[],
  durationHours: number
): Array<{ lat: number; lon: number; time: number; particle: number; model: PredictionModel }> {
  const result: Array<{ lat: number; lon: number; time: number; particle: number; model: PredictionModel }> = []
  const PARTICLES_PER_MODEL = 60
  const TIME_STEP = 3 // hours

  const modelParams: Record<PredictionModel, { bearing: number; speed: number; spread: number; seed: number }> = {
    KOSPS:     { bearing: 42, speed: 0.003,  spread: 0.008, seed: 42 },
    POSEIDON:  { bearing: 55, speed: 0.0025, spread: 0.01,  seed: 137 },
    OpenDrift: { bearing: 35, speed: 0.0035, spread: 0.006, seed: 271 },
  }

  for (const model of models) {
    const p = modelParams[model]
    const rng = mulberry32(p.seed)

    for (let pid = 0; pid < PARTICLES_PER_MODEL; pid++) {
      const particleAngleOffset = (rng() - 0.5) * 40  // ±20°
      const particleSpeedFactor = 0.7 + rng() * 0.6   // 0.7~1.3

      for (let t = 0; t <= durationHours; t += TIME_STEP) {
        const timeFactor = t / durationHours
        const bearing = (p.bearing + particleAngleOffset) * DEG2RAD

        const dist = p.speed * t * particleSpeedFactor
        const turbLat = (rng() - 0.5) * p.spread * timeFactor
        const turbLon = (rng() - 0.5) * p.spread * timeFactor

        const lat = incident.lat + dist * Math.cos(bearing) + turbLat
        const lon = incident.lon + dist * Math.sin(bearing) / Math.cos(incident.lat * DEG2RAD) + turbLon

        result.push({ lat, lon, time: t, particle: pid, model })
      }
    }
  }

  return result
}
// eslint-disable-next-line react-refresh/only-export-components
export const ALL_MODELS: PredictionModel[] = ['KOSPS', 'POSEIDON', 'OpenDrift']

export function OilSpillView() {
  const { activeSubTab, setActiveSubTab } = useSubMenu('prediction')
  const [enabledLayers, setEnabledLayers] = useState<Set<string>>(new Set())
  const [incidentCoord, setIncidentCoord] = useState({ lon: 127.6845, lat: 34.7312 })
  const [isSelectingLocation, setIsSelectingLocation] = useState(false)
  const [oilTrajectory, setOilTrajectory] = useState<Array<{ lat: number; lon: number; time: number; particle?: number; model?: PredictionModel }>>([])
  const [isRunningSimulation, setIsRunningSimulation] = useState(false)
  const [selectedModels, setSelectedModels] = useState<Set<PredictionModel>>(new Set(['KOSPS']))
  const [predictionTime, setPredictionTime] = useState(48)
  const [spillType, setSpillType] = useState('연속')
  const [oilType, setOilType] = useState('벙커C유')
  const [spillAmount, setSpillAmount] = useState(100)

  // 민감자원
  const [sensitiveResources, setSensitiveResources] = useState<SensitiveResource[]>([])

  // 오일펜스 배치 상태
  const [boomLines, setBoomLines] = useState<BoomLine[]>([])
  const [algorithmSettings, setAlgorithmSettings] = useState<AlgorithmSettings>({
    currentOrthogonalCorrection: 15,
    safetyMarginMinutes: 60,
    minContainmentEfficiency: 80,
    waveHeightCorrectionFactor: 1.0,
  })
  const [isDrawingBoom, setIsDrawingBoom] = useState(false)
  const [drawingPoints, setDrawingPoints] = useState<BoomLineCoord[]>([])
  const [containmentResult, setContainmentResult] = useState<ContainmentResult | null>(null)

  // 레이어 스타일 (투명도 / 밝기)
  const [layerOpacity, setLayerOpacity] = useState(50)
  const [layerBrightness, setLayerBrightness] = useState(50)

  // 타임라인 플레이어 상태
  const [isPlaying, setIsPlaying] = useState(false)
  const [timelinePosition, setTimelinePosition] = useState(25) // 0~100%
  const [playSpeed, setPlaySpeed] = useState(1)

  // 역추적 상태
  const [backtrackModalOpen, setBacktrackModalOpen] = useState(false)
  const [backtrackPhase, setBacktrackPhase] = useState<BacktrackPhase>('conditions')
  const [backtrackVessels, setBacktrackVessels] = useState<BacktrackVessel[]>([])
  const [isReplayActive, setIsReplayActive] = useState(false)
  const [isReplayPlaying, setIsReplayPlaying] = useState(false)
  const [replayFrame, setReplayFrame] = useState(0)
  const [replaySpeed, setReplaySpeed] = useState(1)

  // 선택된 분석 (목록에서 클릭 시)
  const [selectedAnalysis, setSelectedAnalysis] = useState<Analysis | null>(null)
  // 분석 상세 (API에서 가져온 선박/기상 정보)
  const [analysisDetail, setAnalysisDetail] = useState<PredictionDetail | null>(null)

  // 역추적 API 데이터
  const [backtrackConditions, setBacktrackConditions] = useState<BacktrackConditions>({
    estimatedSpillTime: '', analysisRange: '±12시간', searchRadius: '10 NM',
    spillLocation: { lat: 34.7312, lon: 127.6845 }, totalVessels: 0,
  })
  const [replayShips, setReplayShips] = useState<ReplayShip[]>([])
  const [collisionEvent, setCollisionEvent] = useState<CollisionEvent | null>(null)

  // 재계산 상태
  const [recalcModalOpen, setRecalcModalOpen] = useState(false)

  const handleToggleLayer = (layerId: string, enabled: boolean) => {
    setEnabledLayers(prev => {
      const newSet = new Set(prev)
      if (enabled) {
        newSet.add(layerId)
      } else {
        newSet.delete(layerId)
      }
      return newSet
    })
  }

  // 역추적: API에서 기존 결과 로딩
  const loadBacktrackData = useCallback(async (acdntSn: number) => {
    try {
      const bt = await fetchBacktrackByAcdnt(acdntSn)
      if (bt && bt.execSttsCd === 'completed' && bt.rsltData) {
        const rslt = bt.rsltData as Record<string, unknown>
        if (Array.isArray(rslt.vessels)) {
          setBacktrackVessels(rslt.vessels as BacktrackVessel[])
        }
        if (Array.isArray(rslt.replayShips)) {
          setReplayShips(rslt.replayShips as ReplayShip[])
        }
        if (rslt.collisionEvent) {
          setCollisionEvent(rslt.collisionEvent as CollisionEvent)
        }
        setBacktrackConditions({
          estimatedSpillTime: bt.estSpilDtm ? new Date(bt.estSpilDtm).toLocaleString('ko-KR', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : '',
          analysisRange: bt.anlysRange || '±12시간',
          searchRadius: bt.srchRadiusNm ? `${bt.srchRadiusNm} NM` : '10 NM',
          spillLocation: { lat: bt.lat || incidentCoord.lat, lon: bt.lon || incidentCoord.lon },
          totalVessels: bt.totalVessels || 0,
        })
        setBacktrackPhase('results')
        return
      }
    } catch (err) {
      console.error('[prediction] 역추적 데이터 로딩 실패:', err)
    }
    // 기존 결과 없으면 conditions 상태 유지
    setBacktrackPhase('conditions')
    setBacktrackVessels([])
    setReplayShips([])
    setCollisionEvent(null)
  }, [incidentCoord])

  // 역추적 핸들러
  const handleOpenBacktrack = () => {
    setBacktrackModalOpen(true)
    setBacktrackConditions(prev => ({
      ...prev,
      spillLocation: incidentCoord,
    }))
    if (selectedAnalysis) {
      loadBacktrackData(selectedAnalysis.acdntSn)
    } else {
      setBacktrackPhase('conditions')
      setBacktrackVessels([])
    }
  }

  const handleRunBacktrackAnalysis = async () => {
    setBacktrackPhase('analyzing')
    try {
      if (selectedAnalysis) {
        const { backtrackSn } = await createBacktrack({
          acdntSn: selectedAnalysis.acdntSn,
          lon: incidentCoord.lon,
          lat: incidentCoord.lat,
        })
        // 생성 후 기존 결과 로딩 (시드 데이터 또는 엔진 처리 결과)
        const bt = await fetchBacktrackByAcdnt(selectedAnalysis.acdntSn)
        if (bt && bt.rsltData) {
          const rslt = bt.rsltData as Record<string, unknown>
          if (Array.isArray(rslt.vessels)) {
            setBacktrackVessels(rslt.vessels as BacktrackVessel[])
          }
          if (Array.isArray(rslt.replayShips)) {
            setReplayShips(rslt.replayShips as ReplayShip[])
          }
          if (rslt.collisionEvent) {
            setCollisionEvent(rslt.collisionEvent as CollisionEvent)
          }
          setBacktrackConditions(prev => ({
            ...prev,
            totalVessels: bt.totalVessels || 0,
          }))
          setBacktrackPhase('results')
        } else {
          // 엔진 미구현 — PENDING 상태, 일단 빈 결과
          console.info('[prediction] 역추적 생성 완료 (SN:', backtrackSn, '), 엔진 미구현')
          setBacktrackPhase('conditions')
        }
      }
    } catch (err) {
      console.error('[prediction] 역추적 분석 실패:', err)
      setBacktrackPhase('conditions')
    }
  }

  const handleStartReplay = () => {
    setBacktrackModalOpen(false)
    setIsReplayActive(true)
    setReplayFrame(0)
    setIsReplayPlaying(false)
  }

  const handleCloseReplay = () => {
    setIsReplayActive(false)
    setIsReplayPlaying(false)
    setReplayFrame(0)
  }

  // 역추적 리플레이 애니메이션
  useEffect(() => {
    if (!isReplayPlaying) return
    if (replayFrame >= TOTAL_REPLAY_FRAMES) {
      setIsReplayPlaying(false)
      return
    }
    const interval = setInterval(() => {
      setReplayFrame(prev => {
        const next = prev + 1
        if (next >= TOTAL_REPLAY_FRAMES) {
          setIsReplayPlaying(false)
          return TOTAL_REPLAY_FRAMES
        }
        return next
      })
    }, 50 / replaySpeed)
    return () => clearInterval(interval)
  }, [isReplayPlaying, replayFrame, replaySpeed])

  // 분석 목록에서 사고명 클릭 시
  const handleSelectAnalysis = async (analysis: Analysis) => {
    setSelectedAnalysis(analysis)
    if (analysis.lon != null && analysis.lat != null) {
      setIncidentCoord({ lon: analysis.lon, lat: analysis.lat })
    }
    // 유종 매핑
    const oilTypeMap: Record<string, string> = {
      'BUNKER_C': '벙커C유', 'DIESEL': '경유', 'CRUDE_OIL': '원유', 'LUBE_OIL': '윤활유',
    }
    setOilType(oilTypeMap[analysis.oilType] || '벙커C유')
    setSpillAmount(analysis.volume ?? 100)
    setPredictionTime(parseInt(analysis.duration) || 48)
    // 모델 상태에 따라 선택 모델 설정
    const models = new Set<PredictionModel>()
    if (analysis.kospsStatus !== 'pending') models.add('KOSPS')
    if (analysis.poseidonStatus !== 'pending') models.add('POSEIDON')
    if (analysis.opendriftStatus !== 'pending') models.add('OpenDrift')
    setSelectedModels(models)
    // 분석 상세 로딩 (선박/기상 정보)
    try {
      const detail = await fetchPredictionDetail(analysis.acdntSn)
      setAnalysisDetail(detail)
    } catch (err) {
      console.error('[prediction] 분석 상세 로딩 실패:', err)
    }
    // 분석 화면으로 전환
    setActiveSubTab('analysis')
  }

  const handleMapClick = (lon: number, lat: number) => {
    if (isDrawingBoom) {
      setDrawingPoints(prev => [...prev, { lat, lon }])
    } else {
      setIncidentCoord({ lon, lat })
      setIsSelectingLocation(false)
    }
  }

  const handleRunSimulation = async () => {
    if (selectedModels.size === 0) return
    setIsRunningSimulation(true)

    try {
      const models = Array.from(selectedModels)
      const results = await Promise.all(
        models.map(async (model) => {
          const { data } = await api.post<{ trajectory: Array<{ lat: number; lon: number; time: number; particle?: number }> }>('/simulation/run', {
            model,
            lat: incidentCoord.lat,
            lon: incidentCoord.lon,
            duration_hours: predictionTime,
            oil_type: oilType,
            spill_amount: spillAmount,
            spill_type: spillType,
          })
          return data.trajectory.map(p => ({ ...p, model }))
        })
      )

      setOilTrajectory(results.flat())
    } catch {
      // 백엔드 미구현 — 클라이언트 데모 궤적 fallback
      console.info('[prediction] 서버 시뮬레이션 미구현, 데모 궤적 생성')
      const models = Array.from(selectedModels)
      const demoTrajectory = generateDemoTrajectory(incidentCoord, models, predictionTime)
      setOilTrajectory(demoTrajectory)

      // AI 방어선 자동 생성
      const demoBooms = generateAIBoomLines(demoTrajectory, incidentCoord, algorithmSettings)
      setBoomLines(demoBooms)

      // 민감자원 로드
      setSensitiveResources(DEMO_SENSITIVE_RESOURCES)
    } finally {
      setIsRunningSimulation(false)
    }
  }

  return (
    <div className="flex flex-1 overflow-hidden">
      {/* Left Sidebar */}
      {activeSubTab === 'analysis' && (
        <LeftPanel
          selectedAnalysis={selectedAnalysis}
          enabledLayers={enabledLayers}
          onToggleLayer={handleToggleLayer}
          incidentCoord={incidentCoord}
          onCoordChange={setIncidentCoord}
          onMapSelectClick={() => setIsSelectingLocation(true)}
          onRunSimulation={handleRunSimulation}
          isRunningSimulation={isRunningSimulation}
          selectedModels={selectedModels}
          onModelsChange={setSelectedModels}
          predictionTime={predictionTime}
          onPredictionTimeChange={setPredictionTime}
          spillType={spillType}
          onSpillTypeChange={setSpillType}
          oilType={oilType}
          onOilTypeChange={setOilType}
          spillAmount={spillAmount}
          onSpillAmountChange={setSpillAmount}
          boomLines={boomLines}
          onBoomLinesChange={setBoomLines}
          oilTrajectory={oilTrajectory}
          algorithmSettings={algorithmSettings}
          onAlgorithmSettingsChange={setAlgorithmSettings}
          isDrawingBoom={isDrawingBoom}
          onDrawingBoomChange={setIsDrawingBoom}
          drawingPoints={drawingPoints}
          onDrawingPointsChange={setDrawingPoints}
          containmentResult={containmentResult}
          onContainmentResultChange={setContainmentResult}
          layerOpacity={layerOpacity}
          onLayerOpacityChange={setLayerOpacity}
          layerBrightness={layerBrightness}
          onLayerBrightnessChange={setLayerBrightness}
        />
      )}

      {/* Center - Map/Content Area */}
      <div className="flex-1 relative overflow-hidden">
        {activeSubTab === 'list' ? (
          <AnalysisListTable onTabChange={setActiveSubTab} onSelectAnalysis={handleSelectAnalysis} />
        ) : activeSubTab === 'theory' ? (
          <OilSpillTheoryView />
        ) : activeSubTab === 'boom-theory' ? (
          <BoomDeploymentTheoryView />
        ) : (
          <>
          <MapView
            enabledLayers={enabledLayers}
            incidentCoord={incidentCoord}
            isSelectingLocation={isSelectingLocation || isDrawingBoom}
            onMapClick={handleMapClick}
            oilTrajectory={oilTrajectory}
            selectedModels={selectedModels}
            boomLines={boomLines}
            isDrawingBoom={isDrawingBoom}
            drawingPoints={drawingPoints}
            layerOpacity={layerOpacity}
            layerBrightness={layerBrightness}
            sensitiveResources={sensitiveResources}
            backtrackReplay={isReplayActive && replayShips.length > 0 ? {
              isActive: true,
              ships: replayShips,
              collisionEvent: collisionEvent || undefined,
              replayFrame,
              totalFrames: TOTAL_REPLAY_FRAMES,
              incidentCoord,
            } : undefined}
          />

          {/* 타임라인 플레이어 (리플레이 비활성 시) */}
          {!isReplayActive && <div style={{
            position: 'absolute', bottom: 0, left: 0, right: 0, height: '72px',
            background: 'rgba(15,21,36,0.95)', backdropFilter: 'blur(16px)',
            borderTop: '1px solid var(--bd)',
            display: 'flex', alignItems: 'center', padding: '0 20px', gap: '16px', zIndex: 1100
          }}>
            {/* 컨트롤 버튼 */}
            <div style={{ display: 'flex', gap: '4px', flexShrink: 0 }}>
              {[
                { icon: '⏮', action: () => setTimelinePosition(0) },
                { icon: '◀', action: () => setTimelinePosition(Math.max(0, timelinePosition - 100 / 12)) },
              ].map((btn, i) => (
                <button key={i} onClick={btn.action} style={{
                  width: '34px', height: '34px', borderRadius: 'var(--rS, 4px)',
                  border: '1px solid var(--bd)', background: 'var(--bg3)', color: 'var(--t2)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  cursor: 'pointer', fontSize: '14px', transition: '0.2s'
                }}>{btn.icon}</button>
              ))}
              <button onClick={() => setIsPlaying(!isPlaying)} style={{
                width: '34px', height: '34px', borderRadius: 'var(--rS, 4px)',
                border: isPlaying ? '1px solid var(--cyan)' : '1px solid var(--bd)',
                background: isPlaying ? 'var(--cyan)' : 'var(--bg3)',
                color: isPlaying ? 'var(--bg0)' : 'var(--t2)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                cursor: 'pointer', fontSize: '14px', transition: '0.2s'
              }}>{isPlaying ? '⏸' : '▶'}</button>
              {[
                { icon: '▶▶', action: () => setTimelinePosition(Math.min(100, timelinePosition + 100 / 12)) },
                { icon: '⏭', action: () => setTimelinePosition(100) },
              ].map((btn, i) => (
                <button key={i} onClick={btn.action} style={{
                  width: '34px', height: '34px', borderRadius: 'var(--rS, 4px)',
                  border: '1px solid var(--bd)', background: 'var(--bg3)', color: 'var(--t2)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  cursor: 'pointer', fontSize: '12px', transition: '0.2s'
                }}>{btn.icon}</button>
              ))}
              <div style={{ width: '8px' }} />
              <button onClick={() => setPlaySpeed(playSpeed >= 4 ? 1 : playSpeed * 2)} style={{
                width: '34px', height: '34px', borderRadius: 'var(--rS, 4px)',
                border: '1px solid var(--bd)', background: 'var(--bg3)', color: 'var(--t2)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                cursor: 'pointer', fontSize: '11px', fontWeight: 600, fontFamily: 'var(--fM)', transition: '0.2s'
              }}>{playSpeed}×</button>
            </div>

            {/* 타임라인 슬라이더 */}
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '6px' }}>
              {/* 시간 라벨 */}
              <div style={{ display: 'flex', justifyContent: 'space-between', padding: '0 4px' }}>
                {['0h', '6h', '12h', '18h', '24h', '36h', '48h', '60h', '72h'].map((label, i) => {
                  const pos = [0, 8.33, 16.67, 25, 33.33, 50, 66.67, 83.33, 100][i]
                  const isActive = Math.abs(timelinePosition - pos) < 5
                  return (
                    <span key={label} style={{
                      fontSize: '10px', fontFamily: 'var(--fM)',
                      color: isActive ? 'var(--cyan)' : 'var(--t3)',
                      fontWeight: isActive ? 600 : 400, cursor: 'pointer'
                    }} onClick={() => setTimelinePosition(pos)}>{label}</span>
                  )
                })}
              </div>

              {/* 슬라이더 트랙 */}
              <div style={{ position: 'relative', height: '24px', display: 'flex', alignItems: 'center' }}>
                {/* 트랙 레일 */}
                <div
                  style={{ width: '100%', height: '4px', background: 'var(--bd)', borderRadius: '2px', position: 'relative', cursor: 'pointer' }}
                  onClick={(e) => {
                    const rect = e.currentTarget.getBoundingClientRect()
                    setTimelinePosition(Math.max(0, Math.min(100, ((e.clientX - rect.left) / rect.width) * 100)))
                  }}
                >
                  {/* 진행 바 */}
                  <div style={{
                    position: 'absolute', top: 0, left: 0,
                    width: `${timelinePosition}%`, height: '100%',
                    background: 'linear-gradient(90deg, var(--cyan), var(--blue))',
                    borderRadius: '2px', transition: 'width 0.15s'
                  }} />
                  {/* 주요 마커 */}
                  {[0, 16.67, 33.33, 50, 66.67, 83.33, 100].map((pos) => (
                    <div key={`mj-${pos}`} style={{
                      position: 'absolute', width: '2px', height: '14px',
                      background: 'var(--t3)', top: '-5px', left: `${pos}%`
                    }} />
                  ))}
                  {/* 보조 마커 */}
                  {[8.33, 25].map((pos) => (
                    <div key={`mn-${pos}`} style={{
                      position: 'absolute', width: '2px', height: '10px',
                      background: 'var(--bdL)', top: '-3px', left: `${pos}%`
                    }} />
                  ))}
                  {/* 방어선 설치 이벤트 마커 */}
                  {boomLines.length > 0 && [
                    { pos: 4.2, label: '1차 방어선 설치 (+3h)' },
                    { pos: 8.3, label: '2차 방어선 설치 (+6h)' },
                    { pos: 12.5, label: '3차 방어선 설치 (+9h)' },
                  ].slice(0, boomLines.length).map((bm, i) => (
                    <div key={`bm-${i}`} title={bm.label} style={{
                      position: 'absolute', top: '-18px', left: `${bm.pos}%`,
                      transform: 'translateX(-50%)', fontSize: '12px', cursor: 'pointer',
                      filter: 'drop-shadow(0 0 4px rgba(245,158,11,0.5))'
                    }}>🛡</div>
                  ))}
                </div>
                {/* 드래그 핸들 */}
                <div style={{
                  position: 'absolute', left: `${timelinePosition}%`, top: '50%',
                  transform: 'translate(-50%, -50%)',
                  width: '16px', height: '16px',
                  background: 'var(--cyan)', border: '3px solid var(--bg0)',
                  borderRadius: '50%', cursor: 'grab',
                  boxShadow: '0 0 10px rgba(6,182,212,0.4)', zIndex: 2,
                  transition: 'left 0.15s'
                }} />
              </div>
            </div>

            {/* 시간 정보 */}
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: '4px', flexShrink: 0, minWidth: '200px' }}>
              <div style={{ fontSize: '14px', fontWeight: 600, color: 'var(--cyan)', fontFamily: 'var(--fM)' }}>
                +{Math.round(timelinePosition * 72 / 100)}h — {(() => {
                  const d = new Date(); d.setHours(d.getHours() + Math.round(timelinePosition * 72 / 100))
                  return `${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')} KST`
                })()}
              </div>
              <div style={{ display: 'flex', gap: '14px' }}>
                {[
                  { label: '풍화율', value: `${Math.min(99, Math.round(timelinePosition * 0.4))}%`, color: 'var(--t1)' },
                  { label: '면적', value: `${(timelinePosition * 0.08).toFixed(1)} km²`, color: 'var(--t1)' },
                  { label: '차단율', value: boomLines.length > 0 ? `${Math.min(95, 70 + Math.round(timelinePosition * 0.2))}%` : '—', color: 'var(--boom)' },
                ].map((s, i) => (
                  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: '5px', fontSize: '11px' }}>
                    <span style={{ color: 'var(--t3)', fontFamily: 'var(--fK)' }}>{s.label}</span>
                    <span style={{ color: s.color, fontWeight: 600, fontFamily: 'var(--fM)' }}>{s.value}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>}

          {/* 역추적 리플레이 바 */}
          {isReplayActive && (
            <BacktrackReplayBar
              isPlaying={isReplayPlaying}
              replayFrame={replayFrame}
              totalFrames={TOTAL_REPLAY_FRAMES}
              replaySpeed={replaySpeed}
              onTogglePlay={() => setIsReplayPlaying(!isReplayPlaying)}
              onSeek={setReplayFrame}
              onSpeedChange={setReplaySpeed}
              onClose={handleCloseReplay}
              replayShips={replayShips}
              collisionEvent={collisionEvent || undefined}
            />
          )}
          </>
        )}
      </div>

      {/* Right Panel */}
      {activeSubTab === 'analysis' && <RightPanel onOpenBacktrack={handleOpenBacktrack} onOpenRecalc={() => setRecalcModalOpen(true)} onOpenReport={() => { setReportGenCategory(0); navigateToTab('reports', 'generate') }} detail={analysisDetail} />}

      {/* 재계산 모달 */}
      <RecalcModal
        isOpen={recalcModalOpen}
        onClose={() => setRecalcModalOpen(false)}
        oilType={oilType}
        spillAmount={spillAmount}
        spillType={spillType}
        predictionTime={predictionTime}
        incidentCoord={incidentCoord}
        selectedModels={selectedModels}
        onSubmit={(params) => {
          setOilType(params.oilType)
          setSpillAmount(params.spillAmount)
          setSpillType(params.spillType)
          setPredictionTime(params.predictionTime)
          setIncidentCoord(params.incidentCoord)
          setSelectedModels(params.selectedModels)
          handleRunSimulation()
        }}
      />

      {/* 역추적 모달 */}
      <BacktrackModal
        isOpen={backtrackModalOpen}
        onClose={() => setBacktrackModalOpen(false)}
        phase={backtrackPhase}
        conditions={backtrackConditions}
        vessels={backtrackVessels}
        onRunAnalysis={handleRunBacktrackAnalysis}
        onStartReplay={handleStartReplay}
      />
    </div>
  )
}
