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; // UUID (same as image.id)
  path: string;
  url: string; // CDN URL for accessing the file
  size: number;
  contentType: string;
  originalFilename?: string; // User's original filename
  fileExtension?: string; // Original extension (png, jpg, etc.)
  error?: string;
}

export interface UploadFileParams {
  orgSlug: string;
  projectSlug: string;
  imageId: string;
  buffer: Buffer;
  contentType: string;
  originalFilename?: 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
   * Path format: {orgSlug}/{projectSlug}/img/{imageId}
   */
  uploadFile(params: UploadFileParams): Promise<UploadResult>;

  /**
   * Download a file from storage
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param imageId UUID filename
   */
  downloadFile(
    orgSlug: string,
    projectSlug: string,
    imageId: string,
  ): Promise<Buffer>;

  /**
   * Stream a file from storage (memory efficient)
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param imageId UUID filename
   */
  streamFile(
    orgSlug: string,
    projectSlug: string,
    imageId: string,
  ): Promise<Readable>;

  /**
   * Generate a presigned URL for downloading a file
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param imageId UUID filename
   * @param expirySeconds URL expiry time in seconds
   */
  getPresignedDownloadUrl(
    orgSlug: string,
    projectSlug: string,
    imageId: string,
    expirySeconds: number,
  ): Promise<string>;

  /**
   * Generate a presigned URL for uploading a file
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param imageId UUID filename
   * @param expirySeconds URL expiry time in seconds
   * @param contentType MIME type
   */
  getPresignedUploadUrl(
    orgSlug: string,
    projectSlug: string,
    imageId: string,
    expirySeconds: number,
    contentType: string,
  ): Promise<string>;

  /**
   * List files in a project's img folder
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param prefix Optional prefix to filter files
   */
  listFiles(
    orgSlug: string,
    projectSlug: string,
    prefix?: string,
  ): Promise<FileMetadata[]>;

  /**
   * Delete a file from storage
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param imageId UUID filename to delete
   */
  deleteFile(
    orgSlug: string,
    projectSlug: string,
    imageId: string,
  ): Promise<void>;

  /**
   * Check if a file exists
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param imageId UUID filename to check
   */
  fileExists(
    orgSlug: string,
    projectSlug: string,
    imageId: string,
  ): Promise<boolean>;

  /**
   * Get the public CDN URL for a file
   * Returns: https://cdn.banatie.app/{orgSlug}/{projectSlug}/img/{imageId}
   *
   * @param orgSlug Organization slug
   * @param projectSlug Project slug
   * @param imageId UUID filename
   */
  getPublicUrl(
    orgSlug: string,
    projectSlug: string,
    imageId: string,
  ): string;
}
