import { v4 as uuidv4 } from 'uuid';
import { mkdir, writeFile, unlink, readFile } from 'fs/promises';
import { join } from 'path';

/**
 * Interfaz para adapters de almacenamiento
 * 
 * Permite cambiar de storage local a cloud (S3, B2, etc.)
 * sin modificar el resto del código.
 */
export interface StorageAdapter {
  /**
   * Guardar un archivo
   * @param file - Buffer del archivo
   * @param fileName - Nombre original del archivo
   * @returns Nombre único del archivo guardado
   */
  save(file: Buffer, fileName: string): Promise<{ name: string }>;

  /**
   * Eliminar un archivo
   * @param fileName - Nombre del archivo a eliminar
   */
  delete(fileName: string): Promise<void>;

  /**
   * Obtener un archivo
   * @param fileName - Nombre del archivo
   * @returns Buffer del archivo
   */
  get(fileName: string): Promise<Buffer>;

  /**
   * Verificar si un archivo existe
   */
  exists(fileName: string): Promise<boolean>;
}

/**
 * Adapter de almacenamiento local para desarrollo
 * 
 * Guarda archivos en /uploads/documents/
 */
class LocalStorageAdapter implements StorageAdapter {
  private basePath: string;

  constructor() {
    this.basePath = join(process.cwd(), 'uploads', 'documents');
  }

  /**
   * Guardar archivo localmente
   */
  async save(file: Buffer, fileName: string): Promise<{ name: string }> {
    // Generar nombre único
    const extension = fileName.split('.').pop() || 'bin';
    const uniqueName = `${uuidv4()}.${extension}`;
    const filePath = join(this.basePath, uniqueName);

    // Crear directorio si no existe
    await mkdir(this.basePath, { recursive: true });

    // Guardar archivo
    await writeFile(filePath, file);

    console.log(`✅ [LOCAL] Archivo guardado: ${uniqueName}`);
    return { name: uniqueName };
  }

  /**
   * Eliminar archivo localmente
   */
  async delete(fileName: string): Promise<void> {
    // Extraer nombre si es una ruta completa
    const name = fileName.includes('/') ? fileName.split('/').pop()! : fileName;
    const filePath = join(this.basePath, name);

    try {
      await unlink(filePath);
      console.log(`✅ [LOCAL] Archivo eliminado: ${name}`);
    } catch (error) {
      console.warn(`⚠️ [LOCAL] Error al eliminar archivo (continuando):`, error);
      // Continuar aunque falle la eliminación
    }
  }

  /**
   * Obtener archivo localmente
   */
  async get(fileName: string): Promise<Buffer> {
    // Extraer nombre si es una ruta completa
    const name = fileName.includes('/') ? fileName.split('/').pop()! : fileName;
    const filePath = join(this.basePath, name);

    return readFile(filePath);
  }

  /**
   * Verificar si existe
   */
  async exists(fileName: string): Promise<boolean> {
    const name = fileName.includes('/') ? fileName.split('/').pop()! : fileName;
    const filePath = join(this.basePath, name);

    try {
      await readFile(filePath);
      return true;
    } catch {
      return false;
    }
  }
}

/**
 * Instancia del adapter de almacenamiento
 * 
 * Usa almacenamiento local en desarrollo.
 * Se puede cambiar a Backblaze B2 o S3 en producción.
 */
export const storageAdapter: StorageAdapter = new LocalStorageAdapter();
