/**
 * Send messages to the socket server
 * Listens to the event bus and emits accordingly messages to the socket server.
 */
import log from "@racletteCore/lib/logger"
import { $store } from "@racletteCore"
import { getUserToken } from "./sessionHandler"
import configService from "@racletteCore/lib/configService"
import { extractSessionIdFromUrl } from "@racletteCore/lib/workSessionUrl"
import { getActiveSocket, setActiveSocket } from "./socketRegistry"
import type { Socket } from "socket.io-client"

let eventbusRegistered = false

const registerSocketClient = ($socket: Socket, $eventbus) => {
  setActiveSocket($socket)

  if (eventbusRegistered) {
    return
  }
  eventbusRegistered = true

  $eventbus.on(
    "socket/join/room",
    (roomId?: string, options?: { bootstrap?: boolean }) => {
      const { requireAuthentication } = configService.getConfig()?.global ?? {
        requireAuthentication: true,
      }

      const sessionId = extractSessionIdFromUrl()
      const isWorkSession = !!sessionId

      if (requireAuthentication && !isWorkSession && !getUserToken()) {
        return log.socket("emitJoin", "no token and not a work session")
      }

      // Light re-join: after a transport reconnect the project is still in store;
      // skip full bootstrap and let the server use readMain (no roomId).
      const projectId = $store.getState(["project", "_id"]) as string | null
      const isLightRejoin =
        options?.bootstrap === false ||
        (!roomId && !!projectId && options?.bootstrap !== true)
      const bootstrap =
        options?.bootstrap ?? (isLightRejoin ? false : !roomId)

      log.socket("emitJoin", {
        roomId,
        bootstrap,
        isWorkSession,
        lightRejoin: isLightRejoin,
      })
      getActiveSocket()?.emit("join", { roomId, bootstrap })
    },
  )

  $eventbus.on("socket/leave/room", (roomId) => {
    log.socket("emitLeave", { roomId })
    getActiveSocket()?.emit("leave", roomId)
  })
}

export default registerSocketClient
export { registerSocketClient }
