/**
 * Batch Queue
 *
 * Collects events and flushes them in batches based on size or time.
 */

/** Generic event type for queue */
export interface QueueableEvent {
  eventType: string;
  timestamp: string;
  [key: string]: unknown;
}

export interface BatchQueueConfig {
  /** Maximum number of events before flush */
  maxSize: number;
  /** Maximum time (ms) before flush */
  maxWait: number;
  /** Callback when batch is flushed */
  onFlush: (events: QueueableEvent[]) => Promise<void>;
}

export class BatchQueue {
  private readonly config: BatchQueueConfig;
  private queue: QueueableEvent[] = [];
  private timer: ReturnType<typeof setTimeout> | null = null;
  private flushing = false;

  constructor(config: BatchQueueConfig) {
    this.config = config;
  }

  /**
   * Add an event to the queue
   */
  add(event: QueueableEvent): void {
    this.queue.push(event);

    if (this.queue.length >= this.config.maxSize) {
      void this.flush();
    } else if (!this.timer) {
      this.timer = setTimeout(() => {
        void this.flush();
      }, this.config.maxWait);
    }
  }

  /**
   * Flush all pending events
   */
  async flush(): Promise<void> {
    if (this.flushing || this.queue.length === 0) {
      return;
    }

    this.flushing = true;

    if (this.timer) {
      clearTimeout(this.timer);
      this.timer = null;
    }

    const events = this.queue;
    this.queue = [];

    try {
      await this.config.onFlush(events);
    } finally {
      this.flushing = false;
    }
  }

  /**
   * Get current queue size
   */
  get size(): number {
    return this.queue.length;
  }
}
