import { useEffect, useRef, useCallback, useState } from "react";

export const useWebSocket = (url, onMessage) => {
  const [isConnected, setIsConnected] = useState(false);
  const isConnectedRef = useRef(false);
  const [error, setError] = useState(null);
  const wsRef = useRef(null);
  const reconnectTimeoutRef = useRef(null);
  const reconnectAttempts = useRef(0);

  useEffect(() => {
    isConnectedRef.current = isConnected;
  }, [isConnected]);

  const connect = useCallback(() => {
    if (wsRef.current?.readyState === WebSocket.OPEN) return;

    try {
      console.log("Connecting to WebSocket:", url);
      const ws = new WebSocket(url);
      wsRef.current = ws;

      ws.onopen = () => {
        console.log("WebSocket connected successfully");
        setIsConnected(true);
        setError(null);
        reconnectAttempts.current = 0;
      };

      ws.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data);
          console.log("WebSocket message received:", data);
          onMessage(data);
        } catch (err) {
          console.error("Failed to parse WebSocket message:", err);
        }
      };

      ws.onerror = (event) => {
        console.error("WebSocket error:", event);
        console.error("WebSocket readyState:", ws.readyState);
        setError("Connection error occurred");
      };

      ws.onclose = (event) => {
        console.log(
          "WebSocket closed:",
          event.code,
          event.reason,
          "Clean:",
          event.wasClean,
        );
        setIsConnected(false);

        // Не переподключаемся если закрыто intentionally или с ошибкой авторизации
        if (event.code === 1008 || event.code === 1000) {
          console.log(
            "Connection closed intentionally or auth error, not reconnecting",
          );
          return;
        }

        // Reconnect with exponential backoff
        if (reconnectAttempts.current < 5) {
          const delay = Math.min(
            1000 * Math.pow(2, reconnectAttempts.current),
            30000,
          );
          console.log(`Reconnecting in ${delay}ms...`);
          reconnectTimeoutRef.current = setTimeout(() => {
            reconnectAttempts.current++;
            connect();
          }, delay);
        } else {
          setError("Max reconnection attempts reached");
        }
      };
    } catch (err) {
      console.error("Failed to create WebSocket:", err);
      setError(err.message);
    }
  }, [url, onMessage]);

  const disconnect = useCallback(() => {
    if (reconnectTimeoutRef.current) {
      clearTimeout(reconnectTimeoutRef.current);
    }
    if (wsRef.current) {
      wsRef.current.close(1000, "Intentional disconnect");
      wsRef.current = null;
    }
    setIsConnected(false);
  }, []);

  const sendMessage = useCallback((message) => {
    if (wsRef.current?.readyState === WebSocket.OPEN) {
      wsRef.current.send(JSON.stringify(message));
      console.log("Message sent:", message);
      return true;
    }
    console.warn(
      "WebSocket is not connected, readyState:",
      wsRef.current?.readyState,
    );
    setError("Cannot send message: WebSocket not connected");
    return false;
  }, []);

  useEffect(() => {
    connect();
    return () => disconnect();
  }, [connect, disconnect]);

  return {
    isConnectedRef,
    isConnected,
    error,
    sendMessage,
    disconnect,
  };
};
