import { useEffect, useRef, useCallback, useState } from 'react';
import { Client, StompSubscription } from '@stomp/stompjs';
import SockJS from 'sockjs-client';

interface WebSocketMessage {
  type: string;
  [key: string]: any;
}

interface UseWebSocketOptions {
  url: string;
  topics: string[];
  onMessage: (message: WebSocketMessage) => void;
  onConnect?: () => void;
  onDisconnect?: () => void;
  onError?: (error: any) => void;
}

/**
 * WebSocket 연결 Hook (STOMP over SockJS)
 */
export const useWebSocket = ({
  url,
  topics,
  onMessage,
  onConnect,
  onDisconnect,
  onError
}: UseWebSocketOptions) => {
  const clientRef = useRef<Client | null>(null);
  const subscriptionsRef = useRef<StompSubscription[]>([]);
  const [isConnected, setIsConnected] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const connect = useCallback(() => {
    if (clientRef.current?.active) {
      console.log('[WebSocket] Already connected');
      return;
    }

    console.log('[WebSocket] Connecting to', url);

    const client = new Client({
      webSocketFactory: () => new SockJS(url),
      connectHeaders: {},
      debug: (str) => {
        console.log('[WebSocket Debug]', str);
      },
      reconnectDelay: 5000,
      heartbeatIncoming: 4000,
      heartbeatOutgoing: 4000,
      onConnect: () => {
        console.log('[WebSocket] Connected');
        setIsConnected(true);
        setError(null);
        
        // 토픽 구독
        topics.forEach((topic) => {
          const subscription = client.subscribe(topic, (message) => {
            try {
              const data = JSON.parse(message.body);
              console.log('[WebSocket] Message received on', topic, data);
              onMessage(data);
            } catch (err) {
              console.error('[WebSocket] Failed to parse message', err);
            }
          });
          subscriptionsRef.current.push(subscription);
          console.log('[WebSocket] Subscribed to', topic);
        });

        onConnect?.();
      },
      onDisconnect: () => {
        console.log('[WebSocket] Disconnected');
        setIsConnected(false);
        
        // 구독 해제
        subscriptionsRef.current.forEach((sub) => sub.unsubscribe());
        subscriptionsRef.current = [];
        
        onDisconnect?.();
      },
      onStompError: (frame) => {
        console.error('[WebSocket] STOMP error', frame);
        const errorMsg = frame.headers['message'] || 'Connection error';
        setError(errorMsg);
        onError?.(frame);
      },
      onWebSocketClose: (event) => {
        console.log('[WebSocket] WebSocket closed', event);
        setIsConnected(false);
      },
      onWebSocketError: (event) => {
        console.error('[WebSocket] WebSocket error', event);
        setError('WebSocket connection error');
        onError?.(event);
      }
    });

    client.activate();
    clientRef.current = client;
  }, [url, topics, onMessage, onConnect, onDisconnect, onError]);

  const disconnect = useCallback(() => {
    if (clientRef.current) {
      console.log('[WebSocket] Disconnecting...');
      
      // 구독 해제
      subscriptionsRef.current.forEach((sub) => sub.unsubscribe());
      subscriptionsRef.current = [];
      
      // 연결 해제
      clientRef.current.deactivate();
      clientRef.current = null;
      setIsConnected(false);
    }
  }, []);

  const send = useCallback((destination: string, body: any) => {
    if (clientRef.current?.active) {
      clientRef.current.publish({
        destination,
        body: JSON.stringify(body)
      });
      console.log('[WebSocket] Message sent to', destination, body);
    } else {
      console.warn('[WebSocket] Cannot send message - not connected');
    }
  }, []);

  // 컴포넌트 마운트 시 연결, 언마운트 시 해제
  useEffect(() => {
    connect();
    
    return () => {
      disconnect();
    };
  }, [connect, disconnect]);

  return {
    isConnected,
    error,
    connect,
    disconnect,
    send
  };
};
