import { useEffect, useRef, useCallback } from 'react';
import Map from 'ol/Map';
import View from 'ol/View';
import { fromLonLat, transformExtent } from 'ol/proj';
import { defaults as defaultControls, ScaleLine } from 'ol/control';
import { defaults as defaultInteractions, DragBox } from 'ol/interaction';
import { platformModifierKeyOnly } from 'ol/events/condition';

import { createBaseLayers } from './layers/baseLayer';
import { useMapStore, BASE_MAP_TYPES } from '../stores/mapStore';
import useShipStore from '../stores/shipStore';
import useShipData from '../hooks/useShipData';
import useShipLayer from '../hooks/useShipLayer';
import ShipLegend from '../components/ship/ShipLegend';
import ReplayLegend from '../components/ship/ReplayLegend';
import ShipTooltip from '../components/ship/ShipTooltip';
import ShipDetailModal from '../components/ship/ShipDetailModal';
import ShipContextMenu from '../components/ship/ShipContextMenu';
import TopBar from '../components/map/TopBar';
import GlobalTrackQueryViewer from '../tracking/components/GlobalTrackQueryViewer';
import useReplayLayer from '../replay/hooks/useReplayLayer';
import { shipBatchRenderer } from './ShipBatchRenderer';
import useReplayStore from '../replay/stores/replayStore';
import useAnimationStore from '../replay/stores/animationStore';
import ReplayTimeline from '../replay/components/ReplayTimeline';
import ReplayLoadingOverlay from '../replay/components/ReplayLoadingOverlay';
import { unregisterReplayLayers } from '../replay/utils/replayLayerRegistry';
import { showLiveShips } from '../utils/liveControl';
import { useTrackQueryStore } from '../tracking/stores/trackQueryStore';
import { LAYER_IDS as TRACK_QUERY_LAYER_IDS } from '../tracking/utils/trackQueryLayerUtils';

import useMeasure from './measure/useMeasure';
import useTrackingMode from '../hooks/useTrackingMode';
import './measure/measure.scss';
import './MapContainer.scss';

/** 호버 쓰로틀 간격 (ms) */
const HOVER_THROTTLE_MS = 50;

/**
 * 지도 컨테이너 컴포넌트
 * - OpenLayers 맵 초기화 및 관리
 * - STOMP 선박 데이터 연결
 * - Deck.gl 선박 레이어 렌더링
 * - 선박 호버 툴팁 / 더블클릭 상세 모달
 */
