/**
 * Event stream adapter for Sentinel integration
 * Converts gateway run events to Sentinel RunEvent format
 */

import { EventStream, RunEvent } from '@4runr/sentinel';
import { createLogger } from '@4runr/shared';

const logger = createLogger('Gateway:Sentinel:EventStream');

export class GatewayEventStream implements EventStream {
  private subscribers: Set<(event: RunEvent) => void> = new Set();

  /**
   * Subscribe to events
   */
  subscribe(callback: (event: RunEvent) => void): { unsubscribe(): void } {
    this.subscribers.add(callback);
    
    return {
      unsubscribe: () => {
        this.subscribers.delete(callback);
      }
    };
  }

  /**
   * Emit a run event to all subscribers
   */
  emit(event: RunEvent): void {
    for (const subscriber of this.subscribers) {
      try {
        subscriber(event);
      } catch (error) {
        // Log error but don't break other subscribers
        logger.error('Error in Sentinel event subscriber', { 
          error: error instanceof Error ? error.message : String(error) 
        });
      }
    }
  }

  /**
   * Emit a created event
   */
  emitCreated(runId: string): void {
    this.emit({
      type: 'created',
      runId,
      at: Date.now()
    });
  }

  /**
   * Emit a started event
   */
  emitStarted(runId: string): void {
    this.emit({
      type: 'started',
      runId,
      at: Date.now()
    });
  }

  /**
   * Emit a token event
   */
  emitToken(runId: string, tokens: number, contentBytes?: number, cost?: number): void {
    const event: RunEvent = {
      type: 'token',
      runId,
      at: Date.now(),
      tokens,
      ...(contentBytes !== undefined && { contentBytes }),
      ...(cost !== undefined && { cost })
    };
    this.emit(event);
  }

  /**
   * Emit a finish event
   */
  emitFinish(runId: string, status: 'ok' | 'error' | 'canceled'): void {
    this.emit({
      type: 'finish',
      runId,
      at: Date.now(),
      status
    });
  }

  /**
   * Emit an error event
   */
  emitError(runId: string, message: string, code?: string): void {
    const event: RunEvent = {
      type: 'error',
      runId,
      at: Date.now(),
      message,
      ...(code !== undefined && { code })
    };
    this.emit(event);
  }
}

