/**
 * Client wrapper around EventSource('/api/notifications/stream').
 *
 * The auto-mounting plugin (plugins/03.notifications-stream.client.ts) uses
 * this to pipe SSE events into useToast(). It's exposed as a composable so
 * pages can also drive their own handlers (e.g. badge counters, sounds, etc.)
 * without re-implementing the connection logic.
 */

export const useNotificationStream = () => {
  const eventSource = ref<EventSource | null>(null)
  const isConnected = ref(false)
  let reconnectTimer: ReturnType<typeof setTimeout> | null = null
  let userOnNotification: ((data: any) => void) | null = null

  const start = (onNotification: (data: any) => void) => {
    if (eventSource.value) return // already running
    userOnNotification = onNotification

    const es = new EventSource('/api/notifications/stream')
    eventSource.value = es

    es.addEventListener('connected', (e: MessageEvent) => {
      isConnected.value = true
      try {
        const data = JSON.parse(e.data)
        console.log('[NotifStream] connected', data)
      } catch {
        console.log('[NotifStream] connected')
      }
    })

    es.addEventListener('notification', (e: MessageEvent) => {
      try {
        const data = JSON.parse(e.data)
        onNotification(data)
      } catch (err) {
        console.error('[NotifStream] failed to parse notification payload:', err)
      }
    })

    es.onerror = () => {
      isConnected.value = false
      // EventSource auto-reconnects on transient errors. Only act when the
      // browser has given up (readyState === CLOSED) — typically after a 401
      // or other non-recoverable response. In that case schedule a manual
      // retry rather than tight-looping.
      if (es.readyState === EventSource.CLOSED) {
        console.warn('[NotifStream] connection closed by server; will retry in 30s')
        eventSource.value = null
        if (reconnectTimer) clearTimeout(reconnectTimer)
        reconnectTimer = setTimeout(() => {
          if (userOnNotification) start(userOnNotification)
        }, 30000)
      }
    }
  }

  const stop = () => {
    if (reconnectTimer) {
      clearTimeout(reconnectTimer)
      reconnectTimer = null
    }
    if (eventSource.value) {
      eventSource.value.close()
      eventSource.value = null
      isConnected.value = false
    }
  }

  // Auto-cleanup if the composable is used inside a component.
  if (getCurrentInstance()) {
    onUnmounted(() => { stop() })
  }

  return {
    start,
    stop,
    isConnected: readonly(isConnected)
  }
}
