'use strict'
const { log } = require('./helpers')

const subscribers = new Map()
let clientIdSeq = 0

function addClient (topics, res, email) {
  const id = ++clientIdSeq
  const client = { id, res, email, topics }
  for (const t of topics) {
    if (!subscribers.has(t)) subscribers.set(t, new Set())
    subscribers.get(t).add(client)
  }
  res.on('close', () => {
    for (const t of topics) {
      const set = subscribers.get(t)
      if (set) { set.delete(client); if (!set.size) subscribers.delete(t) }
    }
    log(`SSE client #${id} disconnected (${email})`)
  })
  log(`SSE client #${id} connected (${email}) topics=[${topics.join(',')}]`)
  return id
}

function broadcast (topic, event, data) {
  const set = subscribers.get(topic)
  if (!set?.size) return 0
  const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`
  let count = 0
  for (const c of set) { try { c.res.write(payload); count++ } catch {} }
  return count
}

function broadcastAll (event, data) {
  const sent = new Set()
  let count = 0
  for (const [, set] of subscribers) {
    for (const c of set) {
      if (!sent.has(c.id)) {
        sent.add(c.id)
        try { c.res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`); count++ } catch {}
      }
    }
  }
  return count
}

function clientCount () {
  const ids = new Set()
  for (const [, set] of subscribers) for (const c of set) ids.add(c.id)
  return ids.size
}

function topicCount () { return subscribers.size }

module.exports = { addClient, broadcast, broadcastAll, clientCount, topicCount }
