import { useState, useEffect, useMemo, useRef, useCallback } from 'react';
import { fetchEvents } from '../services/api';
import { fetchAircraftFromBackend } from '../services/aircraftApi';
import { getSampleAircraft } from '../data/sampleAircraft';
import { fetchSatelliteTLE, propagateAll } from '../services/celestrak';
import { fetchShips } from '../services/ships';
import { fetchOsintFeed } from '../services/osint';
import type { OsintItem } from '../services/osint';
import { fetchSeismic, fetchPressure } from '../services/sensorApi';
import type { SeismicDto, PressureDto } from '../services/sensorApi';
import { propagateAircraft, propagateShips } from '../services/propagation';
import { getMarineTrafficCategory } from '../utils/marineTraffic';
import type { GeoEvent, Aircraft, Ship, Satellite, SatellitePosition, AppMode } from '../types';

interface UseIranDataArgs {
  appMode: AppMode;
  currentTime: number;
  isLive: boolean;
  hiddenAcCategories: Set<string>;
  hiddenShipCategories: Set<string>;
  refreshKey: number;
  dashboardTab: 'iran' | 'korea';
}

interface UseIranDataResult {
  aircraft: Aircraft[];
  ships: Ship[];
  visibleAircraft: Aircraft[];
  visibleShips: Ship[];
  satPositions: SatellitePosition[];
  events: GeoEvent[];
  mergedEvents: GeoEvent[];
  seismicData: SeismicDto[];
  pressureData: PressureDto[];
  osintFeed: OsintItem[];
  aircraftByCategory: Record<string, number>;
  militaryCount: number;
  shipsByCategory: Record<string, number>;
  koreanShips: Ship[];
  koreanShipsByCategory: Record<string, number>;
}

const SENSOR_POLL_INTERVAL = 600_000; // 10 min
const SHIP_POLL_INTERVAL = 300_000; // 5 min
const SHIP_STALE_MS = 3_600_000; // 60 min

