/**
 * 선박 Deck.gl 레이어 관리 훅
 * - OpenLayers 맵과 Deck.gl 레이어 통합
 * - 배치 렌더러 기반 최적화된 렌더링
 * - 선박 데이터 변경 시 레이어 업데이트
 * - 항적 레이어: 정적(경로/포인트) 캐싱 + 동적(가상선박) 경량 갱신
 *
 * 참조: mda-react-front/src/common/deck.ts
 */
import { useEffect, useRef, useCallback } from 'react';
import { Deck } from '@deck.gl/core';
import { toLonLat } from 'ol/proj';
import { createShipLayers, clearClusterCache } from '../map/layers/shipLayer';
import useShipStore from '../stores/shipStore';
import { useTrackQueryStore } from '../tracking/stores/trackQueryStore';
import useTrackingModeStore from '../stores/trackingModeStore';
import { useMapStore } from '../stores/mapStore';
import { getTrackQueryLayers } from '../tracking/utils/trackQueryLayerUtils';
import { getReplayLayers } from '../replay/utils/replayLayerRegistry';
import { shipBatchRenderer } from '../map/ShipBatchRenderer';

/**
 * 선박 레이어 관리 훅
 * @param {Object} map - OpenLayers 맵 인스턴스
 * @returns {Object} { deckCanvas }
 */
