import sharp from 'sharp';
import { writeFile, mkdir } from 'fs/promises';
import path from 'path';
import crypto from 'crypto';
import { env } from '../config/env.js';

export class MediaService {
  private allowedMimeTypes = ['image/jpeg', 'image/png', 'image/webp'];
  private maxFileSize: number;

  constructor() {
    this.maxFileSize = env.MAX_FILE_SIZE;
  }

  /**
   * Validate file type and size
   */
  async validateFile(file: any): Promise<void> {
    if (!this.allowedMimeTypes.includes(file.mimetype)) {
      throw new Error(`Invalid file type. Allowed types: ${this.allowedMimeTypes.join(', ')}`);
    }

    // Check file size
    const buffer = await file.toBuffer();
    if (buffer.length > this.maxFileSize) {
      throw new Error(`File too large. Maximum size: ${this.maxFileSize / 1024 / 1024}MB`);
    }
  }

  /**
   * Generate safe filename
   */
  generateFilename(originalName: string): string {
    const ext = path.extname(originalName);
    const hash = crypto.randomBytes(8).toString('hex');
    const timestamp = Date.now();
    return `${timestamp}-${hash}${ext}`;
  }

  /**
   * Optimize and save image
   */
  async processAndSaveImage(
    file: any,
    destinationDir: string
  ): Promise<{ filename: string; url: string }> {
    await this.validateFile(file);

    // Ensure destination directory exists
    await mkdir(destinationDir, { recursive: true });

    // Generate filename
    const filename = this.generateFilename(file.filename);
    const filepath = path.join(destinationDir, filename);

    // Get file buffer
    const buffer = await file.toBuffer();

    // Process image with sharp (optimize and resize if needed)
    await sharp(buffer)
      .resize(2000, 2000, {
        fit: 'inside',
        withoutEnlargement: true,
      })
      .jpeg({ quality: 85 })
      .png({ quality: 85 })
      .webp({ quality: 85 })
      .toFile(filepath);

    // Return filename and URL path
    return {
      filename,
      url: `/images/${filename}`,
    };
  }

  /**
   * Save image to git workspace
   */
  async saveToGitWorkspace(
    file: any,
    workspaceDir: string
  ): Promise<{ filename: string; url: string }> {
    const imagesDir = path.join(workspaceDir, 'public', 'images');
    return this.processAndSaveImage(file, imagesDir);
  }
}
