/**
 * Infrastructure Adapter: InMemoryAvatarRepository
 * 
 * In-memory implementation of AvatarRepository for testing purposes.
 * Stores avatar entities in memory for fast, deterministic testing.
 */

import type { Avatar } from '@core/media/domain/entities/Avatar';
import type { AvatarRepository } from '@core/media/domain/repositories/AvatarRepository';
import type { Logger } from '@core/shared/domain/Logger';

export class InMemoryAvatarRepository implements AvatarRepository {
  private avatars: Map<string, Avatar> = new Map();
  private driverAvatars: Map<string, Avatar[]> = new Map();

  constructor(private readonly logger: Logger) {
    this.logger.info('[InMemoryAvatarRepository] Initialized.');
  }

  async save(avatar: Avatar): Promise<void> {
    this.logger.debug(`[InMemoryAvatarRepository] Saving avatar: ${avatar.id} for driver: ${avatar.driverId}`);
    
    // Store by ID
    this.avatars.set(avatar.id, avatar);
    
    // Store by driver ID
    if (!this.driverAvatars.has(avatar.driverId)) {
      this.driverAvatars.set(avatar.driverId, []);
    }
    
    const driverAvatars = this.driverAvatars.get(avatar.driverId)!;
    const existingIndex = driverAvatars.findIndex(a => a.id === avatar.id);
    
    if (existingIndex > -1) {
      driverAvatars[existingIndex] = avatar;
    } else {
      driverAvatars.push(avatar);
    }
    
    this.logger.info(`Avatar ${avatar.id} for driver ${avatar.driverId} saved successfully.`);
  }

  async findById(id: string): Promise<Avatar | null> {
    this.logger.debug(`[InMemoryAvatarRepository] Finding avatar by ID: ${id}`);
    const avatar = this.avatars.get(id) ?? null;
    
    if (avatar) {
      this.logger.info(`Found avatar by ID: ${id}`);
    } else {
      this.logger.warn(`Avatar with ID ${id} not found.`);
    }
    
    return avatar;
  }

  async findActiveByDriverId(driverId: string): Promise<Avatar | null> {
    this.logger.debug(`[InMemoryAvatarRepository] Finding active avatar for driver: ${driverId}`);
    
    const driverAvatars = this.driverAvatars.get(driverId) ?? [];
    const activeAvatar = driverAvatars.find(avatar => avatar.isActive) ?? null;
    
    if (activeAvatar) {
      this.logger.info(`Found active avatar for driver ${driverId}: ${activeAvatar.id}`);
    } else {
      this.logger.warn(`No active avatar found for driver: ${driverId}`);
    }
    
    return activeAvatar;
  }

  async findByDriverId(driverId: string): Promise<Avatar[]> {
    this.logger.debug(`[InMemoryAvatarRepository] Finding all avatars for driver: ${driverId}`);
    
    const driverAvatars = this.driverAvatars.get(driverId) ?? [];
    this.logger.info(`Found ${driverAvatars.length} avatars for driver ${driverId}.`);
    
    return driverAvatars;
  }

  async delete(id: string): Promise<void> {
    this.logger.debug(`[InMemoryAvatarRepository] Deleting avatar with ID: ${id}`);
    
    const avatarToDelete = this.avatars.get(id);
    if (!avatarToDelete) {
      this.logger.warn(`Avatar with ID ${id} not found for deletion.`);
      return;
    }
    
    // Remove from avatars map
    this.avatars.delete(id);
    
    // Remove from driver avatars
    const driverAvatars = this.driverAvatars.get(avatarToDelete.driverId);
    if (driverAvatars) {
      const filtered = driverAvatars.filter(avatar => avatar.id !== id);
      if (filtered.length > 0) {
        this.driverAvatars.set(avatarToDelete.driverId, filtered);
      } else {
        this.driverAvatars.delete(avatarToDelete.driverId);
      }
    }
    
    this.logger.info(`Avatar ${id} deleted successfully.`);
  }

  /**
   * Clear all avatars from the repository
   */
  clear(): void {
    this.avatars.clear();
    this.driverAvatars.clear();
    this.logger.info('[InMemoryAvatarRepository] All avatars cleared.');
  }

  /**
   * Get the total number of avatars stored
   */
  get size(): number {
    return this.avatars.size;
  }
}
