import type { Socket } from 'socket.io-client'
import { createSharedComposable } from '@vueuse/core'
import { io } from 'socket.io-client'
import { parseURL } from 'ufo'

export const useSignaling = createSharedComposable(() => {
  const { emit } = useEventBus()
  const { me } = useAuth()

  const socket = shallowRef<Socket>()

  const connected = ref(false)

  watch(socket, (socket, prevSocket) => {
    if (prevSocket) {
      prevSocket.close()
    }

    if (!socket) {
      return
    }

    if (import.meta.dev) {
      socket.onAny((event, ...args) => {
        console.info('[onAny]', event, args)
      })

      socket.onAnyOutgoing((event, ...args) => {
        console.info('[onAnyOutgoing]', event, args)
      })
    }

    socket.on('connect', async () => {
      connected.value = true
    })

    socket.on('disconnect', async () => {
      connected.value = false
    })
  }, { immediate: true, flush: 'sync' })

  watch(connected, (connected) => {
    if (connected)
      emit('socket:connected')
    else
      emit('socket:disconnected')
  }, { immediate: true })

  watch(me, (me) => {
    if (!me) {
      socket.value?.close()
      socket.value = undefined
    }
  })

  onScopeDispose(() => {
    socket.value?.close()
    socket.value = undefined
  })

  function connect() {
    if (socket.value || !me.value)
      return

    const { protocol, host, pathname } = parseURL(__API_BASE_URL__)

    const uri = host ? `${protocol}//${host}` : ``

    socket.value = io(uri, {
      path: `${pathname}/ws`,
      transports: ['websocket'],
      withCredentials: true,
      auth: {
        userId: me.value.id,
      },
    })
  }

  return {
    socket,
    connected,
    connect,
  }
})
