import type { VesselPosition, MapBounds } from '@/types/vessel';
import { getVesselsInArea } from './vesselApi';

export interface VesselSignalClient {
  start(
    onVessels: (vessels: VesselPosition[]) => void,
    getViewportBounds: () => MapBounds | null,
  ): void;
  stop(): void;
  /**
   * 즉시 1회 새로고침. 폴링 모드에선 현재 bbox로 REST 호출,
   * WebSocket 모드에선 no-op(서버 push에 의존).
   */
  refresh(): void;
}

// 개발환경: setInterval(60s) → 백엔드 REST API 호출
class PollingVesselClient implements VesselSignalClient {
  private intervalId: ReturnType<typeof setInterval> | null = null;
  private onVessels: ((vessels: VesselPosition[]) => void) | null = null;
  private getViewportBounds: (() => MapBounds | null) | null = null;

  private async poll(): Promise<void> {
    const bounds = this.getViewportBounds?.();
    if (!bounds || !this.onVessels) return;
    try {
      const vessels = await getVesselsInArea(bounds);
      this.onVessels(vessels);
    } catch {
      // 폴링 실패 시 무시 (다음 인터벌에 재시도)
    }
  }

  start(
    onVessels: (vessels: VesselPosition[]) => void,
    getViewportBounds: () => MapBounds | null,
  ): void {
    this.onVessels = onVessels;
    this.getViewportBounds = getViewportBounds;

    // 즉시 1회 실행 후 60초 간격으로 반복
    this.poll();
    this.intervalId = setInterval(() => this.poll(), 60_000);
  }

  stop(): void {
    if (this.intervalId !== null) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }
    this.onVessels = null;
    this.getViewportBounds = null;
  }

  refresh(): void {
    this.poll();
  }
}

// 운영환경: 실시간 WebSocket 서버에 직접 연결
class DirectWebSocketVesselClient implements VesselSignalClient {
  private ws: WebSocket | null = null;
  private readonly wsUrl: string;

  constructor(wsUrl: string) {
    this.wsUrl = wsUrl;
  }

  start(
    onVessels: (vessels: VesselPosition[]) => void,
    getViewportBounds: () => MapBounds | null,
  ): void {
    this.ws = new WebSocket(this.wsUrl);

    this.ws.onmessage = (event) => {
      try {
        const allVessels = JSON.parse(event.data as string) as VesselPosition[];
        const bounds = getViewportBounds();

        if (!bounds) {
          onVessels(allVessels);
          return;
        }

        const filtered = allVessels.filter(
          (v) =>
            v.lon >= bounds.minLon &&
            v.lon <= bounds.maxLon &&
            v.lat >= bounds.minLat &&
            v.lat <= bounds.maxLat,
        );
        onVessels(filtered);
      } catch {
        // 파싱 실패 무시
      }
    };

    this.ws.onerror = () => {
      console.error('[vesselSignalClient] WebSocket 연결 오류');
    };

    this.ws.onclose = () => {
      console.warn('[vesselSignalClient] WebSocket 연결 종료');
    };
  }

  stop(): void {
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }

  refresh(): void {
    // 운영 WS 모드에선 서버 push에 의존하므로 별도 새로고침 동작 없음
  }
}

export function createVesselSignalClient(): VesselSignalClient {
  if (import.meta.env.VITE_VESSEL_SIGNAL_MODE === 'websocket') {
    const wsUrl = import.meta.env.VITE_VESSEL_WS_URL as string;
    return new DirectWebSocketVesselClient(wsUrl);
  }
  return new PollingVesselClient();
}
