/**
 * Infrastructure Adapter: InMemoryLeaderboardsEventPublisher
 *
 * In-memory implementation of LeaderboardsEventPublisher.
 * Stores events in arrays for testing purposes.
 */

import {
  LeaderboardsEventPublisher,
  GlobalLeaderboardsAccessedEvent,
  DriverRankingsAccessedEvent,
  TeamRankingsAccessedEvent,
  LeaderboardsErrorEvent,
} from '../../../core/leaderboards/application/ports/LeaderboardsEventPublisher';

export class InMemoryLeaderboardsEventPublisher implements LeaderboardsEventPublisher {
  private globalLeaderboardsAccessedEvents: GlobalLeaderboardsAccessedEvent[] = [];
  private driverRankingsAccessedEvents: DriverRankingsAccessedEvent[] = [];
  private teamRankingsAccessedEvents: TeamRankingsAccessedEvent[] = [];
  private leaderboardsErrorEvents: LeaderboardsErrorEvent[] = [];
  private shouldFail: boolean = false;

  async publishGlobalLeaderboardsAccessed(event: GlobalLeaderboardsAccessedEvent): Promise<void> {
    if (this.shouldFail) throw new Error('Event publisher failed');
    this.globalLeaderboardsAccessedEvents.push(event);
  }

  async publishDriverRankingsAccessed(event: DriverRankingsAccessedEvent): Promise<void> {
    if (this.shouldFail) throw new Error('Event publisher failed');
    this.driverRankingsAccessedEvents.push(event);
  }

  async publishTeamRankingsAccessed(event: TeamRankingsAccessedEvent): Promise<void> {
    if (this.shouldFail) throw new Error('Event publisher failed');
    this.teamRankingsAccessedEvents.push(event);
  }

  async publishLeaderboardsError(event: LeaderboardsErrorEvent): Promise<void> {
    if (this.shouldFail) throw new Error('Event publisher failed');
    this.leaderboardsErrorEvents.push(event);
  }

  getGlobalLeaderboardsAccessedEventCount(): number {
    return this.globalLeaderboardsAccessedEvents.length;
  }

  getDriverRankingsAccessedEventCount(): number {
    return this.driverRankingsAccessedEvents.length;
  }

  getTeamRankingsAccessedEventCount(): number {
    return this.teamRankingsAccessedEvents.length;
  }

  getLeaderboardsErrorEventCount(): number {
    return this.leaderboardsErrorEvents.length;
  }

  clear(): void {
    this.globalLeaderboardsAccessedEvents = [];
    this.driverRankingsAccessedEvents = [];
    this.teamRankingsAccessedEvents = [];
    this.leaderboardsErrorEvents = [];
    this.shouldFail = false;
  }

  setShouldFail(shouldFail: boolean): void {
    this.shouldFail = shouldFail;
  }
}
