import { useEffect, useRef, useState } from 'react';
import { WebSocketClient, initWebSocket, getWebSocketClient, WebSocketMessage } from '@/services/websocket';
import { useAuth } from '@/contexts/AuthContext';
import { useToast } from '@/hooks/use-toast';

export interface UseWebSocketReturn {
  isConnected: boolean;
  send: (message: any) => void;
  subscribe: (eventType: string, handler: (message: WebSocketMessage) => void) => void;
  unsubscribe: (eventType: string, handler: (message: WebSocketMessage) => void) => void;
  subscribeToOrder: (orderId: string) => void;
  sendLocationUpdate: (location: { lat: number; lng: number }) => void;
}

export function useWebSocket(): UseWebSocketReturn {
  const { user, isAuthenticated } = useAuth();
  const { toast } = useToast();
  const [isConnected, setIsConnected] = useState(false);
  const wsClientRef = useRef<WebSocketClient | null>(null);
  const handlersRef = useRef<Map<string, (message: WebSocketMessage) => void>>(new Map());

  useEffect(() => {
    if (!isAuthenticated || !user) {
      // Disconnect if not authenticated
      if (wsClientRef.current) {
        wsClientRef.current.disconnect();
        wsClientRef.current = null;
        setIsConnected(false);
      }
      return;
    }

    // Create token for WebSocket authentication
    const token = btoa(JSON.stringify({ 
      userId: user.id, 
      role: user.role,
      timestamp: Date.now()
    }));

    // Initialize WebSocket connection
    const wsClient = initWebSocket(token);
    wsClientRef.current = wsClient;

    // Connection event handlers
    wsClient.on('connected', () => {
      setIsConnected(true);
      console.log('WebSocket connected');
    });

    wsClient.on('disconnected', () => {
      setIsConnected(false);
      console.log('WebSocket disconnected');
    });

    wsClient.on('error', (message) => {
      console.error('WebSocket error:', message.data);
      toast({
        title: "Erreur de connexion",
        description: "Problème de connexion temps réel",
        variant: "destructive",
      });
    });

    wsClient.on('max_reconnect_attempts_reached', () => {
      toast({
        title: "Connexion perdue",
        description: "Impossible de reconnecter. Rechargez la page.",
        variant: "destructive",
      });
    });

    // Connect
    wsClient.connect().catch(error => {
      console.error('Failed to connect WebSocket:', error);
    });

    // Cleanup on unmount
    return () => {
      if (wsClientRef.current) {
        wsClientRef.current.disconnect();
        wsClientRef.current = null;
      }
      setIsConnected(false);
    };
  }, [isAuthenticated, user, toast]);

  // Keep connection alive with ping
  useEffect(() => {
    if (!isConnected || !wsClientRef.current) return;

    const pingInterval = setInterval(() => {
      wsClientRef.current?.ping();
    }, 30000); // Ping every 30 seconds

    return () => clearInterval(pingInterval);
  }, [isConnected]);

  const send = (message: any) => {
    if (wsClientRef.current) {
      wsClientRef.current.send(message);
    }
  };

  const subscribe = (eventType: string, handler: (message: WebSocketMessage) => void) => {
    if (wsClientRef.current) {
      wsClientRef.current.on(eventType, handler);
      handlersRef.current.set(`${eventType}_${handler.toString()}`, handler);
    }
  };

  const unsubscribe = (eventType: string, handler: (message: WebSocketMessage) => void) => {
    if (wsClientRef.current) {
      wsClientRef.current.off(eventType, handler);
      handlersRef.current.delete(`${eventType}_${handler.toString()}`);
    }
  };

  const subscribeToOrder = (orderId: string) => {
    if (wsClientRef.current) {
      wsClientRef.current.subscribeToOrder(orderId);
    }
  };

  const sendLocationUpdate = (location: { lat: number; lng: number }) => {
    if (wsClientRef.current) {
      wsClientRef.current.sendLocationUpdate(location);
    }
  };

  return {
    isConnected,
    send,
    subscribe,
    unsubscribe,
    subscribeToOrder,
    sendLocationUpdate
  };
}