import { onMounted, onBeforeUnmount, watch } from 'vue'
import type { Ref } from 'vue'
import { eventBus } from './eventBus'

// Singleton BroadcastChannel for cross-tab event relay.
// When this tab receives an SSE event it rebroadcasts it so other tabs
// (which may not have received it from the server) can react immediately.
const tabChannel =
  typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel('app_events') : null

function emitEvent(data: any) {
  eventBus.emit(data.type, data)
  eventBus.emit('sse', data)
}

if (tabChannel) {
  // Receive events that were relayed by another tab and emit them locally.
  tabChannel.onmessage = (msg) => {
    emitEvent(msg.data)
  }
}

export function useBackendEvents(userId: Ref<string>) {
  let eventSource: EventSource | null = null

  const connect = () => {
    if (eventSource) eventSource.close()
    if (userId.value) {
      // Auth is cookie-based; the browser sends the access_token cookie automatically
      eventSource = new EventSource(`/api/events`)

      eventSource.onmessage = (event) => {
        const data = JSON.parse(event.data)

        // Emit locally and relay to all other same-origin tabs.
        emitEvent(data)
        tabChannel?.postMessage(data)
      }
    }
  }

  onMounted(connect)
  watch(userId, connect)
  onBeforeUnmount(() => {
    eventSource?.close()
  })
}
