import type { Ship, ShipCategory } from '../types';

// ═══ S&P Global Maritime AIS API v1.3 ═══
// Base URL: https://aisapi.maritime.spglobal.com
// All methods use HTTP POST with Basic Authentication
// Content-Type: application/json

// Use Vite dev proxy to avoid CORS (proxied to https://aisapi.maritime.spglobal.com)
const SPG_BASE = '/api/ais';
const SPG_USERNAME = import.meta.env.VITE_SPG_USERNAME as string | undefined;
const SPG_PASSWORD = import.meta.env.VITE_SPG_PASSWORD as string | undefined;

// Middle East bounding box for GetTargetsInAreaEnhanced
const ME_BOUNDS = {
  minLat: 10,
  maxLat: 42,
  minLng: 30,
  maxLng: 65,
};

// Korea region bounding box: Vladivostok → South China Sea
const KR_BOUNDS = {
  minLat: 10,
  maxLat: 45,
  minLng: 115,
  maxLng: 145,
};

// Iran / Strait of Hormuz bounding box for signal-batch
const IRAN_BOUNDS = {
  minLat: 20,
  maxLat: 30,
  minLng: 48,
  maxLng: 62,
};

// S&P API sinceSeconds — currently disabled, will be removed with S&P code
// const SINCE_SECONDS = 3600;

// MMSI country prefix → flag code (MID = Maritime Identification Digits)
const MMSI_FLAG_MAP: Record<string, string> = {
  '440': 'KR', '441': 'KR',  // South Korea
  '338': 'US', '303': 'US', '366': 'US', '367': 'US', '368': 'US', '369': 'US',
  '232': 'UK', '233': 'UK', '234': 'UK', '235': 'UK',
  '226': 'FR', '227': 'FR', '228': 'FR',
  '211': 'DE',
  '422': 'IR',
  '431': 'JP', '432': 'JP',
  '412': 'CN', '413': 'CN', '414': 'CN',
  '525': 'ID',
  '533': 'MY',
  '548': 'PH',
  '477': 'HK',
  '538': 'MH',
  '636': 'LR',
  '352': 'PA', '353': 'PA', '354': 'PA', '355': 'PA', '356': 'PA', '357': 'PA',
};

// Known naval vessel MMSI prefixes
const NAVAL_MMSI_PREFIXES: Record<string, { flag: string; category: ShipCategory }> = {
  '338': { flag: 'US', category: 'warship' },
  '369': { flag: 'US', category: 'warship' },
  '303': { flag: 'US', category: 'warship' },
};

// Known vessel name patterns
const MILITARY_NAME_PATTERNS: [RegExp, ShipCategory][] = [
  [/\bCVN\b|NIMITZ|\bFORD\b|EISENHOWER|LINCOLN|REAGAN|VINSON|STENNIS|TRUMAN|WASHINGTON|BUSH/i, 'carrier'],
  [/\bDDG\b|\bDDH\b|DESTROYER|ARLEIGH|BURKE|ZUMWALT|SEJONG|CHUNGMUGONG|GWANGGAETO/i, 'destroyer'],
  [/\bSSN\b|\bSS\b.*SUBMARINE/i, 'submarine'],
  [/\bCG\b|CRUISER|TICONDEROGA/i, 'warship'],
  [/\bLHD\b|\bLHA\b|AMPHIBIOUS|WASP|AMERICA|BATAAN|DOKDO|MARADO/i, 'warship'],
  [/\bPATROL\b|\bPC\b|\bMCM\b|\bLCS\b|\bPCC\b|\bFFG\b|\bFF\b|FRIGATE|INCHEON|DAEGU|ULSAN|COAST\s*GUARD|해경|KCG|해양경찰|SAMBONG|TAEPYEONGYANG/i, 'patrol'],
  [/\bROKS\b|\bUSS\b|\bHMS\b|\bFS\b|\bIRGCN\b/i, 'warship'],
];

// S&P Global AIS VesselType string → our ShipCategory
const SPG_VESSEL_TYPE_MAP: Record<string, ShipCategory> = {
  'Cargo': 'cargo',
  'Bulk Carrier': 'cargo',
  'Container Ship': 'cargo',
  'General Cargo': 'cargo',
  'Tanker': 'tanker',
  'Passenger': 'civilian',
  'Tug': 'civilian',
  'Fishing': 'fishing',
  'Pilot Boat': 'civilian',
  'Tender': 'civilian',
  'Vessel': 'civilian',
  'High Speed Craft': 'civilian',
  'Search And Rescue': 'patrol',
  'Law Enforcement': 'patrol',
  'Anti Pollution': 'civilian',
  'Wing In Ground-effect': 'civilian',
  'Medical Transport': 'civilian',
  'N/A': 'unknown',
};

export function classifyShip(name: string, mmsi: string, vesselType?: string): ShipCategory {
  // 1. Check name patterns first (most reliable for military)
  for (const [pattern, cat] of MILITARY_NAME_PATTERNS) {
    if (pattern.test(name)) {
      if (cat === 'carrier') console.log(`[CARRIER by name] "${name}" mmsi=${mmsi} vesselType=${vesselType}`);
      return cat;
    }
  }
  // 2. Check S&P AIS VesselType
  if (vesselType) {
    const mapped = SPG_VESSEL_TYPE_MAP[vesselType];
    if (mapped) return mapped;
    // Partial match fallback
    const lower = vesselType.toLowerCase();
    if (lower.includes('tanker')) return 'tanker';
    if (lower.includes('cargo') || lower.includes('container') || lower.includes('bulk') || lower.includes('carrier')) return 'cargo';
    if (lower.includes('passenger') || lower.includes('cruise') || lower.includes('ferry')) return 'civilian';
    if (lower.includes('naval') || lower.includes('military')) return 'warship';
    if (lower.includes('patrol') || lower.includes('law enforcement')) return 'patrol';
  }
  // 3. Check MMSI prefix
  const prefix = mmsi.slice(0, 3);
  if (NAVAL_MMSI_PREFIXES[prefix]) return NAVAL_MMSI_PREFIXES[prefix].category;
  return 'civilian';
}

