import { createContext, useState, useEffect, useCallback, useRef } from 'react';
import { io } from 'socket.io-client';

export const SocketContext = createContext();

export const SocketProvider = ({ children }) => {
  const [socket, setSocket] = useState(null);
  const [connected, setConnected] = useState(false);
  const connectAttempts = useRef(0);
  const maxAttempts = 3;
  const reconnectDelay = 2000; // ms
  
  // Connect to socket server
  const connect = useCallback(() => {
    if (socket) return;
    
    // Determine server URL based on environment
    const serverUrl = process.env.NODE_ENV === 'production' 
      ? window.location.origin 
      : 'http://localhost:5287';
      
    try {
      const newSocket = io(serverUrl, {
        reconnectionAttempts: 3,
        timeout: 10000,
        reconnectionDelay: 1000
      });
      
      newSocket.on('connect', () => {
        console.log('Socket connected with ID:', newSocket.id);
        setConnected(true);
        connectAttempts.current = 0;
        
        // Store player ID in localStorage for persistence
        localStorage.setItem('playerId', newSocket.id);
      });
      
      newSocket.on('disconnect', (reason) => {
        console.log('Socket disconnected:', reason);
        setConnected(false);
      });
      
      newSocket.on('connect_error', (error) => {
        console.error('Connection error:', error);
        connectAttempts.current += 1;
        
        if (connectAttempts.current >= maxAttempts) {
          console.error('Max connection attempts reached, giving up');
          newSocket.disconnect();
        }
      });
      
      setSocket(newSocket);
    } catch (err) {
      console.error('Error creating socket connection:', err);
    }
  }, [socket]);
  
  // Disconnect socket
  const disconnect = useCallback(() => {
    if (socket) {
      socket.disconnect();
      setSocket(null);
      setConnected(false);
      console.log('Socket manually disconnected');
    }
  }, [socket]);
  
  // Send event through socket
  const send = useCallback((event, data) => {
    if (!socket || !connected) {
      console.warn(`Cannot send event "${event}": socket not connected`);
      return false;
    }
    
    try {
      socket.emit(event, data);
      return true;
    } catch (err) {
      console.error(`Error sending event "${event}":`, err);
      return false;
    }
  }, [socket, connected]);
  
  // Register event listener
  const on = useCallback((event, callback) => {
    if (!socket) {
      console.warn(`Cannot listen for event "${event}": socket not initialized`);
      return () => {};
    }
    
    socket.on(event, callback);
    return () => socket.off(event, callback);
  }, [socket]);
  
  // Clean up socket on component unmount
  useEffect(() => {
    return () => {
      if (socket) {
        socket.disconnect();
      }
    };
  }, [socket]);
  
  return (
    <SocketContext.Provider value={{ 
      socket,
      connected, 
      connect, 
      disconnect, 
      send, 
      on 
    }}>
      {children}
    </SocketContext.Provider>
  );
};
