/**
 * Infrastructure Adapter: InMemoryMediaStorageAdapter
 * 
 * In-memory implementation of MediaStoragePort for testing purposes.
 * Simulates file storage without actual filesystem operations.
 */

import type { MediaStoragePort, UploadOptions, UploadResult } from '@core/media/application/ports/MediaStoragePort';
import type { Logger } from '@core/shared/domain/Logger';

export class InMemoryMediaStorageAdapter implements MediaStoragePort {
  private storage: Map<string, Buffer> = new Map();
  private metadata: Map<string, { size: number; contentType: string }> = new Map();

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

  async uploadMedia(buffer: Buffer, options: UploadOptions): Promise<UploadResult> {
    this.logger.debug(`[InMemoryMediaStorageAdapter] Uploading media: ${options.filename}`);
    
    // Validate content type
    const allowedTypes = ['image/png', 'image/jpeg', 'image/svg+xml', 'image/gif'];
    if (!allowedTypes.includes(options.mimeType)) {
      return {
        success: false,
        errorMessage: `Content type ${options.mimeType} is not allowed`,
      };
    }

    // Generate storage key
    const storageKey = `uploaded/${Date.now()}-${options.filename.replace(/[^a-zA-Z0-9.-]/g, '_')}`;
    
    // Store buffer and metadata
    this.storage.set(storageKey, buffer);
    this.metadata.set(storageKey, {
      size: buffer.length,
      contentType: options.mimeType,
    });

    this.logger.info(`Media uploaded successfully: ${storageKey}`);

    return {
      success: true,
      filename: options.filename,
      url: storageKey,
    };
  }

  async deleteMedia(storageKey: string): Promise<void> {
    this.logger.debug(`[InMemoryMediaStorageAdapter] Deleting media: ${storageKey}`);
    
    this.storage.delete(storageKey);
    this.metadata.delete(storageKey);
    
    this.logger.info(`Media deleted successfully: ${storageKey}`);
  }

  async getBytes(storageKey: string): Promise<Buffer | null> {
    this.logger.debug(`[InMemoryMediaStorageAdapter] Getting bytes for: ${storageKey}`);
    
    const buffer = this.storage.get(storageKey) ?? null;
    
    if (buffer) {
      this.logger.info(`Retrieved bytes for: ${storageKey}`);
    } else {
      this.logger.warn(`No bytes found for: ${storageKey}`);
    }
    
    return buffer;
  }

  async getMetadata(storageKey: string): Promise<{ size: number; contentType: string } | null> {
    this.logger.debug(`[InMemoryMediaStorageAdapter] Getting metadata for: ${storageKey}`);
    
    const meta = this.metadata.get(storageKey) ?? null;
    
    if (meta) {
      this.logger.info(`Retrieved metadata for: ${storageKey}`);
    } else {
      this.logger.warn(`No metadata found for: ${storageKey}`);
    }
    
    return meta;
  }

  /**
   * Clear all stored media
   */
  clear(): void {
    this.storage.clear();
    this.metadata.clear();
    this.logger.info('[InMemoryMediaStorageAdapter] All media cleared.');
  }

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

  /**
   * Check if a storage key exists
   */
  has(storageKey: string): boolean {
    return this.storage.has(storageKey);
  }
}
