/**
 * 선박 데이터 관리 훅
 * - 초기 선박 데이터 API 로드 (/all/12)
 * - STOMP WebSocket 연결 및 구독
 * - 선박 데이터 수신 및 스토어 업데이트
 * - 배치 머지 최적화 (1초 or 500건)
 *
 * 참조: mda-react-front/src/map/MapUpdater.tsx
 * 위성통신망 환경 최적화: 최소 트래픽, 최소 스펙
 */
import { useEffect, useRef, useCallback, useState } from 'react';
import {
  signalStompClient,
  connectStomp,
  disconnectStomp,
  subscribeShips,
  subscribeShipDelete,
} from '../common/stompClient';
import useShipStore from '../stores/shipStore';
import { fetchAllSignals } from '../api/signalApi';

// =====================
// 배치 머지 설정
// =====================
const BATCH_CONFIG = {
  maxInterval: 1000,  // 최대 대기 시간 (1초)
  maxCount: 500,      // 최대 버퍼 크기 (500건)
};

/**
 * 선박 데이터 관리 훅
 * @param {Object} options - 옵션
 * @param {boolean} options.autoConnect - 자동 연결 여부 (기본값: true)
 * @returns {Object} { isConnected, isLoading, connect, disconnect }
 */
export default function useShipData(options = {}) {
  const { autoConnect = true } = options;

  const subscriptionsRef = useRef([]);
  const shipBufferRef = useRef([]);
  const batchTimerRef = useRef(null);
  const initialLoadDoneRef = useRef(false);
  const [isLoading, setIsLoading] = useState(true);
  const { mergeFeatures, deleteFeatureById, setConnected, isConnected } = useShipStore();

  /**
   * 버퍼된 선박 데이터 머지 실행
   */
  const flushBuffer = useCallback(() => {
    if (shipBufferRef.current.length === 0) return;

    // 버퍼 복사 후 초기화
    const ships = shipBufferRef.current;
    shipBufferRef.current = [];

    // 타이머 클리어
    if (batchTimerRef.current) {
      clearTimeout(batchTimerRef.current);
      batchTimerRef.current = null;
    }

    // 머지 실행
    mergeFeatures(ships);
  }, [mergeFeatures]);

  /**
   * 선박 메시지 수신 핸들러 (배치 처리)
   * 조건: 1초 경과 OR 500건 누적 시 머지
   */
  const handleShipMessage = useCallback((ships) => {
    // 버퍼에 추가
    shipBufferRef.current.push(...ships);

    // 조건 1: 500건 이상이면 즉시 머지
    if (shipBufferRef.current.length >= BATCH_CONFIG.maxCount) {
      flushBuffer();
      return;
    }

    // 조건 2: 타이머가 없으면 1초 타이머 설정
    if (!batchTimerRef.current) {
      batchTimerRef.current = setTimeout(() => {
        flushBuffer();
      }, BATCH_CONFIG.maxInterval);
    }
  }, [flushBuffer]);

  /**
   * 선박 삭제 메시지 수신 핸들러
   * @param {string} featureId - signalSourceCode + targetId
   */
  const handleShipDelete = useCallback((featureId) => {
    deleteFeatureById(featureId);
  }, [deleteFeatureById]);

  /**
   * 토픽 구독 시작
   */
  const startSubscriptions = useCallback(() => {
    // 기존 구독 해제
    subscriptionsRef.current.forEach((sub) => {
      try {
        sub.unsubscribe();
      } catch (e) {
        // ignore
      }
    });
    subscriptionsRef.current = [];

    // 선박 토픽 구독
    const shipSub = subscribeShips(handleShipMessage);
    subscriptionsRef.current.push(shipSub);

    // 선박 삭제 토픽 구독
    const deleteSub = subscribeShipDelete(handleShipDelete);
    subscriptionsRef.current.push(deleteSub);
  }, [handleShipMessage, handleShipDelete]);

  /**
   * 연결 성공 시 토픽 구독
   */
  const handleConnect = useCallback(() => {
    setConnected(true);
    startSubscriptions();
  }, [setConnected, startSubscriptions]);

  /**
   * 연결 해제 시
   */
  const handleDisconnect = useCallback(() => {
    setConnected(false);
  }, [setConnected]);

  /**
   * 에러 발생 시
   */
  const handleError = useCallback(() => {
    setConnected(false);
  }, [setConnected]);

  /**
   * STOMP 연결 시작
   */
  const connect = useCallback(() => {
    connectStomp({
      onConnect: handleConnect,
      onDisconnect: handleDisconnect,
      onError: handleError,
    });
  }, [handleConnect, handleDisconnect, handleError]);

  /**
   * STOMP 연결 해제
   */
  const disconnect = useCallback(() => {
    // 남은 버퍼 머지
    flushBuffer();

    // 타이머 클리어
    if (batchTimerRef.current) {
      clearTimeout(batchTimerRef.current);
      batchTimerRef.current = null;
    }

    // 구독 해제
    subscriptionsRef.current.forEach((sub) => {
      try {
        sub.unsubscribe();
      } catch (e) {
        // ignore
      }
    });
    subscriptionsRef.current = [];

    disconnectStomp();
  }, [flushBuffer]);

  /**
   * 초기 선박 데이터 로드 (API 호출)
   * 참조: mda-react-front/src/map/MapUpdater.tsx (라인 128-152)
   */
  const loadInitialData = useCallback(async () => {
    if (initialLoadDoneRef.current) return;

    setIsLoading(true);
    try {
      console.log('[useShipData] Loading initial ship data...');
      const ships = await fetchAllSignals();

      if (ships.length > 0) {
        mergeFeatures(ships);
        console.log(`[useShipData] Initial load complete: ${ships.length} ships`);
      }
    } catch (error) {
      console.error('[useShipData] Initial load error:', error);
    } finally {
      initialLoadDoneRef.current = true;
      setIsLoading(false);
    }
  }, [mergeFeatures]);

  // 초기화: API로 선박 데이터 로드 후 STOMP 연결
  useEffect(() => {
    if (!autoConnect) return;

    // 1단계: API로 초기 선박 데이터 로드
    // 2단계: 로드 완료 후 STOMP 연결 (실시간 업데이트)
    const initialize = async () => {
      await loadInitialData();
      connect();
    };

    initialize();

    return () => {
      // 타이머 클리어
      if (batchTimerRef.current) {
        clearTimeout(batchTimerRef.current);
        batchTimerRef.current = null;
      }
      disconnect();
    };
  }, [autoConnect]); // loadInitialData, connect, disconnect를 deps에서 제외 (의도적)

  return {
    isConnected,
    isLoading,
    connect,
    disconnect,
  };
}
