import { useState, useEffect, useCallback } from 'react';
import { fetchRescueOps, fetchRescueScenarios } from '../services/rescueApi';
import type {
  RescueOpsItem,
  RescueScenarioItem,
  RescueScenario,
  ChartDataItem,
} from '@interfaces/rescue/RescueInterface';
import type { Severity } from '@/types/rescue/RescueType';
import { ScenarioMapOverlay } from './contents/ScenarioMapOverlay';
import { NewScenarioModal } from './contents/NewScenarioModal';
import { ScenarioComparison } from './contents/ScenarioComparison';
/* eslint-disable react-refresh/only-export-components */

/* ─── Types ─── */
type DetailView = 0 | 1 | 2;

export const SEV_STYLE: Record<Severity, { bg: string; color: string; label: string }> = {
  CRITICAL: { bg: 'rgba(239,68,68,0.15)', color: 'var(--color-danger)', label: 'CRITICAL' },
  HIGH: { bg: 'rgba(249,115,22,0.15)', color: 'var(--color-warning)', label: 'HIGH' },
  MEDIUM: { bg: 'rgba(234,179,8,0.15)', color: 'var(--color-caution)', label: 'MEDIUM' },
  RESOLVED: { bg: 'rgba(34,197,94,0.15)', color: 'var(--color-success)', label: 'RESOLVED' },
};

export const SEV_COLOR: Record<Severity, string> = {
  CRITICAL: 'var(--color-danger)',
  HIGH: 'var(--color-warning)',
  MEDIUM: 'var(--color-caution)',
  RESOLVED: 'var(--color-success)',
};

/* ─── Color helpers ─── */
export function gmColor(v: number) {
  return v < 1.0
    ? 'var(--color-danger)'
    : v < 1.5
      ? 'var(--color-caution)'
      : 'var(--color-success)';
}
export function listColor(v: number) {
  return v > 20 ? 'var(--color-danger)' : v > 10 ? 'var(--color-caution)' : 'var(--color-success)';
}
export function buoyColor(v: number) {
  return v < 30 ? 'var(--color-danger)' : v < 50 ? 'var(--color-caution)' : 'var(--color-success)';
}
export function oilColor(v: number) {
  return v > 100
    ? 'var(--color-danger)'
    : v > 30
      ? 'var(--color-warning)'
      : v > 0
        ? 'var(--color-caution)'
        : 'var(--color-success)';
}

/* ─── API 시나리오 → 로컬 타입 변환 ─── */
function toRescueScenario(s: RescueScenarioItem, i: number): RescueScenario {
  return {
    id: `S-${String(i + 1).padStart(2, '0')}`,
    name: s.description?.split('.')[0] ?? s.timeStep,
    severity: s.svrtCd as Severity,
    timeStep: s.timeStep,
    datetime: s.scenarioDtm
      ? new Date(s.scenarioDtm).toLocaleString('ko-KR', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
        }) + ' KST'
      : '—',
    gm: String(s.gmM ?? 0),
    list: String(s.listDeg ?? 0),
    trim: String(s.trimM ?? 0),
    buoyancy: s.buoyancyPct ?? 0,
    oilRate: s.oilRateLpm != null ? `${s.oilRateLpm} L/min` : '— L/min',
    bmRatio: s.bmRatioPct != null ? `${s.bmRatioPct}%` : '—%',
    description: s.description ?? '',
    compartments: s.compartments ?? [],
    assessment: s.assessment ?? [],
    actions: s.actions ?? [],
  };
}

/* ─── 시나리오 관리 요건 ─── */
const SCENARIO_MGMT_GUIDELINES = [
  '긴급구난 R&D 분석 결과는 시간 단계별 시나리오의 형태로 관리되어야 함',
  '각 시나리오는 사고 발생 시점부터 구난 진행 단계별 상태 변화를 포함하여야 함',
  '시나리오별 분석 결과는 사고 단위로 기존 사고 정보와 연계되어 관리되어야 함',
  '동일 사고에 대해 복수 시나리오(시간대, 조건별)가 존재할 경우, 상호 비교·검토가 되어야 함',
  '시나리오별 분석결과는 긴급구난 대응 판단을 지원할 수 있도록 요약 정보 형태로 제공되어야 함',
  '시나리오 관리 기능은 기존 통합지원시스템의 흐름과 연계되어 실질적인 구난 대응 업무에 활용 가능하도록 반영되어야 함',
  '긴급구난 시나리오 관리 기능 구현 시 1차 구축 완료된 GIS기능을 활용하여 구축하여 재개발하거나 중복구현하지 않도록 함',
];