export function useIranData({
  appMode,
  currentTime,
  isLive,
  hiddenAcCategories,
  hiddenShipCategories,
  refreshKey,
  dashboardTab,
}: UseIranDataArgs): UseIranDataResult {
  const [events, setEvents] = useState<GeoEvent[]>([]);
  const [seismicData, setSeismicData] = useState<SeismicDto[]>([]);
  const [pressureData, setPressureData] = useState<PressureDto[]>([]);
  const [baseAircraft, setBaseAircraft] = useState<Aircraft[]>([]);
  const [baseShips, setBaseShips] = useState<Ship[]>([]);
  const [satellites, setSatellites] = useState<Satellite[]>([]);
  const [satPositions, setSatPositions] = useState<SatellitePosition[]>([]);
  const [osintFeed, setOsintFeed] = useState<OsintItem[]>([]);

  const satTimeRef = useRef(0);
  const sensorInitRef = useRef(false);
  const shipMapRef = useRef<Map<string, Ship>>(new Map());

  // Load initial data
  useEffect(() => {
    fetchEvents().then(setEvents).catch(() => {});
    fetchSatelliteTLE().then(setSatellites).catch(() => {});
  }, [refreshKey]);

  // Sensor data: initial full 48h load + 10min polling (incremental merge)
  useEffect(() => {
    const loadFull = async () => {
      try {
        const [seismic, pressure] = await Promise.all([
          fetchSeismic(), // default 2880 min = 48h
          fetchPressure(),
        ]);
        setSeismicData(seismic);
        setPressureData(pressure);
        sensorInitRef.current = true;
      } catch { /* keep previous */ }
    };

    const loadIncremental = async () => {
      if (!sensorInitRef.current) return;
      try {
        const [seismic, pressure] = await Promise.all([
          fetchSeismic(11), // 11 min window (overlap)
          fetchPressure(11),
        ]);
        setSeismicData(prev => mergeSensor(prev, seismic, s => s.usgsId, 2880));
        setPressureData(prev => mergeSensor(prev, pressure, p => `${p.station}-${p.timestamp}`, 2880));
      } catch { /* keep previous */ }
    };

    loadFull();
    const interval = setInterval(loadIncremental, SENSOR_POLL_INTERVAL);
    return () => clearInterval(interval);
  }, [refreshKey]);

  // Fetch base aircraft data (LIVE: backend, REPLAY: sample)
  useEffect(() => {
    const load = async () => {
      if (appMode === 'live') {
        const result = await fetchAircraftFromBackend('iran');
        if (result.length > 0) setBaseAircraft(result);
      } else {
        setBaseAircraft(getSampleAircraft());
      }
    };
    load();
    const interval = setInterval(load, 60_000);
    return () => clearInterval(interval);
  }, [appMode, refreshKey]);

  // Fetch Iran ship data: initial 60min, then 5min polling with 6min window + merge + stale cleanup
  const mergeShips = useCallback((newShips: Ship[]) => {
    const map = shipMapRef.current;
    for (const s of newShips) {
      map.set(s.mmsi, s);
    }
    // Remove stale ships (lastSeen > 60 min ago)
    const cutoff = Date.now() - SHIP_STALE_MS;
    for (const [mmsi, ship] of map) {
      if (ship.lastSeen < cutoff) map.delete(mmsi);
    }
    setBaseShips(Array.from(map.values()));
  }, []);

  useEffect(() => {
    let initialDone = false;
    const loadInitial = async () => {
      try {
        const data = await fetchShips(60); // 초기: 60분 데이터
        if (data.length > 0) {
          shipMapRef.current = new Map(data.map(s => [s.mmsi, s]));
          setBaseShips(data);
          initialDone = true;
        }
      } catch { /* keep previous */ }
    };

    const loadIncremental = async () => {
      if (!initialDone) return;
      try {
        const data = await fetchShips(6); // polling: 6분 데이터
        if (data.length > 0) mergeShips(data);
      } catch { /* keep previous */ }
    };

    loadInitial();
    const interval = setInterval(loadIncremental, SHIP_POLL_INTERVAL);
    return () => clearInterval(interval);
  }, [appMode, refreshKey, mergeShips]);

  // Fetch OSINT feed — live mode (both tabs) + replay mode (iran tab)
  useEffect(() => {
    const shouldFetch = isLive || dashboardTab === 'iran';
    if (!shouldFetch) { setOsintFeed([]); return; }
    const load = async () => {
      try {
        const data = await fetchOsintFeed('iran');
        if (data.length > 0) setOsintFeed(data);
      } catch { /* keep previous */ }
    };
    setOsintFeed([]);
    load();
    const interval = setInterval(load, 120_000);
    return () => clearInterval(interval);
  }, [isLive, dashboardTab, refreshKey]);

  // Propagate satellite positions — throttle to every 2s of real time
  useEffect(() => {
    if (satellites.length === 0) return;
    const now = Date.now();
    if (now - satTimeRef.current < 2000) return;
    satTimeRef.current = now;
    const positions = propagateAll(satellites, new Date(currentTime));
    setSatPositions(positions);
  }, [satellites, currentTime]);

  // Propagate aircraft positions based on current time
  const aircraft = useMemo(
    () => propagateAircraft(baseAircraft, currentTime),
    [baseAircraft, currentTime],
  );

  // Propagate ship positions based on current time
  const ships = useMemo(
    () => propagateShips(baseShips, currentTime, isLive),
    [baseShips, currentTime, isLive],
  );

  // Category-filtered data for map rendering
  const visibleAircraft = useMemo(
    () => aircraft.filter(a => !hiddenAcCategories.has(a.category)),
    [aircraft, hiddenAcCategories],
  );

  const visibleShips = useMemo(
    () => ships.filter(s => !hiddenShipCategories.has(getMarineTrafficCategory(s.typecode, s.category))),
    [ships, hiddenShipCategories],
  );

  // OSINT → GeoEvent 변환
  const osintEvents = useMemo((): GeoEvent[] => {
    if (dashboardTab !== 'iran' || osintFeed.length === 0) return [];

    const STRIKE_PATTERN = /strike|attack|bomb|airstrike|hit|destroy|blast|공습|타격|폭격|파괴|피격/i;
    const MISSILE_PATTERN = /missile|launch|drone|발사|미사일|드론/i;
    const EXPLOSION_PATTERN = /explo|blast|deton|fire|폭발|화재|폭파/i;
    const INTERCEPT_PATTERN = /intercept|shoot.*down|defense|요격|격추|방어/i;
    const IMPACT_PATTERN = /impact|hit|struck|damage|casualt|피격|타격|피해|사상/i;

    const categoryToType: Record<string, GeoEvent['type']> = {
      military: 'osint',
      shipping: 'osint',
      oil: 'osint',
      nuclear: 'osint',
      diplomacy: 'osint',
    };

    return osintFeed
      .filter(item => {
        if (!item.lat || !item.lng) return false;
        return item.category in categoryToType;
      })
      .map((item): GeoEvent => {
        let eventType: GeoEvent['type'] = 'osint';
        const title = item.title;
        if (IMPACT_PATTERN.test(title)) eventType = 'impact';
        else if (STRIKE_PATTERN.test(title)) eventType = 'airstrike';
        else if (MISSILE_PATTERN.test(title)) eventType = 'missile_launch';
        else if (EXPLOSION_PATTERN.test(title)) eventType = 'explosion';
        else if (INTERCEPT_PATTERN.test(title)) eventType = 'intercept';

        let source: GeoEvent['source'] | undefined;
        if (/US|미국|America|Pentagon|CENTCOM/i.test(title)) source = 'US';
        else if (/Israel|이스라엘|IAF|IDF/i.test(title)) source = 'IL';
        else if (/Iran|이란|IRGC/i.test(title)) source = 'IR';
        else if (/Houthi|후티|Hezbollah|헤즈볼라|PMF|proxy|대리/i.test(title)) source = 'proxy';

        return {
          id: `osint-${item.id}`,
          timestamp: item.timestamp,
          lat: item.lat!,
          lng: item.lng!,
          type: eventType,
          source,
          label: `[OSINT] ${item.title}`,
          description: `출처: ${item.source} | ${item.url}`,
          intensity: eventType === 'impact' ? 80 : eventType === 'airstrike' ? 70 : 50,
        };
      });
  }, [osintFeed, dashboardTab]);

  // 기본 이벤트 + OSINT 이벤트 병합 (시간순 정렬)
  const mergedEvents = useMemo(() => {
    if (osintEvents.length === 0) return events;
    return [...events, ...osintEvents].sort((a, b) => a.timestamp - b.timestamp);
  }, [events, osintEvents]);

  // Aircraft stats
  const aircraftByCategory = useMemo(() => {
    const counts: Record<string, number> = {};
    for (const ac of aircraft) {
      counts[ac.category] = (counts[ac.category] || 0) + 1;
    }
    return counts;
  }, [aircraft]);

  const militaryCount = useMemo(
    () => aircraft.filter(a => a.category !== 'civilian' && a.category !== 'unknown').length,
    [aircraft],
  );

  // Ship stats — MT classification
  const shipsByCategory = useMemo(() => {
    const counts: Record<string, number> = {};
    for (const s of ships) {
      const mtCat = getMarineTrafficCategory(s.typecode, s.category);
      counts[mtCat] = (counts[mtCat] || 0) + 1;
    }
    return counts;
  }, [ships]);

  // Korean ship stats
  const koreanShips = useMemo(() => ships.filter(s => s.flag === 'KR'), [ships]);
  const koreanShipsByCategory = useMemo(() => {
    const counts: Record<string, number> = {};
    for (const s of koreanShips) {
      const mtCat = getMarineTrafficCategory(s.typecode, s.category);
      counts[mtCat] = (counts[mtCat] || 0) + 1;
    }
    return counts;
  }, [koreanShips]);

  return {
    aircraft,
    ships,
    visibleAircraft,
    visibleShips,
    satPositions,
    events,
    mergedEvents,
    seismicData,
    pressureData,
    osintFeed,
    aircraftByCategory,
    militaryCount,
    shipsByCategory,
    koreanShips,
    koreanShipsByCategory,
  };
}

/**
 * 센서 데이터 병합: 새 데이터를 기존 배열에 추가, 중복 제거, 오래된 데이터 제거
 */
function mergeSensor<T extends { timestamp: number }>(
  existing: T[],
  incoming: T[],
  keyFn: (item: T) => string,
  maxMinutes: number,
): T[] {
  const cutoff = Date.now() - maxMinutes * 60_000;
  const map = new Map<string, T>();
  for (const item of existing) {
    if (item.timestamp >= cutoff) map.set(keyFn(item), item);
  }
  for (const item of incoming) {
    if (item.timestamp >= cutoff) map.set(keyFn(item), item);
  }
  return Array.from(map.values()).sort((a, b) => a.timestamp - b.timestamp);
}