function getFlagFromMMSI(mmsi: string): string | undefined {
  const mid = mmsi.slice(0, 3);
  return MMSI_FLAG_MAP[mid];
}

// ═══ S&P Global AIS API Response Types (Appendix D) ═══

interface SPGAISTarget {
  // Core AIS fields
  MMSI: string;
  IMO: string;
  Name: string;
  Callsign: string;
  VesselType: string;       // "Cargo", "Tanker", "Passenger", etc.
  Lat: number;
  Lon: number;
  Heading: number;          // True Heading or CoG if True Heading absent
  CoG: number;              // Course Over Ground (max 359.9)
  SoG: number;              // Speed Over Ground (knots)
  Status: string;           // "Under way using engine", "Anchored", "Moored", etc.
  Destination: string;
  DestinationTidied: string;
  ETA: string;              // ISO format
  Draught: number;
  Length: number;
  Width: number;

  // Timestamps
  TimestampUTC: number;     // UTC Seconds only
  MessageTimestamp: string;  // ISO format
  ReceivedDate: string;     // ISO format
  AgeMinutes: number;

  // Enhanced data
  DWT: number;              // Deadweight tonnage (-999 = unknown)
  STAT5CODE: string;        // 7-char ship type code
  Source: string;            // "ORB", "EXA", or "AIS"
  ExtraInfo: string;        // "Military Operations", "Fishing", etc.
  ImoVerified: string;
  TonnesCargo: number;

  // Position data
  PositionAccuracy: number;
  PositionFixType: number;
  RoT: number;              // Rate of Turn
  BandFlag: number;
  RAIMFlag: number;

  // Port/Zone
  ZoneId: number;
  LPCCode: string;          // Last Port of Call Code
  DestinationPortID: number;
  DestinationUNLOCODE: string;

  // Additional
  DTE: string;
  AISVersion: number;
  RadioStatus: number;
  RepeatIndicator: number;
  Anomalous: boolean;
  OnBerth: boolean;
  InSTS: number;
  StationId: number;
  LengthBow: number;
  LengthStern: number;
  WidthPort: number;
  WidthStarboard: number;
  LastStaticUpdateReceived: string;
  MessageType: string;
  Regional: number;
  Regional2: number;
  Spare: number;
  Spare2: number;
}

interface SPGAPIResponse {
  APSStatus: {
    CompletedOK: boolean;
    ErrorLevel: string;
    ErrorMessage: string;
    Guid: string;
    JobRunDate: string;
    RemedialAction: string;
    SystemDate: string;
    SystemVersion: string;
  };
  // API returns different field names depending on endpoint
  targetEnhancedArr?: SPGAISTarget[];  // GetTargetsInAreaEnhanced, GetTargetsByMMSIsEnhanced
  targets?: SPGAISTarget[];            // fallback
}

// Build Basic Auth header
function buildAuthHeader(): string {
  const credentials = `${SPG_USERNAME}:${SPG_PASSWORD}`;
  return `Basic ${btoa(credentials)}`;
}

// Generic S&P Global AIS API POST call
async function callSPGAPI(endpoint: string, body: Record<string, unknown>): Promise<SPGAISTarget[]> {
  const url = `${SPG_BASE}/AISSvc.svc/AIS/${endpoint}`;

  const res = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': buildAuthHeader(),
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    },
    body: JSON.stringify(body),
  });

  if (!res.ok) {
    throw new Error(`S&P AIS API ${res.status}: ${res.statusText}`);
  }

  const data: SPGAPIResponse = await res.json();

  if (!data.APSStatus?.CompletedOK) {
    throw new Error(`S&P AIS API error: ${data.APSStatus?.ErrorMessage || 'Unknown error'}`);
  }

  // API returns targetEnhancedArr for Enhanced endpoints
  return data.targetEnhancedArr || data.targets || [];
}

// Parse S&P AIS target into our Ship type
function parseAISTarget(t: SPGAISTarget): Ship {
  const name = (t.Name || '').trim();
  const mmsi = String(t.MMSI || '');
  const flag = getFlagFromMMSI(mmsi);
  const category = classifyShip(name, mmsi, t.VesselType);

  return {
    mmsi,
    name: name || `MMSI-${mmsi}`,
    lat: t.Lat,
    lng: t.Lon,
    heading: t.Heading ?? t.CoG ?? 0,
    speed: t.SoG ?? 0,
    course: t.CoG ?? t.Heading ?? 0,
    category,
    flag,
    typecode: t.STAT5CODE || t.VesselType || undefined,
    typeDesc: t.VesselType || undefined,
    imo: t.IMO || undefined,
    callSign: t.Callsign || undefined,
    status: t.Status || undefined,
    destination: (t.DestinationTidied || t.Destination || '').trim() || undefined,
    eta: t.ETA || undefined,
    draught: t.Draught > 0 ? t.Draught : undefined,
    length: t.Length > 0 ? t.Length : undefined,
    width: t.Width > 0 ? t.Width : undefined,
    lastSeen: t.MessageTimestamp
      ? new Date(t.MessageTimestamp).getTime()
      : t.TimestampUTC
        ? t.TimestampUTC * 1000
        : Date.now(),
  };
}

