/**
 * In-memory implementation of ISessionRepository for development/testing.
 */
import type { Session } from '@core/racing/domain/entities/Session';
import type { SessionRepository } from '@core/racing/domain/repositories/SessionRepository';
import type { Logger } from '@core/shared/domain/Logger';

export class InMemorySessionRepository implements SessionRepository {
  private sessions: Map<string, Session> = new Map();
  private readonly logger: Logger;

  constructor(logger: Logger, seedData?: Session[]) {
    this.logger = logger;
    this.logger.info('InMemorySessionRepository initialized.');
    if (seedData) {
      seedData.forEach(session => this.sessions.set(session.id, session));
      this.logger.debug(`Seeded ${seedData.length} sessions.`);
    }
  }

  async findById(id: string): Promise<Session | null> {
    this.logger.debug(`Finding session by id: ${id}`);
    try {
      const session = this.sessions.get(id) ?? null;
      if (session) {
        this.logger.info(`Found session: ${id}.`);
      } else {
        this.logger.warn(`Session with id ${id} not found.`);
      }
      return session;
    } catch (error) {
      this.logger.error(`Error finding session by id ${id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async findAll(): Promise<Session[]> {
    this.logger.debug('Finding all sessions.');
    try {
      const sessions = Array.from(this.sessions.values());
      this.logger.info(`Found ${sessions.length} sessions.`);
      return sessions;
    } catch (error) {
      this.logger.error('Error finding all sessions:', error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async findByRaceEventId(raceEventId: string): Promise<Session[]> {
    this.logger.debug(`Finding sessions by race event id: ${raceEventId}`);
    try {
      const sessions = Array.from(this.sessions.values()).filter(
        session => session.raceEventId === raceEventId
      );
      this.logger.info(`Found ${sessions.length} sessions for race event id: ${raceEventId}.`);
      return sessions;
    } catch (error) {
      this.logger.error(`Error finding sessions by race event id ${raceEventId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async findByLeagueId(leagueId: string): Promise<Session[]> {
    this.logger.debug(`Finding sessions by league id: ${leagueId} (not directly supported, returning empty).`);
    // Sessions don't have leagueId directly - would need to join with RaceEvent
    // For now, return empty array
    return [];
  }

  async findByStatus(status: string): Promise<Session[]> {
    this.logger.debug(`Finding sessions by status: ${status}`);
    try {
      const sessions = Array.from(this.sessions.values()).filter(
        session => session.status === status
      );
      this.logger.info(`Found ${sessions.length} sessions with status: ${status}.`);
      return sessions;
    } catch (error) {
      this.logger.error(`Error finding sessions by status ${status}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async create(session: Session): Promise<Session> {
    this.logger.debug(`Creating session: ${session.id}`);
    try {
      if (this.sessions.has(session.id)) {
        this.logger.warn(`Session with ID ${session.id} already exists.`);
        throw new Error(`Session with ID ${session.id} already exists`);
      }
      this.sessions.set(session.id, session);
      this.logger.info(`Session ${session.id} created successfully.`);
      return session;
    } catch (error) {
      this.logger.error(`Error creating session ${session.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async update(session: Session): Promise<Session> {
    this.logger.debug(`Updating session: ${session.id}`);
    try {
      if (!this.sessions.has(session.id)) {
        this.logger.warn(`Session with ID ${session.id} not found for update.`);
        throw new Error(`Session with ID ${session.id} not found`);
      }
      this.sessions.set(session.id, session);
      this.logger.info(`Session ${session.id} updated successfully.`);
      return session;
    } catch (error) {
      this.logger.error(`Error updating session ${session.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async delete(id: string): Promise<void> {
    this.logger.debug(`Deleting session: ${id}`);
    try {
      if (this.sessions.delete(id)) {
        this.logger.info(`Session ${id} deleted successfully.`);
      } else {
        this.logger.warn(`Session with id ${id} not found for deletion.`);
      }
    } catch (error) {
      this.logger.error(`Error deleting session ${id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async exists(id: string): Promise<boolean> {
    this.logger.debug(`Checking existence of session with id: ${id}`);
    try {
      const exists = this.sessions.has(id);
      this.logger.debug(`Session ${id} exists: ${exists}.`);
      return exists;
    } catch (error) {
      this.logger.error(`Error checking existence of session with id ${id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  // Test helper methods
  clear(): void {
    this.logger.debug('Clearing all sessions.');
    this.sessions.clear();
    this.logger.info('All sessions cleared.');
  }

  getAll(): Session[] {
    this.logger.debug('Getting all sessions.');
    try {
      const sessions = Array.from(this.sessions.values());
      this.logger.info(`Retrieved ${sessions.length} sessions.`);
      return sessions;
    } catch (error) {
      this.logger.error(`Error getting all sessions:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }
}