"use client";

import { socket } from "@/socket";
import { useSession } from "next-auth/react";
import { createContext, useContext, useEffect, useState } from "react";

type SocketContextProps = {
  isConnected: boolean;
  transport: string;
};

const SocketContext = createContext<SocketContextProps | undefined>(undefined);

type SocketProviderProps = { children: React.ReactNode };

export const Socket = ({ children }: SocketProviderProps) => {
  const { status, data } = useSession();

  const [isConnected, setIsConnected] = useState(false);
  const [transport, setTransport] = useState("N/A");
  const [hasEmitted, setHasEmitted] = useState(false);

  useEffect(() => {
    if (hasEmitted || !data?.user) return;

    // const { id } = user as any;

    if (status === "authenticated") {
      // let savedStatus: string | number = localStorage.getItem("STATUS");

      // if (!savedStatus) {
      //   localStorage.setItem("STATUS", ConnectionStatus.ONLINE.toString());
      //   savedStatus = ConnectionStatus.ONLINE;
      // }

      // socket.emit("user-is-connected", { id, status: savedStatus });
      setHasEmitted(true);
    }

    if (status === "unauthenticated") {
      // socket.emit("user-is-disconnected", { id });
      setHasEmitted(true);
    }
  }, [status, hasEmitted, data]);

  // useEffect(() => {
  //   if (!usersData || usersData === "error") return;

  //   function onUserIsConnected({ id, status }: UserData) {
  //     setUsersData((prev) => {
  //       const index = prev.findIndex((user) => user.id === id);

  //       if (index === -1) return prev;

  //       const updatedUser = {
  //         ...prev[index],
  //         status,
  //       };

  //       return [...prev.slice(0, index), updatedUser, ...prev.slice(index + 1)];
  //     });

  //     socket.emit("request-user-list");
  //   }

  //   function onUserIsDisconnected({ id }: UserData) {
  //     setUsersData((prev) => {
  //       const index = prev.findIndex((user) => user.id === id);

  //       if (index === -1) return prev;

  //       const updatedUser: UserData = {
  //         ...prev[index],
  //         status: ConnectionStatus.OFFLINE,
  //       };

  //       return [...prev.slice(0, index), updatedUser, ...prev.slice(index + 1)];
  //     });
  //   }

  //   function onRequestUserList(users: {
  //     [key: string]: { id: string; status: number };
  //   }) {
  //     setUsersData((prev) => {
  //       const updateUsers = prev.map((u) => {
  //         if (!users[u.id]) return u;

  //         return {
  //           ...u,
  //           status: users[u.id].status,
  //         };
  //       });

  //       return updateUsers;
  //     });
  //   }

  //   socket.on("user-is-connected", onUserIsConnected);
  //   socket.on("user-is-disconnected", onUserIsDisconnected);
  //   socket.on("request-user-list", onRequestUserList);

  //   return () => {
  //     socket.off("user-is-connected", onUserIsConnected);
  //     socket.off("user-is-disconnected", onUserIsDisconnected);
  //     socket.off("request-user-list", onRequestUserList);
  //   };
  // }, [usersData, setUsersData]);

  useEffect(() => {
    if (socket.connected) {
      onConnect();
    }

    function onSetTransport(transport: any) {
      setTransport(transport);
    }

    function onConnect() {
      setIsConnected(true);
      setTransport(socket.io.engine.transport.name);

      socket.io.engine.on("upgrade", onSetTransport);
    }

    function onDisconnect() {
      setIsConnected(false);
      setTransport("N/A");
    }

    // function onBeforeUnload() {
    //   socket.emit("user-is-disconnected", { id: user.id });
    // }

    socket.on("connect", onConnect);
    socket.on("disconnect", onDisconnect);
    // window.addEventListener("beforeunload", onBeforeUnload);

    return () => {
      socket.io.engine.off("upgrade", onSetTransport);

      socket.off("connect", onConnect);
      socket.off("disconnect", onDisconnect);
      // window.removeEventListener("beforeunload", onBeforeUnload);
    };
  }, []);

  return (
    <SocketContext.Provider
      value={{
        isConnected,
        transport,
      }}
    >
      {children}
    </SocketContext.Provider>
  );
};

export const useSocket = (): SocketContextProps => {
  const context = useContext(SocketContext);
  if (!context) {
    throw new Error();
  }

  return context;
};
