"use client";

import { useState, useEffect, useCallback, createContext, useContext, ReactNode } from "react";
import io, { Socket } from "socket.io-client";
import { toast } from "sonner";

interface LocationType {
  latitude: number;
  longitude: number;
  accuracy: number;
  timestamp: number;
}

interface SocketContextType {
  socket: Socket | null;
  isConnected: boolean;
  location: LocationType | null;
  startSharing: (token: string) => void;
  stopSharing: () => void;
  joinLocationView: (token: string) => void;
  updateLocation: (location: LocationType) => void;
}

const SocketContext = createContext<SocketContextType>({
  socket: null,
  isConnected: false,
  location: null,
  startSharing: () => {},
  stopSharing: () => {},
  joinLocationView: () => {},
  updateLocation: () => {},
});

export const SocketProvider = ({ children }: { children: ReactNode }) => {
  const [socket, setSocket] = useState<Socket | null>(null);
  const [isConnected, setIsConnected] = useState(false);
  const [location, setLocation] = useState<LocationType | null>(null);

  useEffect(() => {
    // Initialize socket connection
    const socketInstance = io(process.env.NEXT_PUBLIC_SOCKET_URL || "http://localhost:3001", {
      transports: ["websocket"],
      autoConnect: true,
    });

    socketInstance.on("connect", () => {
      setIsConnected(true);
      console.log("Connected to socket server");
    });

    socketInstance.on("disconnect", () => {
      setIsConnected(false);
      console.log("Disconnected from socket server");
    });

    socketInstance.on("location-update", (data: LocationType) => {
      setLocation(data);
    });

    socketInstance.on("error", (error: string) => {
      toast.error(error);
    });

    setSocket(socketInstance);

    return () => {
      socketInstance.disconnect();
    };
  }, []);

  const startSharing = useCallback((token: string) => {
    if (socket && isConnected) {
      socket.emit("start-sharing", { token });
      toast.success("Started sharing your location");
    } else {
      toast.error("Socket connection not available");
    }
  }, [socket, isConnected]);

  const stopSharing = useCallback(() => {
    if (socket && isConnected) {
      socket.emit("stop-sharing");
      toast.success("Stopped sharing your location");
    }
  }, [socket, isConnected]);

  const joinLocationView = useCallback((token: string) => {
    if (socket && isConnected) {
      socket.emit("join-location", { token });
    } else {
      // If socket isn't connected yet, we'll attempt to connect when it becomes available
      const checkInterval = setInterval(() => {
        if (socket && isConnected) {
          socket.emit("join-location", { token });
          clearInterval(checkInterval);
        }
      }, 1000);

      // Clean up interval after 10 seconds if still not connected
      setTimeout(() => clearInterval(checkInterval), 10000);
    }
  }, [socket, isConnected]);

  const updateLocation = useCallback((locationData: LocationType) => {
    if (socket && isConnected) {
      socket.emit("update-location", locationData);
    }
  }, [socket, isConnected]);

  return (
    <SocketContext.Provider
      value={{
        socket,
        isConnected,
        location,
        startSharing,
        stopSharing,
        joinLocationView,
        updateLocation,
      }}
    >
      {children}
    </SocketContext.Provider>
  );
};

export const useSocket = () => useContext(SocketContext); 