export default function useShipLayer(map) {
  const deckRef = useRef(null);
  const canvasRef = useRef(null);
  const animationFrameRef = useRef(null);
  const batchRendererInitialized = useRef(false);

  const getSelectedShips = useShipStore((s) => s.getSelectedShips);
  const isShipVisible = useShipStore((s) => s.isShipVisible);

  // 마지막 선박 레이어: 캐시용
  const lastShipLayersRef = useRef([]);

  /**
   * Deck.gl 인스턴스 초기화
   */
  const initDeck = useCallback((container) => {
    if (deckRef.current) return;

    const canvas = document.createElement('canvas');
    canvas.id = 'deck-canvas';
    canvas.style.position = 'absolute';
    canvas.style.left = '0';
    canvas.style.top = '0';
    canvas.style.width = '100%';
    canvas.style.height = '100%';
    canvas.style.pointerEvents = 'none';
    canvas.style.zIndex = '0';
    container.appendChild(canvas);
    canvasRef.current = canvas;

    deckRef.current = new Deck({
      canvas,
      controller: false,
      layers: [],
      useDevicePixels: true,
      pickingRadius: 12,
      onError: (error) => {
        console.error('[Deck.gl] Error:', error);
      },
    });
  }, []);

  /**
   * Deck.gl viewState를 OpenLayers 뷰와 동기화
   */
  const syncViewState = useCallback(() => {
    if (!map || !deckRef.current) return;

    const view = map.getView();
    const center = view.getCenter();
    const zoom = view.getZoom();
    const rotation = view.getRotation();

    if (!center || zoom === undefined) return;

    const [lon, lat] = toLonLat(center);

    deckRef.current.setProps({
      viewState: {
        longitude: lon,
        latitude: lat,
        zoom: zoom - 1,
        bearing: (-rotation * 180) / Math.PI,
        pitch: 0,
      },
    });
  }, [map]);

  /**
   * 뷰포트 범위 계산
   */
  const getViewportBounds = useCallback(() => {
    if (!map) return null;

    const view = map.getView();
    const size = map.getSize();
    if (!size) return null;

    const extent = view.calculateExtent(size);
    const [minX, minY, maxX, maxY] = extent;
    const [minLon, minLat] = toLonLat([minX, minY]);
    const [maxLon, maxLat] = toLonLat([maxX, maxY]);

    return { minLon, maxLon, minLat, maxLat };
  }, [map]);

  /**
   * 배치 렌더러 콜백 - 선박 레이어 생성 + 캐싱된 항적 레이어 병합
   */
  const handleBatchRender = useCallback((ships, trigger) => {
    if (!deckRef.current || !map) return;

    const view = map.getView();
    const zoom = view.getZoom() || 7;
    const selectedShips = getSelectedShips();

    const { showLabels: currentShowLabels, labelOptions: currentLabelOptions, isIntegrate: currentIsIntegrate, darkSignalIds } = useShipStore.getState();

    // 라이브 선박 숨김 상태 확인
    const { hideLiveShips } = useTrackQueryStore.getState();

    // 선박 레이어 생성 (hideLiveShips일 때는 빈 배열)
    const shipLayers = hideLiveShips
      ? []
      : createShipLayers(ships, selectedShips, zoom, currentShowLabels, currentLabelOptions, currentIsIntegrate, trigger, darkSignalIds);

    // 선박 레이어 캐시
    lastShipLayersRef.current = shipLayers;

    // 항적 레이어 (tracking 패키지 전역 레지스트리에서 가져옴)
    const trackLayers = getTrackQueryLayers();

    // 리플레이 레이어 (전역 레지스트리)
    const replayLayers = getReplayLayers();

    // 병합: 선박 + 항적 + 리플레이 레이어
    deckRef.current.setProps({
      layers: [...shipLayers, ...trackLayers, ...replayLayers],
    });
  }, [map, getSelectedShips]);

  /**
   * 선박 레이어 업데이트 (배치 렌더러 사용)
   */
  const updateLayers = useCallback(() => {
    if (!deckRef.current || !map) return;

    if (!isShipVisible) {
      deckRef.current.setProps({ layers: [] });
      return;
    }

    const view = map.getView();
    const zoom = view.getZoom() || 10;
    const zoomIntChanged = shipBatchRenderer.setZoom(zoom);

    const bounds = getViewportBounds();
    shipBatchRenderer.setViewportBounds(bounds);

    if (zoomIntChanged) {
      clearClusterCache();
      shipBatchRenderer.immediateRender();
      return;
    }

    shipBatchRenderer.requestRender();
  }, [map, isShipVisible, getViewportBounds]);

  /**
   * 렌더링 루프
   */
  const render = useCallback(() => {
    syncViewState();
    updateLayers();
    deckRef.current?.redraw();
  }, [syncViewState, updateLayers]);

  // 맵 초기화 및 이벤트 바인딩
  useEffect(() => {
    if (!map) return;

    const viewport = map.getViewport();
    initDeck(viewport);

    if (!batchRendererInitialized.current) {
      shipBatchRenderer.initialize(handleBatchRender);
      batchRendererInitialized.current = true;
    }

    const handleMoveEnd = () => { render(); };
    const handlePostRender = () => {
      syncViewState();
      deckRef.current?.redraw();
    };

    map.on('moveend', handleMoveEnd);
    map.on('postrender', handlePostRender);

    setTimeout(() => { render(); }, 100);

    return () => {
      map.un('moveend', handleMoveEnd);
      map.un('postrender', handlePostRender);

      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }

      if (deckRef.current) {
        deckRef.current.finalize();
        deckRef.current = null;
      }

      if (canvasRef.current) {
        canvasRef.current.remove();
        canvasRef.current = null;
      }

      shipBatchRenderer.dispose();
      batchRendererInitialized.current = false;
    };
  }, [map, initDeck, render, syncViewState, handleBatchRender]);

  // 선박 데이터 변경 시 레이어 업데이트
  useEffect(() => {
    const unsubscribe = useShipStore.subscribe(
      (state) => [state.features, state.kindVisibility, state.sourceVisibility, state.isShipVisible, state.detailModals, state.isIntegrate, state.nationalVisibility, state.showLabels, state.labelOptions, state.darkSignalVisible, state.darkSignalIds],
      (current, prev) => {
        const filterChanged =
          current[1] !== prev[1] ||
          current[2] !== prev[2] ||
          current[3] !== prev[3] ||
          current[5] !== prev[5] ||
          current[6] !== prev[6] ||
          current[7] !== prev[7] ||
          current[8] !== prev[8] ||
          current[9] !== prev[9] ||
          current[10] !== prev[10];

        if (filterChanged) {
          shipBatchRenderer.clearCache();
          clearClusterCache();
          shipBatchRenderer.immediateRender();
          return;
        }

        updateLayers();
      },
      { equalityFn: (a, b) => a.every((v, i) => v === b[i]) }
    );

    return () => { unsubscribe(); };
  }, [updateLayers]);

  // === trackQueryStore 변경 시 선박 레이어 리렌더 ===
  // tracking 패키지의 TrackQueryViewer가 레이어를 전역 레지스트리에 등록하면
  // 여기서 shipBatchRenderer를 트리거하여 deck.gl에 반영
  useEffect(() => {
    const unsubscribe = useTrackQueryStore.subscribe(
      (state) => [state.tracks, state.currentTime, state.showPoints, state.showVirtualShip, state.showLabels, state.disabledVesselIds, state.hideLiveShips],
      () => {
        if (deckRef.current && map) {
          shipBatchRenderer.requestRender();
        }
      },
      { equalityFn: (a, b) => a.every((v, i) => v === b[i]) }
    );

    return () => unsubscribe();
  }, [map]);

  // === trackingModeStore 변경 시 선박 레이어 리렌더 ===
  // 반경 필터링 상태가 변경되면 즉시 렌더링
  useEffect(() => {
    const unsubscribe = useTrackingModeStore.subscribe(
      (state) => [state.mode, state.trackedShipId, state.trackedShip, state.radiusNM],
      () => {
        if (deckRef.current && map) {
          // 반경/추적 모드 변경은 필터 변경이므로 캐시 클리어 후 즉시 렌더링
          shipBatchRenderer.clearCache();
          clearClusterCache();
          shipBatchRenderer.immediateRender();
        }
      },
      { equalityFn: (a, b) => a.every((v, i) => v === b[i]) }
    );

    return () => unsubscribe();
  }, [map]);

  // === mapStore 테마(배경지도) 변경 시 선박 레이어 리렌더 ===
  // 테마 변경 시 선박명/속도벡터/선박크기 색상이 변경되므로 즉시 렌더링
  useEffect(() => {
    const unsubscribe = useMapStore.subscribe(
      (state) => state.baseMapType,
      () => {
        if (deckRef.current && map) {
          clearClusterCache();
          shipBatchRenderer.immediateRender();
        }
      }
    );

    return () => unsubscribe();
  }, [map]);

  return {
    deckCanvas: canvasRef.current,
    deckRef,
  };
}