// ═══ Primary API: GetTargetsInAreaEnhanced ═══
// Returns vessels within a bounding box updated in the last N seconds
export async function fetchShipsFromSPG(): Promise<Ship[]> {
  // TODO: signal-batch 전환 후 제거 — S&P API 비활성화
  return [];
}

// ═══ Supplementary: fetch specific vessels by MMSI ═══
// Useful for tracking known military vessels that may not appear in area query
export async function fetchShipsByMMSI(mmsiList: string[]): Promise<Ship[]> {
  if (!SPG_USERNAME || !SPG_PASSWORD || mmsiList.length === 0) return [];

  try {
    const targets = await callSPGAPI('GetTargetsByMMSIsEnhanced', {
      MMSI: mmsiList.join(','),
    });

    return targets
      .filter(t => t.Lat != null && t.Lon != null)
      .map(parseAISTarget);
  } catch (err) {
    console.warn('S&P AIS API (GetTargetsByMMSIsEnhanced) failed:', err);
    return [];
  }
}

// ═══ Supplementary: fetch tankers only ═══
export async function fetchTankers(): Promise<Ship[]> {
  if (!SPG_USERNAME || !SPG_PASSWORD) return [];

  try {
    const targets = await callSPGAPI('GetTankerSubsetOneEnhanced', {});
    return targets
      .filter(t => t.Lat != null && t.Lon != null)
      .filter(t => {
        // Filter to Middle East region
        return t.Lat >= ME_BOUNDS.minLat && t.Lat <= ME_BOUNDS.maxLat
          && t.Lon >= ME_BOUNDS.minLng && t.Lon <= ME_BOUNDS.maxLng;
      })
      .map(parseAISTarget);
  } catch (err) {
    console.warn('S&P AIS API (GetTankerSubsetOneEnhanced) failed:', err);
    return [];
  }
}

// ═══ Main fetch function ═══
// Tries signal-batch Iran region first, merges with sample military ships
export async function fetchShips(minutes = 10): Promise<Ship[]> {
  const sampleShips = getSampleShips();
  const real = await fetchShipsFromSignalBatchIran(minutes);

  if (real.length > 0) {
    console.log(`signal-batch: ${real.length} vessels in Iran/Hormuz region`);
    // 샘플 군함(military)은 유지 (AIS에 안 잡힘)
    const sampleMilitary = sampleShips.filter(s =>
      s.category === 'warship' || s.category === 'carrier' || s.category === 'destroyer' || s.category === 'patrol' || s.category === 'submarine'
    );
    const sampleMMSIs = new Set(sampleMilitary.map(s => s.mmsi));
    return [...real.filter(s => !sampleMMSIs.has(s.mmsi)), ...sampleMilitary];
  }

  // signal-batch 실패 시 기존 샘플 데이터 사용
  console.warn('signal-batch Iran returned no data, using sample data');
  return sampleShips;
}


// T0 = main strike moment
const T0 = new Date('2026-03-01T12:01:00Z').getTime();
const HOUR = 3600_000;