export default function MapContainer() {
  const mapRef = useRef(null);
  const mapInstanceRef = useRef(null);
  const baseLayersRef = useRef(null); // 배경지도 레이어 참조
  const { map, setMap, setZoom, center, baseMapType } = useMapStore();
  const showLegend = useShipStore((s) => s.showLegend);
  const hoverInfo = useShipStore((s) => s.hoverInfo);
  const detailModals = useShipStore((s) => s.detailModals);
  const replayCompleted = useReplayStore((s) => s.queryCompleted);
  const replayQuery = useReplayStore((s) => s.currentQuery);

  // STOMP 선박 데이터 연결
  useShipData({ autoConnect: true });

  // Deck.gl 선박 레이어
  const { deckRef } = useShipLayer(map);

  // 리플레이 레이어
  useReplayLayer();

  // 측정 도구
  useMeasure();

  // 추적 모드 (함정 중심 지도 이동 + 반경 원)
  useTrackingMode();

  // 배경지도 타입 변경 시 레이어 가시성 토글
  useEffect(() => {
    if (!baseLayersRef.current) return;

    const { worldMap, encMap, darkMap } = baseLayersRef.current;

    worldMap.setVisible(baseMapType === BASE_MAP_TYPES.NORMAL);
    encMap.setVisible(baseMapType === BASE_MAP_TYPES.ENC);
    darkMap.setVisible(baseMapType === BASE_MAP_TYPES.DARK);
  }, [baseMapType]);

  // 호버 쓰로틀 타이머
  const hoverTimerRef = useRef(null);

  /**
   * deck.pickObject 헬퍼 (라이브 선박 전용)
   */
  const pickShip = useCallback((pixel) => {
    const deck = deckRef.current;
    if (!deck) return null;
    if (!deck.layerManager) return null;

    try {
      const result = deck.pickObject({
        x: pixel[0],
        y: pixel[1],
        layerIds: ['ship-icon-layer'],
      });
      return result?.object || null;
    } catch {
      return null;
    }
  }, [deckRef]);

  /**
   * deck.pickObject 헬퍼 (모든 레이어)
   */
  const pickAny = useCallback((pixel) => {
    const deck = deckRef.current;
    if (!deck) return null;
    if (!deck.layerManager) return null;

    try {
      // layerIds를 지정하지 않으면 모든 pickable 레이어에서 픽킹
      const result = deck.pickObject({
        x: pixel[0],
        y: pixel[1],
      });
      return result || null;
    } catch {
      return null;
    }
  }, [deckRef]);

  /**
   * OpenLayers pointermove → 호버 툴팁
   */
  const handlePointerMove = useCallback((evt) => {
    // 드래그 중이면 무시
    if (evt.dragging) {
      useShipStore.getState().setHoverInfo(null);
      useTrackQueryStore.getState().setHighlightedVesselId(null);
      useReplayStore.getState().setHighlightedVesselId(null);
      return;
    }

    // 쓰로틀
    if (hoverTimerRef.current) return;

    hoverTimerRef.current = setTimeout(() => {
      hoverTimerRef.current = null;

      const pixel = evt.pixel;
      const { clientX, clientY } = evt.originalEvent;
      const pickResult = pickAny(pixel);

      if (!pickResult || !pickResult.layer) {
        // 아무것도 픽킹되지 않음
        useShipStore.getState().setHoverInfo(null);
        useTrackQueryStore.getState().setHighlightedVesselId(null);
        useTrackQueryStore.getState().clearHoveredPoint();
        useReplayStore.getState().setHighlightedVesselId(null);
        return;
      }

      const layerId = pickResult.layer.id;
      const obj = pickResult.object;

      // 라이브 선박
      if (layerId === 'ship-icon-layer') {
        useShipStore.getState().setHoverInfo({ ship: obj, x: clientX, y: clientY });
        useTrackQueryStore.getState().setHighlightedVesselId(null);
        useTrackQueryStore.getState().clearHoveredPoint();
        useReplayStore.getState().setHighlightedVesselId(null);
        return;
      }

      // 항적조회 경로 (PathLayer)
      if (layerId === TRACK_QUERY_LAYER_IDS.PATH) {
        useShipStore.getState().setHoverInfo(null);
        useTrackQueryStore.getState().setHighlightedVesselId(obj?.vesselId || null);
        useTrackQueryStore.getState().clearHoveredPoint();
        useReplayStore.getState().setHighlightedVesselId(null);
        return;
      }

      // 항적조회 포인트 (ScatterplotLayer)
      if (layerId === TRACK_QUERY_LAYER_IDS.POINTS) {
        useShipStore.getState().setHoverInfo(null);
        useTrackQueryStore.getState().setHighlightedVesselId(obj?.vesselId || null);
        useReplayStore.getState().setHighlightedVesselId(null);
        // 포인트 호버 정보 설정
        if (obj) {
          useTrackQueryStore.getState().setHoveredPoint({
            vesselId: obj.vesselId,
            position: obj.position,
            timestamp: obj.timestamp,
            speed: obj.speed,
            index: obj.index,
          }, clientX, clientY);
        } else {
          useTrackQueryStore.getState().clearHoveredPoint();
        }
        return;
      }

      // 항적조회 가상 선박 아이콘
      if (layerId === TRACK_QUERY_LAYER_IDS.VIRTUAL_SHIP) {
        const tooltipShip = {
          shipName: obj.shipName,
          targetId: obj.vesselId?.split('_').pop() || obj.vesselId,
          signalKindCode: obj.shipKindCode,
          sog: obj.speed || 0,
          cog: obj.heading || 0,
        };
        useShipStore.getState().setHoverInfo({ ship: tooltipShip, x: clientX, y: clientY });
        useTrackQueryStore.getState().setHighlightedVesselId(obj?.vesselId || null);
        useTrackQueryStore.getState().clearHoveredPoint();
        useReplayStore.getState().setHighlightedVesselId(null);
        return;
      }

      // 리플레이 경로 (PathLayer)
      if (layerId === 'track-path-layer') {
        useShipStore.getState().setHoverInfo(null);
        useTrackQueryStore.getState().setHighlightedVesselId(null);
        useTrackQueryStore.getState().clearHoveredPoint();
        useReplayStore.getState().setHighlightedVesselId(obj?.vesselId || null);
        return;
      }

      // 리플레이 가상 선박 아이콘
      if (layerId === 'track-virtual-ship-layer') {
        const tooltipShip = {
          shipName: obj.shipName,
          targetId: obj.vesselId?.split('_').pop() || obj.vesselId,
          signalKindCode: obj.shipKindCode,
          sog: obj.speed || 0,
          cog: obj.heading || 0,
        };
        useShipStore.getState().setHoverInfo({ ship: tooltipShip, x: clientX, y: clientY });
        useTrackQueryStore.getState().setHighlightedVesselId(null);
        useTrackQueryStore.getState().clearHoveredPoint();
        useReplayStore.getState().setHighlightedVesselId(obj?.vesselId || null);
        return;
      }

      // 기타: 모두 클리어
      useShipStore.getState().setHoverInfo(null);
      useTrackQueryStore.getState().setHighlightedVesselId(null);
      useTrackQueryStore.getState().clearHoveredPoint();
      useReplayStore.getState().setHighlightedVesselId(null);
    }, HOVER_THROTTLE_MS);
  }, [pickAny]);

  /**
   * OpenLayers dblclick → 상세 모달
   */
  const handleDblClick = useCallback((evt) => {
    const pixel = evt.pixel;
    const ship = pickShip(pixel);

    if (ship) {
      evt.stopPropagation();
      useShipStore.getState().openDetailModal(ship);
    }
  }, [pickShip]);

  /**
   * pointerout → 툴팁 숨김 + 하이라이트 클리어
   */
  const handlePointerOut = useCallback(() => {
    useShipStore.getState().setHoverInfo(null);
    useTrackQueryStore.getState().setHighlightedVesselId(null);
    useTrackQueryStore.getState().clearHoveredPoint();
    useReplayStore.getState().setHighlightedVesselId(null);
  }, []);

  /**
   * singleclick → 빈 영역 클릭 시 선택/메뉴 해제
   */
  const handleSingleClick = useCallback((evt) => {
    const ship = pickShip(evt.pixel);
    if (!ship) {
      useShipStore.getState().clearSelectedShips();
      useShipStore.getState().closeContextMenu();
    }
  }, [pickShip]);

  // OL 이벤트 바인딩
  useEffect(() => {
    if (!map) return;

    map.on('pointermove', handlePointerMove);
    map.on('dblclick', handleDblClick);
    map.on('singleclick', handleSingleClick);

    // pointerout은 뷰포트 DOM 이벤트로 처리
    const viewport = map.getViewport();
    viewport.addEventListener('pointerout', handlePointerOut);

    // 우클릭 컨텍스트 메뉴
    const handleContextMenu = (e) => {
      e.preventDefault();
      const pixel = map.getEventPixel(e);
      const ship = pickShip(pixel);
      const state = useShipStore.getState();

      if (ship) {
        state.openContextMenu({ x: e.clientX, y: e.clientY, ships: [ship] });
      } else if (state.selectedShipIds.length > 0) {
        const selectedShips = state.getSelectedShips();
        state.openContextMenu({ x: e.clientX, y: e.clientY, ships: selectedShips });
      }
    };
    viewport.addEventListener('contextmenu', handleContextMenu);

    return () => {
      map.un('pointermove', handlePointerMove);
      map.un('dblclick', handleDblClick);
      map.un('singleclick', handleSingleClick);
      viewport.removeEventListener('pointerout', handlePointerOut);
      viewport.removeEventListener('contextmenu', handleContextMenu);

      if (hoverTimerRef.current) {
        clearTimeout(hoverTimerRef.current);
        hoverTimerRef.current = null;
      }
    };
  }, [map, handlePointerMove, handleDblClick, handleSingleClick, handlePointerOut, pickShip]);

  useEffect(() => {
    if (!mapRef.current || mapInstanceRef.current) return;

    // 현재 배경지도 타입 가져오기
    const currentBaseMapType = useMapStore.getState().baseMapType;

    // 베이스 레이어 생성 (3가지 배경지도 + 상세지도)
    const { worldMap, encMap, darkMap, eastAsiaMap, korMap } = createBaseLayers(currentBaseMapType);

    // 배경지도 레이어 참조 저장
    baseLayersRef.current = { worldMap, encMap, darkMap };

    // 스케일라인 컨트롤 (해리 단위)
    const scaleLineControl = new ScaleLine({
      units: 'nautical',
      bar: true,
      text: true,
    });

    // 지도 인스턴스 생성
    const map = new Map({
      target: mapRef.current,
      layers: [
        worldMap,
        encMap,
        darkMap,
        eastAsiaMap,
        korMap,
      ],
      view: new View({
        center: fromLonLat(center),
        zoom: 7,
        minZoom: 5,  // 야간지도 타일 최소 레벨
        maxZoom: 15, // 줌 확장은 15까지 (타일은 12레벨까지만 로드)
      }),
      controls: defaultControls({
        attribution: false,
        zoom: false,
        rotate: false,
      }).extend([scaleLineControl]),
      interactions: defaultInteractions({
        doubleClickZoom: false,
      }),
    });

    // Ctrl+Drag 박스 선택 인터랙션
    const dragBox = new DragBox({ condition: platformModifierKeyOnly });
    map.addInteraction(dragBox);

    dragBox.on('boxend', () => {
      const extent3857 = dragBox.getGeometry().getExtent();
      const [minLon, minLat, maxLon, maxLat] = transformExtent(extent3857, 'EPSG:3857', 'EPSG:4326');

      const state = useShipStore.getState();
      const { features, darkSignalIds, isIntegrate, kindVisibility, sourceVisibility,
              nationalVisibility, darkSignalVisible } = state;

      // 국적 코드 매핑 (shipStore.js와 동일)
      const mapNational = (code) => {
        if (!code) return 'OTHER';
        const c = code.toUpperCase();
        if (c === 'KR' || c === 'KOR' || c === '440') return 'KR';
        if (c === 'CN' || c === 'CHN' || c === '412' || c === '413' || c === '414') return 'CN';
        if (c === 'JP' || c === 'JPN' || c === '431' || c === '432') return 'JP';
        if (c === 'KP' || c === 'PRK' || c === '445') return 'KP';
        return 'OTHER';
      };

      const matchedIds = [];
      features.forEach((ship, featureId) => {
        // 단독 레이더 제외
        if (ship.signalSourceCode === '000005' && !ship.integrate) return;
        // 통합 모드 ON: isPriority만
        if (isIntegrate && ship.integrate && !ship.isPriority) return;

        // 다크시그널: 독립 필터
        if (darkSignalIds.has(featureId)) {
          if (!darkSignalVisible) return;
        } else {
          if (!kindVisibility[ship.signalKindCode]) return;
          if (!sourceVisibility[ship.signalSourceCode]) return;
          const mappedNational = mapNational(ship.nationalCode);
          if (!nationalVisibility[mappedNational]) return;
        }

        const lon = parseFloat(ship.longitude);
        const lat = parseFloat(ship.latitude);
        if (lon >= minLon && lon <= maxLon && lat >= minLat && lat <= maxLat) {
          matchedIds.push(featureId);
        }
      });

      state.setSelectedShipIds(matchedIds);
    });

    // 줌 변경 이벤트
    map.getView().on('change:resolution', () => {
      const zoom = Math.round(map.getView().getZoom());
      setZoom(zoom);
    });

    // 스토어에 맵 인스턴스 저장
    setMap(map);
    mapInstanceRef.current = map;
    // TrackQueryViewer 등에서 줌 감지용
    window.__mainMap__ = map;

    // 클린업
    return () => {
      if (mapInstanceRef.current) {
        mapInstanceRef.current.setTarget(null);
        mapInstanceRef.current = null;
      }
      window.__mainMap__ = null;
    };
  }, []);

  return (
    <>
      <div id="map" ref={mapRef} className="map-container" />
      <TopBar />
      {showLegend && (replayCompleted ? <ReplayLegend /> : <ShipLegend />)}
      {hoverInfo && (
        <ShipTooltip ship={hoverInfo.ship} x={hoverInfo.x} y={hoverInfo.y} />
      )}
      {detailModals.map((modal) => (
        <ShipDetailModal key={modal.id} modal={modal} />
      ))}
      <ShipContextMenu />
      <GlobalTrackQueryViewer />
      <ReplayLoadingOverlay />
      {replayCompleted && (
        <ReplayTimeline
          fromDate={replayQuery?.startTime}
          toDate={replayQuery?.endTime}
          onClose={() => {
            useReplayStore.getState().reset();
            useAnimationStore.getState().reset();
            unregisterReplayLayers();
            showLiveShips(); // 라이브 선박 다시 표시
            shipBatchRenderer.immediateRender();
          }}
        />
      )}
    </>
  );
}
