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 } 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 ShipTooltip from '../components/ship/ShipTooltip';
import ShipDetailModal from '../components/ship/ShipDetailModal';
import ShipContextMenu from '../components/ship/ShipContextMenu';

import useMeasure from './measure/useMeasure';
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 { map, setMap, setZoom, center } = useMapStore();
  const { showLegend } = useShipStore();
  const hoverInfo = useShipStore((s) => s.hoverInfo);
  const detailModals = useShipStore((s) => s.detailModals);

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

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

  // 측정 도구
  useMeasure();

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

  /**
   * deck.pickObject 헬퍼
   */
  const pickShip = useCallback((pixel) => {
    const deck = deckRef.current;
    if (!deck) return null;

    // deck.layerManager가 초기화되기 전에 pickObject 호출하면 assertion error 발생
    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]);

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

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

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

      const pixel = evt.pixel;
      const ship = pickShip(pixel);

      if (ship) {
        // evt.originalEvent에서 화면 좌표 가져오기
        const { clientX, clientY } = evt.originalEvent;
        useShipStore.getState().setHoverInfo({ ship, x: clientX, y: clientY });
      } else {
        useShipStore.getState().setHoverInfo(null);
      }
    }, HOVER_THROTTLE_MS);
  }, [pickShip]);

  /**
   * 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);
  }, []);

  /**
   * 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 { worldMap, eastAsiaMap, korMap } = createBaseLayers();

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

    // 지도 인스턴스 생성
    const map = new Map({
      target: mapRef.current,
      layers: [
        worldMap,
        eastAsiaMap,
        korMap,
      ],
      view: new View({
        center: fromLonLat(center),
        zoom: 7,
        minZoom: 0,
        maxZoom: 17,
      }),
      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;

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

  return (
    <>
      <div id="map" ref={mapRef} className="map-container" />
      {showLegend && <ShipLegend />}
      {hoverInfo && (
        <ShipTooltip ship={hoverInfo.ship} x={hoverInfo.x} y={hoverInfo.y} />
      )}
      {detailModals.map((modal) => (
        <ShipDetailModal key={modal.id} modal={modal} />
      ))}
      <ShipContextMenu />
    </>
  );
}
