/* eslint-disable @typescript-eslint/no-explicit-any */
import React, {
  createContext,
  useContext,
  ReactNode,
  useEffect,
  useState,
  useRef,
  useCallback,
} from "react";
import { getChatConfig } from "../Chat.config";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

interface ChatProviderProps {
  userId: string;
  children: ReactNode;
}

interface ChatContextType {
  socket: WebSocket | null;
  userId: string;
  // onlineUsers: any[];
  sendMessage: (data: any) => void;
  isConnected: boolean;
  onlineUsers: Set<string>; // Change to Set for better performance
  isUserOnline: (userId: string) => boolean; // Add helper function
}

const ChatContext = createContext<ChatContextType | null>(null);
const queryClient = new QueryClient();

export const ChatProvider: React.FC<ChatProviderProps> = ({
  userId,
  children,
}) => {
  const socketRef = useRef<WebSocket | null>(null);
  const [socket, setSocket] = useState<WebSocket | null>(null);
  // const [onlineUsers, setOnlineUsers] = useState<any[]>([]);
  const [onlineUsers, setOnlineUsers] = useState<Set<string>>(new Set());
  const [isConnected, setIsConnected] = useState(false);
  const reconnectAttempts = useRef(0);
  const maxReconnectAttempts = 5;
  const reconnectInterval = 5000; // 5 seconds
  const { webSocketUrl,role } = getChatConfig();

  const connectWebSocket = useCallback(() => {
    // console.log("🔌 Creating new WebSocket connection...");

    // Convert HTTP URL to WebSocket URL
    const wsUrl = webSocketUrl.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
    const socketInstance = new WebSocket(
      `${wsUrl}?userId=${encodeURIComponent(userId)}&role=${encodeURIComponent(role)}`
    );

    socketInstance.onopen = () => {
      // console.log("✅ WebSocket connected");
      setIsConnected(true);
      reconnectAttempts.current = 0;

      // Send initial handshake if needed
      socketInstance.send(
        JSON.stringify({
          event: "handshake",
          userId: userId,
          role: role,
        })
      );
    };

    socketInstance.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);

        if (data.event === "getOnlineUsers") {
          // console.log("Online users update:", data.data);
          setOnlineUsers(new Set(data.data));
        }

        // Handle other message types here
        // console.log("Received message:", data);
      } catch (error) {
        console.error("Error parsing message:", error);
      }
    };

    socketInstance.onerror = (error) => {
      console.error("❌ WebSocket error:", error);
    };

    socketInstance.onclose = () => {
      // console.log("🔌 WebSocket connection closed", event);
      // console.log("❌ WebSocket disconnected:", event.code, event.reason);
      setIsConnected(false);

      // Attempt reconnection
      if (reconnectAttempts.current < maxReconnectAttempts) {
        reconnectAttempts.current += 1;
        // console.log(
        //   `Attempting to reconnect (${reconnectAttempts.current}/${maxReconnectAttempts})...`
        // );
        setTimeout(connectWebSocket, reconnectInterval);
      }
    };

    socketRef.current = socketInstance;
    setSocket(socketInstance);
  }, [webSocketUrl, userId]);

  const sendMessage = useCallback((data: any) => {
    if (socketRef.current?.readyState === WebSocket.OPEN) {
      socketRef.current.send(JSON.stringify(data));
    } else {
      console.error("Cannot send message - WebSocket not connected");
    }
  }, []);

  // useEffect(() => {
  //   connectWebSocket();

  //   return () => {
  //     // console.log("❌ Closing WebSocket connection...");
  //     if (socketRef.current) {
  //       socketRef.current.close(1000, "Component unmounted");
  //       socketRef.current = null;
  //     }
  //   };
  // }, [connectWebSocket]);


  useEffect(() => {
    connectWebSocket();
  
    return () => {
      // Gracefully notify backend before closing
      if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
        socketRef.current.send(
          JSON.stringify({
            event: "disconnect",
            userId,
            role,
          })
        );
        socketRef.current.close(1000, "Component unmounted");
      }
      socketRef.current = null;
    };
  }, [connectWebSocket]);
  

  const isUserOnline = useCallback(
    (userId: string) => {
      return onlineUsers.has(userId);
    },
    [onlineUsers]
  );

  return (
    <QueryClientProvider client={queryClient}>
      <ChatContext.Provider
        value={{
          socket,
          userId,
          onlineUsers,
          sendMessage,
          isConnected,
          isUserOnline,
        }}
      >
        {children}
      </ChatContext.Provider>
    </QueryClientProvider>
  );
};

export const useChatContext = () => {
  const context = useContext(ChatContext);
  if (!context) {
    throw new Error("useChatContext must be used within a ChatProvider");
  }
  return context;
};