/* ─── Mock 시나리오 (API 미연결 시 폴백) — 긴급구난 모델 이론 기반 10개 ─── */
const MOCK_SCENARIOS: RescueScenarioItem[] = [
  {
    scenarioSn: 1,
    rescueOpsSn: 1,
    timeStep: 'T+0h',
    scenarioDtm: '2024-10-27T01:30:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.8,
    listDeg: 15.0,
    trimM: 2.5,
    buoyancyPct: 30.0,
    oilRateLpm: 100.0,
    bmRatioPct: 92.0,
    description:
      '좌현 35° 충돌로 No.1P 화물탱크 파공. 벙커C유 유출 개시. 손상복원성 분석: 초기 GM 0.8m으로 IMO 기준(1.0m) 미달, 복원력 위험 판정.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'BREACHED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'RISK', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '위험 (GM 0.8m < IMO 1.0m)', color: 'var(--red)' },
      { label: '유출 위험', value: '활발 유출중 (100 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 92% (경계)', color: 'var(--orange)' },
      { label: '승선인원', value: '15/20 확인, 5명 수색중', color: 'var(--red)' },
    ],
    actions: [
      { time: '10:30', text: '충돌 발생, VHF Ch.16 조난 통보', color: 'var(--red)' },
      { time: '10:32', text: 'EPIRB 자동 발신 확인', color: 'var(--red)' },
      { time: '10:35', text: '해경 3009함 출동 지시', color: 'var(--orange)' },
      { time: '10:42', text: '인근 선박 구조 활동 개시', color: 'var(--cyan)' },
    ],
    sortOrd: 1,
  },
  {
    scenarioSn: 2,
    rescueOpsSn: 1,
    timeStep: 'T+30m',
    scenarioDtm: '2024-10-27T02:00:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.7,
    listDeg: 17.0,
    trimM: 2.8,
    buoyancyPct: 28.0,
    oilRateLpm: 120.0,
    bmRatioPct: 90.0,
    description:
      '잠수사 수중 조사 결과 좌현 No.1P 파공 크기 1.2m×0.8m 확인. Bernoulli 유입률 모델 적용: 수두차 4.5m 기준 유입률 약 2.1㎥/min.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'BREACHED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'RISK', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '악화 (GM 0.7m, GZ 커브 감소)', color: 'var(--red)' },
      { label: '유출 위험', value: '증가 (120 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 90% — 종강도 모니터링 개시', color: 'var(--orange)' },
      { label: '승선인원', value: '15명 퇴선, 5명 수색중', color: 'var(--red)' },
    ],
    actions: [
      { time: '10:50', text: '잠수사 투입, 수중 손상 조사 개시', color: 'var(--cyan)' },
      { time: '10:55', text: '파공 규모 확인: 1.2m×0.8m', color: 'var(--red)' },
      { time: '11:00', text: '손상복원성 재계산 — IMO 기준 위험', color: 'var(--red)' },
      { time: '11:00', text: '유출유 방제선 배치 요청', color: 'var(--orange)' },
    ],
    sortOrd: 2,
  },
  {
    scenarioSn: 3,
    rescueOpsSn: 1,
    timeStep: 'T+1h',
    scenarioDtm: '2024-10-27T02:30:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.65,
    listDeg: 18.5,
    trimM: 3.0,
    buoyancyPct: 26.0,
    oilRateLpm: 135.0,
    bmRatioPct: 89.0,
    description:
      '해경 3009함 현장 도착, SAR 작전 개시. Leeway 표류 예측 모델: 풍속 8m/s, 해류 2.5kn NE — 실종자 표류 반경 1.2nm. GZ 최대 복원력 각도 25°로 감소.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'FLOODING', color: 'var(--red)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '한계 접근 (GM 0.65m)', color: 'var(--red)' },
      { label: '유출 위험', value: '파공 확대 우려 (135 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 89% — Hogging 증가', color: 'var(--orange)' },
      { label: '인명구조', value: '실종 5명 수색중, 표류 1.2nm', color: 'var(--red)' },
    ],
    actions: [
      { time: '11:10', text: '해경 3009함 현장 도착, SAR 구역 설정', color: 'var(--cyan)' },
      { time: '11:15', text: 'Leeway 표류 예측 모델 적용', color: 'var(--cyan)' },
      { time: '11:20', text: '회전익 항공기 수색 개시', color: 'var(--cyan)' },
      { time: '11:30', text: '#2 Port Tank 2차 침수 징후', color: 'var(--red)' },
    ],
    sortOrd: 3,
  },
  {
    scenarioSn: 4,
    rescueOpsSn: 1,
    timeStep: 'T+2h',
    scenarioDtm: '2024-10-27T03:30:00.000Z',
    svrtCd: 'CRITICAL',
    gmM: 0.5,
    listDeg: 20.0,
    trimM: 3.5,
    buoyancyPct: 22.0,
    oilRateLpm: 160.0,
    bmRatioPct: 86.0,
    description:
      '격벽 관통으로 #2 Port Tank 침수 확대. 자유표면효과(FSE) 보정: GM_fluid = 0.5m. 종강도: Sagging 모멘트 86%. 침몰 위험 단계 진입.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: 'Engine Room', status: 'RISK', color: 'var(--orange)' },
      { name: '#3 Stbd Tank', status: 'INTACT', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '위기 (GM 0.5m, FSE 보정)', color: 'var(--red)' },
      { label: '유출 위험', value: '최대치 접근 (160 L/min)', color: 'var(--red)' },
      { label: '선체 강도', value: 'BM 86% — Sagging 경고', color: 'var(--red)' },
      { label: '승선인원', value: '실종 3명 발견, 2명 수색', color: 'var(--orange)' },
    ],
    actions: [
      { time: '12:00', text: '#2 Port Tank 격벽 관통 침수', color: 'var(--red)' },
      { time: '12:10', text: '자유표면효과(FSE) 보정 재계산', color: 'var(--red)' },
      { time: '12:15', text: '긴급 Counter-Flooding 검토', color: 'var(--orange)' },
      { time: '12:30', text: '실종자 3명 추가 발견 구조', color: 'var(--green)' },
    ],
    sortOrd: 4,
  },
  {
    scenarioSn: 5,
    rescueOpsSn: 1,
    timeStep: 'T+3h',
    scenarioDtm: '2024-10-27T04:30:00.000Z',
    svrtCd: 'HIGH',
    gmM: 0.55,
    listDeg: 16.0,
    trimM: 3.2,
    buoyancyPct: 25.0,
    oilRateLpm: 140.0,
    bmRatioPct: 87.0,
    description:
      'Counter-Flooding 실시: #3 Stbd Tank에 평형수 280톤 주입, 횡경사 20°→16° 교정. 종강도: 중량 재배분으로 BM 87% 유지.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#2 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: 'Engine Room', status: 'RISK', color: 'var(--orange)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '개선 중 (GM 0.55m, 경사 16°)', color: 'var(--orange)' },
      { label: '유출 위험', value: '감소 추세 (140 L/min)', color: 'var(--orange)' },
      { label: '선체 강도', value: 'BM 87% — Counter-Flooding 평가', color: 'var(--orange)' },
      { label: '구조 상황', value: '실종 2명 수색 지속', color: 'var(--orange)' },
    ],
    actions: [
      { time: '12:45', text: 'Counter-Flooding — #3 Stbd 주입 개시', color: 'var(--orange)' },
      { time: '13:00', text: '평형수 280톤 주입, 경사 교정 진행', color: 'var(--cyan)' },
      { time: '13:15', text: '종강도 재계산 — 허용 범위 내', color: 'var(--cyan)' },
      { time: '13:30', text: '횡경사 16° 안정화 확인', color: 'var(--green)' },
    ],
    sortOrd: 5,
  },
  {
    scenarioSn: 6,
    rescueOpsSn: 1,
    timeStep: 'T+6h',
    scenarioDtm: '2024-10-27T07:30:00.000Z',
    svrtCd: 'HIGH',
    gmM: 0.7,
    listDeg: 12.0,
    trimM: 2.5,
    buoyancyPct: 32.0,
    oilRateLpm: 80.0,
    bmRatioPct: 90.0,
    description:
      '수중패치 설치, 유입률 감소. GM 0.7m 회복. Trim/Stability Booklet 기준 예인 가능 최소 조건(GM≥0.5m, List≤15°) 충족.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '개선 (GM 0.7m, 예인 가능)', color: 'var(--orange)' },
      { label: '유출 위험', value: '수중패치 효과 (80 L/min)', color: 'var(--orange)' },
      { label: '선체 강도', value: 'BM 90% — 안정 범위', color: 'var(--green)' },
      { label: '구조 상황', value: '전원 구조 완료', color: 'var(--green)' },
    ],
    actions: [
      { time: '14:00', text: '수중패치 설치 작업 개시', color: 'var(--cyan)' },
      { time: '14:30', text: '수중패치 설치 완료', color: 'var(--green)' },
      { time: '15:00', text: '해상크레인 도착, 잔류유 이적 준비', color: 'var(--cyan)' },
      { time: '16:30', text: '잔류유 1차 이적 완료 (45kL)', color: 'var(--green)' },
    ],
    sortOrd: 6,
  },
  {
    scenarioSn: 7,
    rescueOpsSn: 1,
    timeStep: 'T+8h',
    scenarioDtm: '2024-10-27T09:30:00.000Z',
    svrtCd: 'MEDIUM',
    gmM: 0.8,
    listDeg: 10.0,
    trimM: 2.0,
    buoyancyPct: 38.0,
    oilRateLpm: 55.0,
    bmRatioPct: 91.0,
    description:
      '오일붐 2중 전개, 유회수기 3대 가동. GNOME 확산 모델: 12시간 후 확산 면적 2.3km² 예측. 기계적 회수율 35%.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '안정 (GM 0.8m)', color: 'var(--orange)' },
      { label: '유출 위험', value: '방제 진행 (55 L/min, 회수 35%)', color: 'var(--orange)' },
      { label: '선체 강도', value: 'BM 91%', color: 'var(--green)' },
      { label: '방제 현황', value: '오일붐 2중, 유회수기 3대', color: 'var(--cyan)' },
    ],
    actions: [
      { time: '17:00', text: '오일붐 1차 전개 (500m)', color: 'var(--cyan)' },
      { time: '17:30', text: '오일붐 2차 전개 (이중 방어선)', color: 'var(--cyan)' },
      { time: '17:45', text: '유회수기 3대 배치·가동', color: 'var(--cyan)' },
      { time: '18:30', text: 'GNOME 확산 예측 갱신', color: 'var(--orange)' },
    ],
    sortOrd: 7,
  },
  {
    scenarioSn: 8,
    rescueOpsSn: 1,
    timeStep: 'T+12h',
    scenarioDtm: '2024-10-27T13:30:00.000Z',
    svrtCd: 'MEDIUM',
    gmM: 0.9,
    listDeg: 8.0,
    trimM: 1.5,
    buoyancyPct: 45.0,
    oilRateLpm: 30.0,
    bmRatioPct: 94.0,
    description:
      '예인 개시. 예인 저항 Rt=1/2·ρ·Cd·A·V²  기반 4,000HP급 배정. 목포항 42nm, 예인 속도 3kn, ETA 14h.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'BALLASTED', color: 'var(--orange)' },
    ],
    assessment: [
      { label: '복원력', value: '안정 (GM 0.9m)', color: 'var(--orange)' },
      { label: '유출 위험', value: '억제 중 (30 L/min)', color: 'var(--green)' },
      { label: '선체 강도', value: 'BM 94%', color: 'var(--green)' },
      { label: '예인 상태', value: '목포항, ETA 14h, 3kn', color: 'var(--cyan)' },
    ],
    actions: [
      { time: '18:00', text: '예인 접속, 예인삭 250m 전개', color: 'var(--cyan)' },
      { time: '18:30', text: '예인 개시 (목포항 방향)', color: 'var(--cyan)' },
      { time: '20:00', text: '야간 감시 체제 전환', color: 'var(--orange)' },
      { time: '22:30', text: '예인 진행률 30%, 선체 안정', color: 'var(--green)' },
    ],
    sortOrd: 8,
  },
  {
    scenarioSn: 9,
    rescueOpsSn: 1,
    timeStep: 'T+18h',
    scenarioDtm: '2024-10-27T19:30:00.000Z',
    svrtCd: 'MEDIUM',
    gmM: 1.0,
    listDeg: 5.0,
    trimM: 1.0,
    buoyancyPct: 55.0,
    oilRateLpm: 15.0,
    bmRatioPct: 96.0,
    description:
      '예인 진행률 65%. 파랑 응답 분석(RAO): 유의파고 1.2m, 주기 6s — 횡동요 ±3° 안전 범위. 잔류 유출률 15 L/min.',
    compartments: [
      { name: '#1 FP Tank', status: 'FLOODED', color: 'var(--red)' },
      { name: '#1 Port Tank', status: 'PATCHED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'STABLE', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '양호 (GM 1.0m, IMO 충족)', color: 'var(--green)' },
      { label: '유출 위험', value: '미량 유출 (15 L/min)', color: 'var(--green)' },
      { label: '선체 강도', value: 'BM 96% 정상', color: 'var(--green)' },
      { label: '예인 상태', value: '진행률 65%, ETA 5.5h', color: 'var(--cyan)' },
    ],
    actions: [
      { time: '00:00', text: '야간 예인 정상 진행', color: 'var(--green)' },
      { time: '02:00', text: '파랑 응답 분석 — 안전 확인', color: 'var(--green)' },
      { time: '03:00', text: '잔류유 유출률 15 L/min', color: 'var(--green)' },
      { time: '04:30', text: '목포항 VTS 통보, 입항 협의', color: 'var(--cyan)' },
    ],
    sortOrd: 9,
  },
  {
    scenarioSn: 10,
    rescueOpsSn: 1,
    timeStep: 'T+24h',
    scenarioDtm: '2024-10-28T01:30:00.000Z',
    svrtCd: 'RESOLVED',
    gmM: 1.2,
    listDeg: 3.0,
    trimM: 0.5,
    buoyancyPct: 75.0,
    oilRateLpm: 5.0,
    bmRatioPct: 98.0,
    description:
      '목포항 접안 완료. 잔류유 전량 이적(120kL). 최종 GM 1.2m IMO 충족, BM 98% 정상. 방제 총 회수량 85kL (회수율 71%). 상황 종료.',
    compartments: [
      { name: '#1 FP Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: '#1 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: '#2 Port Tank', status: 'SEALED', color: 'var(--orange)' },
      { name: 'Engine Room', status: 'INTACT', color: 'var(--green)' },
      { name: '#3 Stbd Tank', status: 'STABLE', color: 'var(--green)' },
    ],
    assessment: [
      { label: '복원력', value: '안전 (GM 1.2m)', color: 'var(--green)' },
      { label: '유출 위험', value: '차단 완료', color: 'var(--green)' },
      { label: '선체 강도', value: 'BM 98% 정상', color: 'var(--green)' },
      { label: '최종 상태', value: '접안 완료, 상황 종료', color: 'var(--green)' },
    ],
    actions: [
      { time: '06:00', text: '목포항 접근, 도선사 대기', color: 'var(--cyan)' },
      { time: '08:00', text: '도선사 승선, 접안 개시', color: 'var(--cyan)' },
      { time: '09:30', text: '접안 완료, 잔류유 이적선 접현', color: 'var(--green)' },
      { time: '10:30', text: '잔류유 전량 이적, 상황 종료', color: 'var(--green)' },
    ],
    sortOrd: 10,
  },
];

const MOCK_OPS: RescueOpsItem[] = [
  {
    rescueOpsSn: 1,
    acdntSn: 1,
    opsCd: 'RSC-2026-001',
    acdntTpCd: 'collision',
    vesselNm: 'M/V SEA GUARDIAN',
    commanderNm: null,
    lon: 126.25,
    lat: 37.467,
    locDc: "37°28'N, 126°15'E",
    depthM: 25.0,
    currentDc: '2.5kn NE',
    gmM: 0.8,
    listDeg: 15.0,
    trimM: 2.5,
    buoyancyPct: 30.0,
    oilRateLpm: 100.0,
    bmRatioPct: 92.0,
    totalCrew: 20,
    survivors: 15,
    missing: 5,
    hydroData: null,
    gmdssData: null,
    sttsCd: 'ACTIVE',
    regDtm: '2024-10-27T01:30:00.000Z',
  },
];

/* ═══════════════════════════════════════════════════════════════════
   RescueScenarioView
   ═══════════════════════════════════════════════════════════════════ */
export function RescueScenarioView() {
  const [ops, setOps] = useState<RescueOpsItem[]>([]);
  const [apiScenarios, setApiScenarios] = useState<RescueScenarioItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [selectedIncident, setSelectedIncident] = useState(0);
  const [checked, setChecked] = useState<Set<string>>(new Set());
  const [selectedId, setSelectedId] = useState('');
  const [sortBy, setSortBy] = useState<'time' | 'risk'>('time');
  const [detailView, setDetailView] = useState<DetailView>(0);
  const [newScnModalOpen, setNewScnModalOpen] = useState(false);
  const [guideOpen, setGuideOpen] = useState(false);

  const loadScenarios = useCallback(async (opsSn: number) => {
    setLoading(true);
    try {
      const items = await fetchRescueScenarios(opsSn);
      setApiScenarios(items.length > 0 ? items : MOCK_SCENARIOS);
    } catch {
      setApiScenarios(MOCK_SCENARIOS);
    } finally {
      setLoading(false);
    }
  }, []);

  const loadOps = useCallback(async () => {
    try {
      const items = await fetchRescueOps();
      if (items.length > 0) {
        setOps(items);
        loadScenarios(items[0].rescueOpsSn);
      } else {
        setOps(MOCK_OPS);
        setApiScenarios(MOCK_SCENARIOS);
        setLoading(false);
      }
    } catch {
      setOps(MOCK_OPS);
      setApiScenarios(MOCK_SCENARIOS);
      setLoading(false);
    }
  }, [loadScenarios]);

  useEffect(() => {
    loadOps();
  }, [loadOps]);

  useEffect(() => {
    if (ops.length > 0 && ops[selectedIncident]) {
      loadScenarios(ops[selectedIncident].rescueOpsSn);
    }
  }, [selectedIncident, ops, loadScenarios]);

  /* API 시나리오 → 로컬 타입 변환 */
  const scenarios: RescueScenario[] = apiScenarios.map(toRescueScenario);

  /* checked / selectedId: apiScenarios 변경 시 초기화 */
  useEffect(() => {
    setChecked(new Set(scenarios.map((s) => s.id)));
    if (scenarios.length > 0) setSelectedId(scenarios[0].id);
  }, [apiScenarios]); // eslint-disable-line react-hooks/exhaustive-deps

  /* chartData: scenarios에서 파생 */
  const chartData: ChartDataItem[] = scenarios.map((s) => ({
    id: s.id,
    label: s.timeStep,
    gm: parseFloat(s.gm),
    list: parseFloat(s.list),
    buoy: s.buoyancy,
    oil: parseFloat(s.oilRate),
    bm: parseFloat(s.bmRatio),
    severity: s.severity,
  }));

  const selected = scenarios.find((s) => s.id === selectedId);

  const sorted = [...scenarios].sort((a, b) => {
    if (sortBy === 'risk') {
      const order: Record<Severity, number> = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, RESOLVED: 3 };
      return order[a.severity] - order[b.severity];
    }
    return 0;
  });

  const toggleCheck = (id: string) => {
    setChecked((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  return (
    <div className="flex flex-col flex-1 w-full h-full overflow-hidden bg-bg-base">
      {/* ── Header ── */}
      <div className="px-5 py-3.5 border-b border-stroke flex items-center justify-between shrink-0">
        <div className="flex items-center gap-2.5">
          <span className="text-base">📊</span>
          <div>
            <div className="text-title-4 font-bold">긴급구난 시나리오 관리</div>
            <div className="text-label-2 text-fg-disabled">
              시간 단계별 시나리오 비교·검토 및 구난 의사결정 지원 (SFR-009)
            </div>
          </div>
        </div>
        <div className="flex gap-2 items-center">
          <select
            value={selectedIncident}
            onChange={(e) => setSelectedIncident(Number(e.target.value))}
            className="prd-i w-[280px] text-label-2"
          >
            {ops.map((op, i) => (
              <option key={op.rescueOpsSn} value={i}>
                {op.opsCd} · {op.vesselNm}
              </option>
            ))}
          </select>
          <button
            onClick={() => setNewScnModalOpen(true)}
            className="cursor-pointer whitespace-nowrap font-semibold text-color-accent text-label-2 px-[14px] py-1.5 rounded-sm"
            style={{
              border: '1px solid rgba(6,182,212,.3)',
              background: 'rgba(6,182,212,.08)',
            }}
          >
            + 신규 시나리오
          </button>
          <button
            onClick={() => setGuideOpen((v) => !v)}
            className="cursor-pointer whitespace-nowrap font-semibold text-label-2 px-[14px] py-1.5 rounded-sm"
            style={{
              border: '1px solid rgba(6,182,212,.15)',
              background: guideOpen ? 'rgba(6,182,212,.12)' : 'transparent',
              color: guideOpen ? 'var(--color-accent)' : 'var(--fg-disabled)',
            }}
          >
            {guideOpen ? '▴ 관리 요건' : '▾ 관리 요건'}
          </button>
        </div>
      </div>

      {/* ── 시나리오 관리 요건 가이드라인 ── */}
      {guideOpen && (
        <div className="border-b border-stroke px-5 py-3 bg-bg-surface shrink-0">
          <p className="text-label-1 font-bold mb-2">시나리오 관리 요건</p>
          <ul className="flex flex-col gap-1">
            {SCENARIO_MGMT_GUIDELINES.map((g, i) => (
              <li key={i} className="text-caption text-fg-sub leading-relaxed flex gap-1.5">
                <span className="text-color-accent shrink-0">{i + 1}.</span>
                <span>{g}</span>
              </li>
            ))}
          </ul>
        </div>
      )}

      {/* ── Content: Left List + Right Detail ── */}
      <div className="flex flex-1 overflow-hidden">
        {/* ═══ LEFT: 시나리오 목록 ═══ */}
        <div
          className="flex flex-col overflow-hidden shrink-0 border-r border-stroke bg-bg-surface"
          style={{ width: '370px', minWidth: '370px' }}
        >
          {/* Sort bar */}
          <div className="flex items-center justify-between border-b border-stroke px-[14px] py-2.5">
            <span className="text-label-2 font-bold text-fg-disabled">
              시나리오 목록 ({scenarios.length}개)
            </span>
            <div className="flex gap-1">
              {(['time', 'risk'] as const).map((s) => (
                <button
                  key={s}
                  onClick={() => setSortBy(s)}
                  className={`cursor-pointer px-2 py-[3px] text-caption font-semibold rounded-sm border border-stroke ${
                    sortBy === s
                      ? 'bg-[rgba(6,182,212,0.08)] text-color-accent'
                      : 'bg-bg-card text-fg-disabled'
                  }`}
                >
                  {s === 'time' ? '시간순' : '위험도순'}
                </button>
              ))}
            </div>
          </div>

          {/* Card list */}
          <div
            className="flex-1 overflow-y-auto flex flex-col gap-1.5 p-2"
            style={{ scrollbarWidth: 'thin', scrollbarColor: 'var(--stroke-light) transparent' }}
          >
            {loading && scenarios.length === 0 && (
              <div className="text-center py-10 text-label-2 text-fg-disabled">
                시나리오 로딩 중...
              </div>
            )}
            {sorted.map((sc) => {
              const isSel = selectedId === sc.id;
              const sev = SEV_STYLE[sc.severity];
              return (
                <div
                  key={sc.id}
                  onClick={() => setSelectedId(sc.id)}
                  className={`hns-scn-card${isSel ? ' sel' : ''}`}
                >
                  {/* Top: checkbox + ID + severity */}
                  <div className="flex items-center justify-between mb-1.5">
                    <div className="flex items-center gap-1.5">
                      <input
                        type="checkbox"
                        checked={checked.has(sc.id)}
                        onChange={(e) => {
                          e.stopPropagation();
                          toggleCheck(sc.id);
                        }}
                        style={{ accentColor: 'var(--color-accent)' }}
                      />
                      <span className="text-label-1 font-bold">
                        {sc.id} {sc.name}
                      </span>
                    </div>
                    <span
                      className="font-bold px-2 py-[2px] rounded-lg text-caption"
                      style={{ background: sev.bg, color: sev.color }}
                    >
                      {sev.label}
                    </span>
                  </div>
                  {/* Time row */}
                  <div className="flex items-center gap-1.5 mb-1.5">
                    <span
                      className="font-bold font-mono text-color-accent text-caption px-1.5 py-[2px] rounded-[3px]"
                      style={{ background: 'rgba(6,182,212,0.1)' }}
                    >
                      {sc.timeStep}
                    </span>
                    <span className="text-caption text-fg-disabled font-mono">{sc.datetime}</span>
                  </div>
                  {/* KPI grid */}
                  <div className="grid grid-cols-4 gap-1 font-mono text-caption">
                    {[
                      { label: 'GM', value: `${sc.gm}m`, color: gmColor(parseFloat(sc.gm)) },
                      {
                        label: '횡경사',
                        value: `${sc.list}°`,
                        color: listColor(parseFloat(sc.list)),
                      },
                      { label: '부력', value: `${sc.buoyancy}%`, color: buoyColor(sc.buoyancy) },
                      {
                        label: '유출',
                        value: sc.oilRate.split(' ')[0],
                        color: oilColor(parseFloat(sc.oilRate)),
                      },
                    ].map((m, i) => (
                      <div key={i} className="text-center p-[3px] bg-bg-base rounded-[3px]">
                        <div className="text-fg-disabled text-caption">{m.label}</div>
                        <div className="font-bold" style={{ color: m.color }}>
                          {m.value}
                        </div>
                      </div>
                    ))}
                  </div>
                  {/* Description */}
                  <div className="text-fg-sub mt-1.5 text-caption leading-[1.4]">
                    {sc.description}
                  </div>
                </div>
              );
            })}
          </div>

          {/* Bottom actions */}
          <div className="flex gap-2 border-t border-stroke px-[14px] py-2.5">
            <button
              onClick={() => setDetailView(1)}
              className="flex-1 cursor-pointer font-bold text-static-white text-label-2 p-2 rounded-sm bg-color-navy hover:bg-color-navy-hover"
            >
              📊 선택 시나리오 비교
            </button>
            <button className="cursor-pointer font-semibold text-fg-sub text-label-2 px-[14px] py-2 rounded-sm bg-bg-card border border-stroke">
              📄 보고서
            </button>
          </div>
        </div>

        {/* ═══ RIGHT: 상세/비교 ═══ */}
        <div className="flex-1 min-w-0 flex flex-col overflow-hidden">
          {/* Detail tabs */}
          <div className="flex border-b border-stroke shrink-0 px-4 bg-bg-surface">
            {(['📋 시나리오 상세', '📊 비교 차트', '🗺 지도 오버레이'] as const).map((label, i) => (
              <button
                key={i}
                onClick={() => setDetailView(i as DetailView)}
                className={`rsc-atab ${detailView === i ? 'on' : ''}`}
              >
                {label}
              </button>
            ))}
          </div>

          {/* View content */}
          <div
            className={`flex-1 ${detailView === 2 ? 'flex flex-col overflow-hidden' : 'overflow-y-auto scrollbar-thin'}`}
          >
            {/* ─── VIEW 0: 시나리오 상세 ─── */}
            {detailView === 0 && selected && (
              <div className="p-5">
                {/* Header card */}
                <div className="px-5 py-4 rounded-[10px] bg-bg-card border border-stroke mb-4">
                  <div className="flex items-center gap-2.5 mb-2.5">
                    <span className="text-base font-extrabold font-mono text-color-accent">
                      {selected.id}
                    </span>
                    <span className="text-label-1 font-bold">{selected.name}</span>
                    <span
                      className="px-2 py-[2px] rounded-lg text-caption font-bold font-mono"
                      style={{
                        background: SEV_STYLE[selected.severity].bg,
                        color: SEV_STYLE[selected.severity].color,
                      }}
                    >
                      {selected.severity}
                    </span>
                    <span className="ml-auto text-label-2 text-fg-disabled font-mono">
                      {selected.datetime}
                    </span>
                  </div>
                  {/* 6 KPI cards */}
                  <div
                    className="grid gap-2 text-caption text-center"
                    style={{ gridTemplateColumns: 'repeat(6,1fr)' }}
                  >
                    {[
                      {
                        label: 'GM (복원심)',
                        value: `${selected.gm}m`,
                        color: gmColor(parseFloat(selected.gm)),
                      },
                      {
                        label: '횡경사 (List)',
                        value: `${selected.list}°`,
                        color: listColor(parseFloat(selected.list)),
                      },
                      {
                        label: '종경사 (Trim)',
                        value: `${selected.trim}m`,
                        color:
                          parseFloat(selected.trim) > 3
                            ? 'var(--color-danger)'
                            : 'var(--fg-default)',
                      },
                      {
                        label: '잔존부력',
                        value: `${selected.buoyancy}%`,
                        color: buoyColor(selected.buoyancy),
                      },
                      {
                        label: '유출률',
                        value: selected.oilRate,
                        color: oilColor(parseFloat(selected.oilRate)),
                      },
                      {
                        label: 'BM 비율',
                        value: selected.bmRatio,
                        color:
                          parseFloat(selected.bmRatio) > 100
                            ? 'var(--color-danger)'
                            : parseFloat(selected.bmRatio) > 85
                              ? 'var(--color-warning)'
                              : 'var(--color-success)',
                      },
                    ].map((kpi) => (
                      <div
                        key={kpi.label}
                        className="px-1 py-2 bg-bg-card rounded-md border border-stroke"
                      >
                        <div className="text-fg-disabled mb-1">{kpi.label}</div>
                        <div
                          className="text-lg font-extrabold font-mono"
                          style={{ color: kpi.color }}
                        >
                          {kpi.value}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>

                {/* 2-column: 침수구획 + 구난판단 */}
                <div className="grid grid-cols-2 gap-4 mb-4">
                  {/* 침수 구획 */}
                  <div className="bg-bg-card border border-stroke rounded-md p-3.5">
                    <div className="text-label-2 font-bold mb-2.5">🚢 침수 구획 상태</div>
                    <div className="flex flex-col gap-1.5">
                      {selected.compartments.map((c, i) => (
                        <div
                          key={i}
                          className="flex items-center justify-between px-2.5 py-1.5 bg-bg-base rounded"
                          style={{ borderLeft: `3px solid ${c.color}` }}
                        >
                          <span className="text-caption">{c.name}</span>
                          <span
                            className="text-caption font-semibold font-mono"
                            style={{ color: c.color }}
                          >
                            {c.status}
                          </span>
                        </div>
                      ))}
                    </div>
                  </div>
                  {/* 구난 판단 */}
                  <div className="bg-bg-card border border-stroke rounded-md p-3.5">
                    <div className="text-label-2 font-bold mb-2.5">⚠️ 구난 판단 요약</div>
                    <div className="flex flex-col gap-1.5">
                      {selected.assessment.map((a, i) => (
                        <div
                          key={i}
                          className="px-2.5 py-2 bg-bg-base rounded"
                          style={{ borderLeft: `3px solid ${a.color}` }}
                        >
                          <div className="text-caption font-bold" style={{ color: a.color }}>
                            {a.label}
                          </div>
                          <div className="text-caption text-fg-sub mt-0.5">{a.value}</div>
                        </div>
                      ))}
                    </div>
                  </div>
                </div>

                {/* 대응 조치 이력 */}
                <div className="bg-bg-card border border-stroke rounded-md p-3.5">
                  <div className="text-label-2 font-bold mb-2.5">📋 대응 조치 이력</div>
                  <div className="flex flex-col gap-1.5">
                    {selected.actions.map((a, i) => (
                      <div
                        key={i}
                        className="flex items-center gap-2.5 px-2.5 py-1.5 bg-bg-base rounded"
                      >
                        <span
                          className="text-label-2 font-bold font-mono min-w-[40px]"
                          style={{ color: a.color }}
                        >
                          {a.time}
                        </span>
                        <div
                          className="w-1.5 h-1.5 rounded-full shrink-0"
                          style={{ background: a.color }}
                        />
                        <span className="text-caption">{a.text}</span>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            )}

            {/* ─── VIEW 1: 비교 차트 ─── */}
            {detailView === 1 && <ScenarioComparison chartData={chartData} />}

            {/* ─── VIEW 2: 지도 오버레이 ─── */}
            {detailView === 2 && (
              <ScenarioMapOverlay
                ops={ops}
                selectedIncident={selectedIncident}
                scenarios={scenarios}
                selectedId={selectedId}
                checked={checked}
                onSelectScenario={setSelectedId}
              />
            )}
          </div>
        </div>
      </div>

      {/* ═══ 신규 시나리오 모달 ═══ */}
      {newScnModalOpen && <NewScenarioModal ops={ops} onClose={() => setNewScnModalOpen(false)} />}
    </div>
  );
}

