import { useEffect, useMemo, useRef, useState } from 'react'

function buildSseUrl(symbols: string[], timeframe = '1m') {
  const api = (import.meta as any).env?.VITE_API_URL || 'http://localhost:8000/api'
  const base = api.replace(/\/$/, '')
  const params = new URLSearchParams({ symbols: symbols.join(','), timeframe })
  return `${base}/stream/sse?${params.toString()}`
}

export type KlineEvent = {
  symbol: string
  timeframe: string
  open_time: string
  close_time: string
  open: number
  high: number
  low: number
  close: number
  volume: number
  is_closed: boolean
  source: string
}

export function useSSEMultiplexer(symbols: string[], timeframe = '1m') {
  const [isConnected, setIsConnected] = useState(false)
  const [error, setError] = useState<Error | null>(null)
  const [lastBySymbol, setLastBySymbol] = useState<Record<string, KlineEvent | undefined>>({})
  const esRef = useRef<EventSource | null>(null)
  const key = useMemo(() => symbols.slice().sort().join(','), [symbols])

  useEffect(() => {
    if (!symbols.length) return
    // Close previous
    if (esRef.current) {
      try { esRef.current.close() } catch {}
      esRef.current = null
    }
    const url = buildSseUrl(symbols, timeframe)
    const es = new EventSource(url)
    esRef.current = es
    setIsConnected(false)
    setError(null)

    const onOpen = () => setIsConnected(true)
    const onError = () => {
      setIsConnected(false)
      setError(new Error('SSE connection error'))
    }
    const onMessage = (ev: MessageEvent) => {
      // We expect named events 'kline'
      try {
        const data = JSON.parse(ev.data) as KlineEvent
        setLastBySymbol(prev => ({ ...prev, [data.symbol.replace('/', '')]: data }))
      } catch {}
    }
    const onKline = (ev: MessageEvent) => onMessage(ev)

    es.addEventListener('open', onOpen as any)
    es.addEventListener('error', onError as any)
    es.addEventListener('kline', onKline as any)
    // Some servers send unnamed messages
    es.addEventListener('message', onMessage as any)

    return () => {
      try {
        es.removeEventListener('open', onOpen as any)
        es.removeEventListener('error', onError as any)
        es.removeEventListener('kline', onKline as any)
        es.removeEventListener('message', onMessage as any)
        es.close()
      } catch {}
      esRef.current = null
      setIsConnected(false)
    }
  }, [key, timeframe])

  return { isConnected, error, lastBySymbol }
}
