import { Readable } from 'stream';

export interface FileMetadata {
  filename: string;
  size: number;
  contentType: string;
  lastModified: Date;
  etag?: string;
  path: string;
}

export interface UploadResult {
  success: boolean;
  filename: string;
  path: string;
  url: string; // API URL for accessing the file
  size: number;
  contentType: string;
  error?: string;
}

export interface StorageService {
  /**
   * Create the main bucket if it doesn't exist
   */
  createBucket(): Promise<void>;

  /**
   * Check if the main bucket exists
   */
  bucketExists(): Promise<boolean>;

  /**
   * Upload a file to storage
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category (uploads, generated, references)
   * @param filename Original filename
   * @param buffer File buffer
   * @param contentType MIME type
   */
  uploadFile(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    filename: string,
    buffer: Buffer,
    contentType: string,
  ): Promise<UploadResult>;

  /**
   * Download a file from storage
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category
   * @param filename Filename to download
   */
  downloadFile(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    filename: string,
  ): Promise<Buffer>;

  /**
   * Stream a file from storage (memory efficient)
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category
   * @param filename Filename to stream
   */
  streamFile(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    filename: string,
  ): Promise<Readable>;

  /**
   * Generate a presigned URL for downloading a file
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category
   * @param filename Filename
   * @param expirySeconds URL expiry time in seconds
   */
  getPresignedDownloadUrl(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    filename: string,
    expirySeconds: number,
  ): Promise<string>;

  /**
   * Generate a presigned URL for uploading a file
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category
   * @param filename Filename
   * @param expirySeconds URL expiry time in seconds
   * @param contentType MIME type
   */
  getPresignedUploadUrl(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    filename: string,
    expirySeconds: number,
    contentType: string,
  ): Promise<string>;

  /**
   * List files in a specific path
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category
   * @param prefix Optional prefix to filter files
   */
  listFiles(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    prefix?: string,
  ): Promise<FileMetadata[]>;

  /**
   * Delete a file from storage
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category
   * @param filename Filename to delete
   */
  deleteFile(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    filename: string,
  ): Promise<void>;

  /**
   * Check if a file exists
   * @param orgId Organization ID
   * @param projectId Project ID
   * @param category File category
   * @param filename Filename to check
   */
  fileExists(
    orgId: string,
    projectId: string,
    category: 'uploads' | 'generated' | 'references',
    filename: string,
  ): Promise<boolean>;
}
