import { EventEmitter } from 'node:events'

import type { TapeTrade } from '../../core/types.js'

export interface TradeSource extends EventEmitter {
  readonly name: string
  start(): void | Promise<void>
  stop(): void
}

function wrapPayload(source: string, payload: unknown): Record<string, unknown> {
  if (payload && typeof payload === 'object' && !Array.isArray(payload)) {
    return { source, ...(payload as Record<string, unknown>) }
  }

  return { source, value: payload }
}

export class MultiVenueTradeAggregator extends EventEmitter {
  constructor(private readonly sources: TradeSource[]) {
    super()

    for (const source of this.sources) {
      this.bindSource(source)
    }
  }

  async start(): Promise<void> {
    for (const source of this.sources) {
      await source.start()
    }
  }

  stop(): void {
    for (const source of this.sources) {
      source.stop()
    }
  }

  private bindSource(source: TradeSource): void {
    source.on('trade', (trade: TapeTrade) => this.emit('trade', trade))
    source.on('discover', (payload: unknown) => this.emit('discover', wrapPayload(source.name, payload)))
    source.on('ready', (payload: unknown) => this.emit('ready', wrapPayload(source.name, payload)))
    source.on('warn', (payload: unknown) => this.emit('warn', wrapPayload(source.name, payload)))
    source.on('error', (error: unknown) => this.emit('error', { source: source.name, error }))
  }
}
