import { useState, useEffect, useRef, useCallback } from 'react';
import {
  createVesselSignalClient,
  type VesselSignalClient,
} from '@common/services/vesselSignalClient';
import {
  getInitialVesselSnapshot,
  isVesselInitEnabled,
} from '@common/services/vesselApi';
import type { VesselPosition, MapBounds } from '@/types/vessel';

/**
 * 선박 신호 실시간 수신 훅
 *
 * 개발환경(VITE_VESSEL_SIGNAL_MODE=polling):
 *   - 60초마다 백엔드 REST API(/api/vessels/in-area)를 현재 뷰포트 bbox로 호출
 *
 * 운영환경(VITE_VESSEL_SIGNAL_MODE=websocket):
 *   - 운영 WebSocket 서버(VITE_VESSEL_WS_URL)에 직접 연결하여 실시간 수신
 *   - 수신된 전체 데이터를 현재 뷰포트 bbox로 프론트에서 필터링
 *
 * @param mapBounds MapView의 onBoundsChange로 전달받은 현재 뷰포트 bbox
 * @returns 현재 뷰포트 내 선박 목록
 */
export function useVesselSignals(mapBounds: MapBounds | null): VesselPosition[] {
  const [vessels, setVessels] = useState<VesselPosition[]>([]);
  const boundsRef = useRef<MapBounds | null>(mapBounds);
  const clientRef = useRef<VesselSignalClient | null>(null);

  useEffect(() => {
    boundsRef.current = mapBounds;
  }, [mapBounds]);

  const getViewportBounds = useCallback(() => boundsRef.current, []);

  useEffect(() => {
    const client = createVesselSignalClient();
    clientRef.current = client;

    // 운영 환경: 로그인/새로고침 직후 최근 10분치 스냅샷을 먼저 1회 로드.
    // 이후 WebSocket 수신이 시작되면 최신 신호로 갱신된다.
    // VITE_VESSEL_INIT_ENABLED=true 일 때만 활성화(기본 비활성).
    if (isVesselInitEnabled()) {
      getInitialVesselSnapshot()
        .then((initial) => {
          const bounds = boundsRef.current;
          const filtered = bounds
            ? initial.filter(
                (v) =>
                  v.lon >= bounds.minLon &&
                  v.lon <= bounds.maxLon &&
                  v.lat >= bounds.minLat &&
                  v.lat <= bounds.maxLat,
              )
            : initial;
          // WS 첫 메시지가 먼저 도착해 이미 채워졌다면 덮어쓰지 않음
          setVessels((prev) => (prev.length === 0 ? filtered : prev));
        })
        .catch((e) => console.warn('[useVesselSignals] 초기 스냅샷 실패', e));
    }

    client.start(setVessels, getViewportBounds);
    return () => {
      client.stop();
      clientRef.current = null;
    };
  }, [getViewportBounds]);

  // mapBounds가 바뀔 때마다(최초 채워질 때 + 이후 뷰포트 이동/줌마다) 즉시 1회 새로고침.
  // MapView의 onBoundsChange는 moveend/zoomend에서만 호출되므로 드래그 중 스팸은 없다.
  // 이후에도 60초 인터벌 폴링은 백그라운드에서 계속 동작.
  useEffect(() => {
    if (mapBounds && clientRef.current) {
      clientRef.current.refresh();
    }
  }, [mapBounds]);

  return vessels;
}
