import fs from 'fs';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';

export interface StorageProvider {
  upload(file: Express.Multer.File, folder: string): Promise<string>;
  delete(fileUrl: string): Promise<void>;
  getUrl(key: string): string;
}

class LocalStorageProvider implements StorageProvider {
  private uploadDir: string;
  private baseUrl: string;

  constructor() {
    this.uploadDir = process.env.UPLOAD_DIR || './uploads';
    this.baseUrl = process.env.API_URL || 'http://localhost:4000';
    if (!fs.existsSync(this.uploadDir)) {
      fs.mkdirSync(this.uploadDir, { recursive: true });
    }
  }

  async upload(file: Express.Multer.File, folder: string): Promise<string> {
    const dir = path.join(this.uploadDir, folder);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    const ext = path.extname(file.originalname);
    const filename = `${uuidv4()}${ext}`;
    const filepath = path.join(dir, filename);
    fs.writeFileSync(filepath, file.buffer);
    return `/uploads/${folder}/${filename}`;
  }

  async delete(fileUrl: string): Promise<void> {
    const filepath = path.join(this.uploadDir, fileUrl.replace('/uploads/', ''));
    if (fs.existsSync(filepath)) {
      fs.unlinkSync(filepath);
    }
  }

  getUrl(key: string): string {
    return `${this.baseUrl}${key}`;
  }
}

// R2 and S3 providers ready for production configuration
class R2StorageProvider implements StorageProvider {
  async upload(_file: Express.Multer.File, _folder: string): Promise<string> {
    throw new Error('R2 storage not configured. Set R2 credentials in environment.');
  }
  async delete(_fileUrl: string): Promise<void> {
    throw new Error('R2 storage not configured.');
  }
  getUrl(key: string): string {
    return `${process.env.R2_PUBLIC_URL}${key}`;
  }
}

class S3StorageProvider implements StorageProvider {
  async upload(_file: Express.Multer.File, _folder: string): Promise<string> {
    throw new Error('S3 storage not configured. Set AWS credentials in environment.');
  }
  async delete(_fileUrl: string): Promise<void> {
    throw new Error('S3 storage not configured.');
  }
  getUrl(key: string): string {
    return `${process.env.AWS_S3_PUBLIC_URL}${key}`;
  }
}

function createStorageProvider(): StorageProvider {
  const provider = process.env.STORAGE_PROVIDER || 'local';
  switch (provider) {
    case 'r2':
      return new R2StorageProvider();
    case 's3':
      return new S3StorageProvider();
    default:
      return new LocalStorageProvider();
  }
}

export const storage = createStorageProvider();
