/**
 * MapLibre GL + deck.gl 통합 지도 컴포넌트
 *
 * 최적화 구조:
 * - MapLibre: 래스터 베이스맵 전용 (dark/light 자동 전환)
 * - deck.gl: 모든 벡터 렌더링 (MapboxOverlay → setProps 직접 호출)
 * - React 리렌더 완전 분리: useImperativeHandle로 overlay 외부 노출
 *   → useMapLayers/useStoreLayerSync hook으로 RAF 기반 업데이트
 */
import { useRef, useEffect, useCallback, useImperativeHandle, forwardRef, memo } from 'react';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { MapboxOverlay } from '@deck.gl/mapbox';
import type { Layer } from 'deck.gl';
import { TILE_URLS, DEFAULT_CENTER, DEFAULT_ZOOM } from './constants';
import { useSettingsStore } from '@stores/settingsStore';
import type { MapHandle } from './hooks/useMapLayers';

export type { MapHandle };

interface BaseMapProps {
  center?: [number, number];
  zoom?: number;
  className?: string;
  style?: React.CSSProperties;
  height?: number | string;
  /** @deprecated useMapLayers hook 사용 권장 — 하위 호환용 */
  layers?: Layer[];
  onMapReady?: (map: maplibregl.Map) => void;
  onClick?: (info: unknown) => void;
  interactive?: boolean;
}

function createRasterStyle(theme: 'dark' | 'light'): maplibregl.StyleSpecification {
  const url = TILE_URLS[theme];
  return {
    version: 8,
    sources: {
      carto: {
        type: 'raster',
        tiles: [url.replace('{s}', 'a'), url.replace('{s}', 'b'), url.replace('{s}', 'c')],
        tileSize: 256,
      },
    },
    layers: [{ id: 'carto-tiles', type: 'raster', source: 'carto' }],
  };
}

export const BaseMap = memo(forwardRef<MapHandle, BaseMapProps>(function BaseMap(
  {
    center = DEFAULT_CENTER,
    zoom = DEFAULT_ZOOM,
    className = '',
    style,
    height = '100%',
    layers,
    onMapReady,
    onClick,
    interactive = true,
  },
  ref,
) {
  const containerRef = useRef<HTMLDivElement>(null);
  const mapRef = useRef<maplibregl.Map | null>(null);
  const overlayRef = useRef<MapboxOverlay | null>(null);
  const theme = useSettingsStore((s) => s.theme);

  const handleClick = useCallback((info: unknown) => { onClick?.(info); }, [onClick]);

  // overlay를 외부에 노출 — useMapLayers hook에서 직접 접근
  useImperativeHandle(ref, () => ({
    get overlay() { return overlayRef.current; },
    get map() { return mapRef.current; },
  }), []);

  // 지도 초기화 (1회)
  useEffect(() => {
    if (!containerRef.current || mapRef.current) return;

    const map = new maplibregl.Map({
      container: containerRef.current,
      style: createRasterStyle(theme),
      center: [center[1], center[0]],
      zoom,
      attributionControl: false,
      interactive,
    });

    if (interactive) {
      map.addControl(new maplibregl.NavigationControl({ showCompass: false }), 'top-right');
    }

    const overlay = new MapboxOverlay({ layers: [], onClick: handleClick });
    map.addControl(overlay as unknown as maplibregl.IControl);

    mapRef.current = map;
    overlayRef.current = overlay;

    map.on('load', () => { onMapReady?.(map); });

    return () => {
      // deck.gl overlay를 먼저 정리하여 WebGL 리소스 해제
      if (overlayRef.current) {
        try {
          overlayRef.current.finalize();
        } catch { /* 이미 해제된 경우 무시 */ }
      }
      map.remove();
      mapRef.current = null;
      overlayRef.current = null;
    };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // 테마 전환 시 타일 교체
  useEffect(() => {
    mapRef.current?.setStyle(createRasterStyle(theme));
  }, [theme]);

  // 하위 호환: layers prop이 전달되면 overlay에 적용
  useEffect(() => {
    if (layers && overlayRef.current) {
      overlayRef.current.setProps({ layers });
    }
  }, [layers]);

  return (
    <div
      ref={containerRef}
      className={className}
      style={{ width: '100%', height, ...style }}
    />
  );
}));