function getSampleShips(): Ship[] {
  const now = Date.now();
  return [
    // ═══ USS ABRAHAM LINCOLN CSG — Arabian Sea (deployed Nov 2025, rerouted to ME) ═══
    {
      mmsi: '369970072', name: 'USS ABRAHAM LINCOLN (CVN-72)', lat: 23.5, lng: 59.8,
      heading: 315, speed: 20, course: 315, category: 'carrier', flag: 'US', typecode: 'CVN',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970121', name: 'USS FRANK E. PETERSEN JR. (DDG-121)', lat: 23.8, lng: 59.5,
      heading: 300, speed: 22, course: 300, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970111', name: 'USS SPRUANCE (DDG-111)', lat: 23.2, lng: 60.1,
      heading: 340, speed: 20, course: 340, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970112', name: 'USS MICHAEL MURPHY (DDG-112)', lat: 23.0, lng: 60.4,
      heading: 280, speed: 18, course: 280, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ USS GERALD R. FORD CSG — Red Sea (deployed Feb 2026) ═══
    {
      mmsi: '369970078', name: 'USS GERALD R. FORD (CVN-78)', lat: 20.5, lng: 38.5,
      heading: 170, speed: 18, course: 170, category: 'carrier', flag: 'US', typecode: 'CVN',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ Independent US destroyers — Arabian Sea ═══
    {
      mmsi: '369970074', name: 'USS McFAUL (DDG-74)', lat: 24.0, lng: 58.0,
      heading: 45, speed: 22, course: 45, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970113', name: 'USS JOHN FINN (DDG-113)', lat: 22.0, lng: 61.5,
      heading: 350, speed: 24, course: 350, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970069', name: 'USS MILIUS (DDG-69)', lat: 25.5, lng: 57.5,
      heading: 270, speed: 20, course: 270, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970119', name: 'USS DELBERT D. BLACK (DDG-119)', lat: 24.5, lng: 56.8,
      heading: 90, speed: 18, course: 90, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970091', name: 'USS PINCKNEY (DDG-91)', lat: 21.5, lng: 60.8,
      heading: 30, speed: 22, course: 30, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970057', name: 'USS MITSCHER (DDG-57)', lat: 26.0, lng: 55.5,
      heading: 180, speed: 20, course: 180, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ US LCS — Persian Gulf ═══
    {
      mmsi: '369970030', name: 'USS CANBERRA (LCS-30)', lat: 27.2, lng: 51.5,
      heading: 60, speed: 15, course: 60, category: 'patrol', flag: 'US', typecode: 'LCS',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '369970016', name: 'USS TULSA (LCS-16)', lat: 26.2, lng: 53.0,
      heading: 120, speed: 14, course: 120, category: 'patrol', flag: 'US', typecode: 'LCS',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ UK Royal Navy ═══
    {
      mmsi: '232001034', name: 'HMS DIAMOND (D34)', lat: 25.0, lng: 57.0,
      heading: 0, speed: 16, course: 0, category: 'destroyer', flag: 'UK', typecode: 'DDG',
      lastSeen: now, activeStart: T0 - 8 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '232001041', name: 'HMS MIDDLETON (M34)', lat: 26.0, lng: 56.8,
      heading: 270, speed: 8, course: 270, category: 'patrol', flag: 'UK', typecode: 'MCM',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 6 * HOUR,
    },

    // ═══ French Navy ═══
    {
      mmsi: '227001653', name: 'FS LANGUEDOC (D653)', lat: 34.8, lng: 33.5,
      heading: 120, speed: 16, course: 120, category: 'destroyer', flag: 'FR', typecode: 'FREMM',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '227001091', name: 'FS CHARLES DE GAULLE (R91)', lat: 35.0, lng: 28.0,
      heading: 90, speed: 22, course: 90, category: 'carrier', flag: 'FR', typecode: 'CVN',
      lastSeen: now, activeStart: T0 + 4 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ IRGCN — Iranian patrol boats ═══
    {
      mmsi: '422001001', name: 'IRGCN FAST ATTACK-1', lat: 26.55, lng: 56.25,
      heading: 180, speed: 35, course: 180, category: 'patrol', flag: 'IR', typecode: 'PC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 4 * HOUR,
    },
    {
      mmsi: '422001002', name: 'IRGCN FAST ATTACK-2', lat: 26.65, lng: 56.10,
      heading: 210, speed: 32, course: 210, category: 'patrol', flag: 'IR', typecode: 'PC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 4 * HOUR,
    },
    {
      mmsi: '422001003', name: 'IRGCN FAST ATTACK-3', lat: 26.70, lng: 56.40,
      heading: 240, speed: 30, course: 240, category: 'patrol', flag: 'IR', typecode: 'PC',
      lastSeen: now, activeStart: T0 - 10 * HOUR, activeEnd: T0 + 2 * HOUR,
    },
    {
      mmsi: '422010001', name: 'IRIS DENA (F75)', lat: 25.8, lng: 57.2,
      heading: 210, speed: 14, course: 210, category: 'warship', flag: 'IR', typecode: 'FFG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ Republic of Korea Navy ═══
    {
      mmsi: '440001981', name: 'ROKS CHOI YOUNG (DDH-981)', lat: 25.3, lng: 57.5,
      heading: 45, speed: 16, course: 45, category: 'destroyer', flag: 'KR', typecode: 'DDH',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ KOREAN VESSELS — ships stranded at Fujairah anchorage (Gulf of Oman) ═══
    // Fujairah Offshore Anchorage: ~25.1-25.35°N, 56.30-56.55°E (open water)
    {
      mmsi: '440101001', name: 'HYUNDAI SUPREME', lat: 25.18, lng: 56.38,
      heading: 130, speed: 0, course: 130, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440101002', name: 'HYUNDAI PRESTIGE', lat: 25.22, lng: 56.42,
      heading: 110, speed: 0, course: 110, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440102001', name: 'GS VOYAGER', lat: 25.15, lng: 56.35,
      heading: 90, speed: 0, course: 90, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440103001', name: 'SINOKOR ENERGY', lat: 25.25, lng: 56.45,
      heading: 150, speed: 0, course: 150, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440103002', name: 'SINOKOR PIONEER', lat: 25.20, lng: 56.50,
      heading: 200, speed: 0, course: 200, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440104001', name: 'SK HARMONY', lat: 25.28, lng: 56.40,
      heading: 170, speed: 0, course: 170, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440105001', name: 'S-OIL CROWN', lat: 25.12, lng: 56.33,
      heading: 0, speed: 0, course: 0, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440501234', name: 'HYUNDAI BRAVE', lat: 25.30, lng: 56.48,
      heading: 130, speed: 0, course: 130, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440501235', name: 'HMM ROTTERDAM', lat: 25.16, lng: 56.52,
      heading: 100, speed: 0, course: 100, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440501236', name: 'PAN OCEAN STAR', lat: 25.35, lng: 56.44,
      heading: 80, speed: 0, course: 80, category: 'cargo', flag: 'KR', typecode: 'BULK',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440501237', name: 'POLARIS VICTORY', lat: 25.23, lng: 56.36,
      heading: 160, speed: 0, course: 160, category: 'cargo', flag: 'KR', typecode: 'BULK',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440501238', name: 'KSS BUSAN', lat: 25.32, lng: 56.55,
      heading: 120, speed: 0, course: 120, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440106001', name: 'SK SPLENDOR', lat: 25.19, lng: 56.46,
      heading: 140, speed: 0, course: 140, category: 'tanker', flag: 'KR', typecode: 'LNG',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '440107001', name: 'EAGLE VELLORE', lat: 24.0, lng: 59.0,
      heading: 120, speed: 14, course: 120, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 6 * HOUR, activeEnd: T0 + 12 * HOUR,
    },

    // ═══ Other Commercial vessels ═══
    {
      mmsi: '538006789', name: 'PACIFIC HARMONY', lat: 25.27, lng: 56.58,
      heading: 300, speed: 0, course: 300, category: 'tanker', flag: 'MH', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '228001234', name: 'CMA CGM TROCADERO', lat: 26.3, lng: 53.5,
      heading: 90, speed: 0, course: 90, category: 'cargo', flag: 'FR', typecode: 'CONT',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
    {
      mmsi: '636012345', name: 'FRONT ALTAIR', lat: 25.5, lng: 57.2,
      heading: 0, speed: 0, course: 0, category: 'tanker', flag: 'LR', typecode: 'VLCC',
      lastSeen: now, activeStart: T0 - 12 * HOUR, activeEnd: T0 + 12 * HOUR,
    },
  ];
}

// ═══════════════════════════════════════
//  KOREA REGION — signal-batch data pipeline
// ═══════════════════════════════════════

const SIGNAL_BATCH_BASE = '/signal-batch';

// signal-batch POST /api/v1/vessels/recent-positions-detail
interface RecentPositionDetailRequest {
  minutes: number;
  coordinates: number[][]; // [[lon,lat], ...] polygon (first == last)
}

interface RecentPositionDetailDto {
  mmsi: string;
  imo: number | null;
  lon: number;
  lat: number;
  sog: number;
  cog: number;
  shipNm: string;
  shipTy: string;
  shipKindCode: string;
  nationalCode: string;
  lastUpdate: string;
  shipImagePath: string | null;
  shipImageCount: number | null;
  heading: number | null;
  callSign: string | null;
  status: string | null;
  destination: string | null;
  eta: string | null;
  draught: number | null;
  length: number | null;
  width: number | null;
}

// AIS Ship and Cargo Type (0-99) → SPG-compatible vessel type string
// ITU-R M.1371-5, Table 53 — second digit encodes hazard category (x1-x4)
// Returns strings matching SPG_VESSEL_TYPE_MAP keys for classifyShip() compatibility
function aisTypeToVesselType(shipTy: string): string | undefined {
  const code = parseInt(shipTy, 10);
  if (isNaN(code) || code < 0 || code > 99) return undefined;

  // 20-29: Wing in Ground effect
  if (code >= 20 && code <= 29) return 'Wing In Ground-effect';
  // 30: Fishing
  if (code === 30) return 'Fishing';
  // 31-32: Towing
  if (code === 31 || code === 32) return 'Tug';
  // 33: Dredging/underwater ops
  if (code === 33) return 'Vessel';
  // 34: Diving operations
  if (code === 34) return 'Vessel';
  // 35: Military operations — let name/MMSI classification take priority
  if (code === 35) return 'N/A';
  // 36: Sailing
  if (code === 36) return 'Vessel';
  // 37: Pleasure craft
  if (code === 37) return 'Vessel';
  // 38-39: Reserved
  // 40-49: High Speed Craft (x0=all, x1=Haz A, x2=Haz B, x3=Haz C, x4=Haz D)
  if (code >= 40 && code <= 49) return 'High Speed Craft';
  // 50: Pilot vessel
  if (code === 50) return 'Pilot Boat';
  // 51: Search and Rescue
  if (code === 51) return 'Search And Rescue';
  // 52: Tug
  if (code === 52) return 'Tug';
  // 53: Port tender
  if (code === 53) return 'Tender';
  // 54: Anti-pollution equipment
  if (code === 54) return 'Anti Pollution';
  // 55: Law enforcement
  if (code === 55) return 'Law Enforcement';
  // 56-57: Spare (local assignment)
  // 58: Medical transport
  if (code === 58) return 'Medical Transport';
  // 59: Noncombatant ship (RR Resolution No. 18)
  if (code === 59) return 'N/A';
  // 60-69: Passenger (x0=all, x1=Haz A, x2=Haz B, x3=Haz C, x4=Haz D)
  if (code >= 60 && code <= 69) return 'Passenger';
  // 70-79: Cargo (x0=all, x1=Haz A, x2=Haz B, x3=Haz C, x4=Haz D)
  if (code >= 70 && code <= 79) return 'Cargo';
  // 80-89: Tanker (x0=all, x1=Haz A, x2=Haz B, x3=Haz C, x4=Haz D)
  if (code >= 80 && code <= 89) return 'Tanker';
  // 90-99: Other (x0=all, x1=Haz A, ... same pattern)
  if (code >= 90 && code <= 99) return 'Vessel';

  return undefined;
}

// 어구/어망 선박명 패턴:
// "이름_숫자_" (예: "HAEJIN_123_", "金龙_45_")
// "이름%" (예: "HAEJIN%", "金龙123%")
const FISHING_GEAR_NAME_PATTERN = /^.+_\d+_$|%$/;

function parseSignalBatchVessel(d: RecentPositionDetailDto): Ship {
  const name = (d.shipNm || '').trim();
  const mmsi = String(d.mmsi || '');
  // nationalCode is MMSI prefix (3 digits) — reuse existing MMSI_FLAG_MAP
  const flag = MMSI_FLAG_MAP[d.nationalCode] || getFlagFromMMSI(mmsi);

  // shipTy can be either a SPG VesselType string ("Cargo", "Tanker") or AIS numeric code ("70", "80")
  // Try as-is first (string), fall back to AIS numeric conversion
  const rawShipTy = (d.shipTy || '').trim();
  const isNumeric = /^\d+$/.test(rawShipTy);
  let vesselType = isNumeric ? aisTypeToVesselType(rawShipTy) : (rawShipTy || undefined);

  // shipKindCode 보조 분류 (signal-batch 한국 데이터)
  // 해양수산부 선종코드: 000020~000029 어선, 000023 화물, 000024 유조, 000030 어선
  const kindCode = (d.shipKindCode || '').trim();
  const kindNum = parseInt(kindCode, 10);
  if (!vesselType || vesselType === 'N/A' || vesselType === 'Vessel') {
    if (kindNum >= 20 && kindNum <= 22) vesselType = 'Fishing';
    else if (kindNum === 30 || kindNum === 31) vesselType = 'Fishing';
    else if (kindNum >= 10 && kindNum <= 15) vesselType = 'Fishing';  // 소형 어선류
  }

  // DEBUG: kindCode 분포 집계
  if (typeof window !== 'undefined') {
    const w = window as Window & { __kindCodeMap?: Record<string, number>; __kindCodeLogged?: boolean };
    if (!w.__kindCodeMap) w.__kindCodeMap = {};
    const km = w.__kindCodeMap;
    const key = `${kindCode}|${rawShipTy}`;
    km[key] = (km[key] || 0) + 1;
    if (!w.__kindCodeLogged && Object.keys(km).length > 20) {
      w.__kindCodeLogged = true;
      console.log('[SHIP DEBUG] kindCode|shipTy distribution:', JSON.stringify(
        Object.entries(km).sort((a, b) => b[1] - a[1]).slice(0, 30)
      ));
    }
  }
  if (!vesselType || vesselType === 'Vessel' || vesselType === 'N/A') {
    if (kindCode.includes('어선') || kindCode.toLowerCase().includes('fish')) {
      vesselType = 'Fishing';
    } else if (kindCode.includes('화물') || kindCode.toLowerCase().includes('cargo')) {
      vesselType = 'Cargo';
    } else if (kindCode.includes('유조') || kindCode.toLowerCase().includes('tanker')) {
      vesselType = 'Tanker';
    } else if (kindCode.includes('여객') || kindCode.toLowerCase().includes('passenger')) {
      vesselType = 'Passenger';
    } else if (kindCode.includes('예인') || kindCode.toLowerCase().includes('tug')) {
      vesselType = 'Tug';
    }
  }

  // 어구/어망 판별: 선박명이 "이름_숫자_" 패턴
  if (FISHING_GEAR_NAME_PATTERN.test(name)) {
    vesselType = 'FishingGear';
  }

  // 선박명 기반 어선 추정 (어구로 이미 분류된 것은 건너뜀)
  if (vesselType !== 'FishingGear' && (!vesselType || vesselType === 'Vessel' || vesselType === 'N/A')) {
    const nm = name.toLowerCase();
    // 중국 어선명 패턴: 省略号+渔+番号 (예: 鲁荣渔1234, 浙象渔05678)
    if (/[鲁浙闽粤琼桂辽冀津沪苏].*渔/.test(name) || nm.includes('渔')) {
      vesselType = 'Fishing';
    }
    // AIS shipTy=0 이지만 중국 국적(412~416 MMSI) + 소형선(<50m)이면 어선 가능성 높음
    if (!vesselType && flag === 'CN' && d.length != null && d.length > 0 && d.length < 50) {
      // 소형 중국선 중 화물/유조가 아닌 것은 어선 가능성
      if (rawShipTy === '0' || rawShipTy === '' || rawShipTy === '30') {
        vesselType = 'Fishing';
      }
    }
  }

  // Existing classification: name pattern → vesselType string → MMSI prefix
  const category = classifyShip(name, mmsi, vesselType);

  // lastUpdate is KST "yyyy-MM-dd HH:mm:ss" — append timezone offset
  let lastSeen = Date.now();
  if (d.lastUpdate) {
    const parsed = new Date(d.lastUpdate.replace(' ', 'T') + '+09:00').getTime();
    if (!isNaN(parsed)) lastSeen = parsed;
  }

  return {
    mmsi,
    name: name || `MMSI-${mmsi}`,
    lat: d.lat,
    lng: d.lon,
    heading: d.heading ?? d.cog ?? 0,
    speed: d.sog ?? 0,
    course: d.cog ?? d.heading ?? 0,
    category,
    flag,
    // vesselType string for getMarineTrafficCategory() matching
    typecode: vesselType || undefined,
    typeDesc: vesselType || undefined,
    imo: d.imo ? String(d.imo) : undefined,
    callSign: d.callSign || undefined,
    status: d.status || undefined,
    destination: (d.destination || '').trim() || undefined,
    eta: d.eta || undefined,
    draught: d.draught != null && d.draught > 0 ? d.draught : undefined,
    length: d.length != null && d.length > 0 ? d.length : undefined,
    width: d.width != null && d.width > 0 ? d.width : undefined,
    lastSeen,
    shipImagePath: d.shipImagePath || undefined,
    shipImageCount: d.shipImageCount ?? undefined,
  };
}

async function fetchShipsFromSignalBatchIran(minutes = 10): Promise<Ship[]> {
  try {
    const body: RecentPositionDetailRequest = {
      minutes,
      coordinates: [
        [IRAN_BOUNDS.minLng, IRAN_BOUNDS.minLat],
        [IRAN_BOUNDS.maxLng, IRAN_BOUNDS.minLat],
        [IRAN_BOUNDS.maxLng, IRAN_BOUNDS.maxLat],
        [IRAN_BOUNDS.minLng, IRAN_BOUNDS.maxLat],
        [IRAN_BOUNDS.minLng, IRAN_BOUNDS.minLat],
      ],
    };

    const res = await fetch(`${SIGNAL_BATCH_BASE}/api/v1/vessels/recent-positions-detail`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
      body: JSON.stringify(body),
    });

    if (!res.ok) throw new Error(`signal-batch API ${res.status}`);
    const data: RecentPositionDetailDto[] = await res.json();
    return data
      .filter(d => d.lat != null && d.lon != null && d.lat !== 0 && d.lon !== 0)
      .map(parseSignalBatchVessel);
  } catch (err) {
    console.warn('signal-batch API (Iran region) failed:', err);
    return [];
  }
}

async function fetchShipsFromSignalBatch(minutes = 5): Promise<Ship[]> {
  try {
    const body: RecentPositionDetailRequest = {
      minutes,
      coordinates: [
        [KR_BOUNDS.minLng, KR_BOUNDS.minLat],
        [KR_BOUNDS.maxLng, KR_BOUNDS.minLat],
        [KR_BOUNDS.maxLng, KR_BOUNDS.maxLat],
        [KR_BOUNDS.minLng, KR_BOUNDS.maxLat],
        [KR_BOUNDS.minLng, KR_BOUNDS.minLat],
      ],
    };

    const res = await fetch(`${SIGNAL_BATCH_BASE}/api/v1/vessels/recent-positions-detail`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
      body: JSON.stringify(body),
    });

    if (!res.ok) throw new Error(`signal-batch API ${res.status}`);
    const data: RecentPositionDetailDto[] = await res.json();
    return data
      .filter(d => d.lat != null && d.lon != null && d.lat !== 0 && d.lon !== 0)
      .map(parseSignalBatchVessel);
  } catch (err) {
    console.warn('signal-batch API (Korea region) failed:', err);
    return [];
  }
}

export async function fetchShipsKorea(minutes = 5): Promise<Ship[]> {
  const sample = getSampleShipsKorea();
  const real = await fetchShipsFromSignalBatch(minutes);
  if (real.length > 0) {
    console.log(`signal-batch: ${real.length} vessels in Korea region`);
    const sampleMMSIs = new Set(sample.map(s => s.mmsi));
    return [...real.filter(s => !sampleMMSIs.has(s.mmsi)), ...sample];
  }
  return sample;
}

function getSampleShipsKorea(): Ship[] {
  const now = Date.now();
  return [
    // ═══ ROKN — Korean Navy (본토 방어 강화) ═══
    { mmsi: '440991001', name: 'ROKS SEJONG THE GREAT (DDG-991)', lat: 35.05, lng: 129.08,
      heading: 180, speed: 0, course: 180, category: 'destroyer', flag: 'KR', typecode: 'DDG',
      lastSeen: now },
    { mmsi: '440991002', name: 'ROKS YULGOK YI I (DDG-992)', lat: 37.50, lng: 126.55,
      heading: 270, speed: 12, course: 270, category: 'destroyer', flag: 'KR', typecode: 'DDG',
      lastSeen: now },
    { mmsi: '440991003', name: 'ROKS DOKDO (LPH-6111)', lat: 33.95, lng: 128.60,
      heading: 90, speed: 14, course: 90, category: 'warship', flag: 'KR', typecode: 'LPH',
      lastSeen: now },
    { mmsi: '440991004', name: 'ROKS MARADO (LPH-6112)', lat: 34.80, lng: 128.50,
      heading: 150, speed: 16, course: 150, category: 'warship', flag: 'KR', typecode: 'LPH',
      lastSeen: now },
    { mmsi: '440991005', name: 'ROKS DAEGU (FFG-818)', lat: 35.95, lng: 129.60,
      heading: 45, speed: 10, course: 45, category: 'patrol', flag: 'KR', typecode: 'FFG',
      lastSeen: now },
    { mmsi: '440991006', name: 'ROKS INCHEON (FFG-811)', lat: 37.45, lng: 126.40,
      heading: 310, speed: 8, course: 310, category: 'patrol', flag: 'KR', typecode: 'FFG',
      lastSeen: now },
    { mmsi: '440991007', name: 'ROKS GANG GAMCHAN (DDH-979)', lat: 33.52, lng: 126.53,
      heading: 200, speed: 14, course: 200, category: 'destroyer', flag: 'KR', typecode: 'DDH',
      lastSeen: now },

    // ═══ 부산항 — 컨테이너/화물선 ═══
    { mmsi: '440201001', name: 'HMM ALGECIRAS', lat: 35.08, lng: 129.06,
      heading: 0, speed: 0, course: 0, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now },
    { mmsi: '440201002', name: 'HMM OSLO', lat: 35.06, lng: 129.08,
      heading: 45, speed: 0, course: 45, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now },
    { mmsi: '440201003', name: 'HMM GDANSK', lat: 35.04, lng: 129.10,
      heading: 90, speed: 0, course: 90, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now },
    { mmsi: '441201001', name: 'SINOKOR INCHEON', lat: 35.10, lng: 129.04,
      heading: 180, speed: 0, course: 180, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now },

    // ═══ 울산항 — 유조선 (원유 수입 대기) ═══
    { mmsi: '440301001', name: 'SK ENERGY NO.1', lat: 35.50, lng: 129.42,
      heading: 0, speed: 0, course: 0, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now },
    { mmsi: '440301002', name: 'GS CALTEX ULSAN', lat: 35.48, lng: 129.45,
      heading: 30, speed: 0, course: 30, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now },
    { mmsi: '440301003', name: 'S-OIL PIONEER', lat: 35.52, lng: 129.40,
      heading: 270, speed: 0, course: 270, category: 'tanker', flag: 'KR', typecode: 'VLCC',
      lastSeen: now },

    // ═══ 여수/광양 — LNG/석유화학 ═══
    { mmsi: '440401001', name: 'KOGAS LNG YEOSU', lat: 34.73, lng: 127.74,
      heading: 180, speed: 0, course: 180, category: 'tanker', flag: 'KR', typecode: 'LNG',
      lastSeen: now },
    { mmsi: '440401002', name: 'SK GAS CARRIER', lat: 34.75, lng: 127.70,
      heading: 0, speed: 0, course: 0, category: 'tanker', flag: 'KR', typecode: 'LPG',
      lastSeen: now },

    // ═══ 인천항 ═══
    { mmsi: '440501001', name: 'PAN OCEAN INCHEON', lat: 37.44, lng: 126.58,
      heading: 90, speed: 0, course: 90, category: 'cargo', flag: 'KR', typecode: 'BULK',
      lastSeen: now },
    { mmsi: '440501002', name: 'POLARIS STAR', lat: 37.46, lng: 126.60,
      heading: 0, speed: 0, course: 0, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now },

    // ═══ 동해 — 일본/러시아 항로 화물선 ═══
    { mmsi: '440601001', name: 'HYUNDAI MIPO', lat: 37.10, lng: 130.50,
      heading: 30, speed: 12, course: 30, category: 'cargo', flag: 'KR', typecode: 'BULK',
      lastSeen: now },
    { mmsi: '431201001', name: 'NIPPON MARU', lat: 38.20, lng: 131.50,
      heading: 200, speed: 14, course: 200, category: 'cargo', flag: 'JP', typecode: 'BULK',
      lastSeen: now },

    // ═══ 대한해협 통과 선박 ═══
    { mmsi: '412801001', name: 'COSCO BUSAN', lat: 34.30, lng: 129.20,
      heading: 60, speed: 16, course: 60, category: 'cargo', flag: 'CN', typecode: 'CONT',
      lastSeen: now },
    { mmsi: '538201001', name: 'PACIFIC VENUS', lat: 34.50, lng: 128.80,
      heading: 240, speed: 18, course: 240, category: 'tanker', flag: 'MH', typecode: 'VLCC',
      lastSeen: now },
    { mmsi: '636201001', name: 'NORDIC STAR', lat: 34.10, lng: 128.50,
      heading: 70, speed: 14, course: 70, category: 'tanker', flag: 'LR', typecode: 'VLCC',
      lastSeen: now },

    // ═══ 남중국해 → 부산 항로 ═══
    { mmsi: '440701001', name: 'HMM SINGAPORE', lat: 25.00, lng: 122.00,
      heading: 30, speed: 18, course: 30, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now },
    { mmsi: '440701002', name: 'HYUNDAI BANGKOK', lat: 20.50, lng: 118.00,
      heading: 45, speed: 16, course: 45, category: 'cargo', flag: 'KR', typecode: 'CONT',
      lastSeen: now },
    { mmsi: '477201001', name: 'OOCL HONG KONG', lat: 22.30, lng: 120.50,
      heading: 20, speed: 20, course: 20, category: 'cargo', flag: 'HK', typecode: 'CONT',
      lastSeen: now },

    // ═══ 블라디보스톡 근해 ═══
    { mmsi: '440801001', name: 'KORYO TRADER', lat: 42.80, lng: 132.50,
      heading: 180, speed: 10, course: 180, category: 'cargo', flag: 'KR', typecode: 'BULK',
      lastSeen: now },

    // ═══ 제주 해역 ═══
    { mmsi: '440901001', name: 'JEJU WORLD', lat: 33.30, lng: 126.30,
      heading: 90, speed: 16, course: 90, category: 'civilian', flag: 'KR', typecode: 'PASS',
      lastSeen: now },

    // ═══ USN 7th Fleet (주일미군 / 한반도 근해) ═══
    { mmsi: '369971001', name: 'USS RONALD REAGAN (CVN-76)', lat: 35.30, lng: 139.60,
      heading: 180, speed: 0, course: 180, category: 'carrier', flag: 'US', typecode: 'CVN',
      lastSeen: now },
    { mmsi: '369971002', name: 'USS BARRY (DDG-52)', lat: 34.00, lng: 130.50,
      heading: 270, speed: 22, course: 270, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now },
    { mmsi: '369971003', name: 'USS BENFOLD (DDG-65)', lat: 35.50, lng: 130.00,
      heading: 180, speed: 18, course: 180, category: 'destroyer', flag: 'US', typecode: 'DDG',
      lastSeen: now },

    // ═══ JMSDF (해상자위대) ═══
    { mmsi: '431991001', name: 'JS IZUMO (DDH-183)', lat: 34.60, lng: 137.20,
      heading: 90, speed: 14, course: 90, category: 'warship', flag: 'JP', typecode: 'DDH',
      lastSeen: now },
  ];
}
