import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

// Configuración
const STORAGE_BASE_DIR = path.join(__dirname, '../storage');
const MANHWA_BASE_URL = 'https://manhwaweb.com';

/**
 * Servicio de almacenamiento para capítulos descargados
 * Gestiona la descarga, almacenamiento y serving de imágenes
 */
class StorageService {
  constructor() {
    this.ensureDirectories();
  }

  /**
   * Crea los directorios necesarios si no existen
   */
  ensureDirectories() {
    const dirs = [
      STORAGE_BASE_DIR,
      path.join(STORAGE_BASE_DIR, 'manga'),
      path.join(STORAGE_BASE_DIR, 'temp')
    ];

    dirs.forEach(dir => {
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
        console.log(`📁 Directorio creado: ${dir}`);
      }
    });
  }

  /**
   * Obtiene la ruta del directorio de un manga
   */
  getMangaDir(mangaSlug) {
    const mangaDir = path.join(STORAGE_BASE_DIR, 'manga', mangaSlug);
    if (!fs.existsSync(mangaDir)) {
      fs.mkdirSync(mangaDir, { recursive: true });
    }
    return mangaDir;
  }

  /**
   * Obtiene la ruta del directorio de un capítulo
   */
  getChapterDir(mangaSlug, chapterNumber) {
    const mangaDir = this.getMangaDir(mangaSlug);
    const chapterDir = path.join(mangaDir, `chapter_${chapterNumber}`);
    if (!fs.existsSync(chapterDir)) {
      fs.mkdirSync(chapterDir, { recursive: true });
    }
    return chapterDir;
  }

  /**
   * Descarga una imagen desde una URL y la guarda
   */
  async downloadImage(url, filepath) {
    try {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }

      const buffer = Buffer.from(await response.arrayBuffer());
      fs.writeFileSync(filepath, buffer);

      return {
        success: true,
        size: buffer.length,
        path: filepath
      };
    } catch (error) {
      console.error(`Error descargando ${url}:`, error.message);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * Descarga todas las imágenes de un capítulo
   */
  async downloadChapter(mangaSlug, chapterNumber, imageUrls) {
    const chapterDir = this.getChapterDir(mangaSlug, chapterNumber);
    const manifestPath = path.join(chapterDir, 'manifest.json');

    // Verificar si ya está descargado
    if (fs.existsSync(manifestPath)) {
      const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
      return {
        success: true,
        alreadyDownloaded: true,
        manifest: manifest
      };
    }

    console.log(`📥 Descargando capítulo ${chapterNumber} de ${mangaSlug}...`);
    console.log(`   Directorio: ${chapterDir}`);

    const downloaded = [];
    const failed = [];

    // Descargar cada imagen
    for (let i = 0; i < imageUrls.length; i++) {
      const url = imageUrls[i];
      const filename = `page_${String(i + 1).padStart(3, '0')}.jpg`;
      const filepath = path.join(chapterDir, filename);

      process.stdout.write(`\r  ⏳ ${i + 1}/${imageUrls.length} (${Math.round((i / imageUrls.length) * 100)}%)`);

      const result = await this.downloadImage(url, filepath);

      if (result.success) {
        downloaded.push({
          page: i + 1,
          filename: filename,
          url: url,
          size: result.size,
          sizeKB: (result.size / 1024).toFixed(2)
        });
        process.stdout.write(`\r  ✓ ${i + 1}/${imageUrls.length} (${((result.size / 1024)).toFixed(2)} KB)   `);
      } else {
        failed.push({
          page: i + 1,
          url: url,
          error: result.error
        });
        process.stdout.write(`\r  ✗ ${i + 1}/${imageUrls.length} (ERROR)   `);
      }
    }

    console.log(); // Nueva línea

    // Crear manifest
    const manifest = {
      mangaSlug: mangaSlug,
      chapterNumber: chapterNumber,
      totalPages: imageUrls.length,
      downloadedPages: downloaded.length,
      failedPages: failed.length,
      downloadDate: new Date().toISOString(),
      totalSize: downloaded.reduce((sum, img) => sum + img.size, 0),
      images: downloaded.map(img => ({
        page: img.page,
        filename: img.filename,
        url: img.url,
        size: img.size
      }))
    };

    fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));

    return {
      success: true,
      alreadyDownloaded: false,
      manifest: manifest,
      downloaded: downloaded.length,
      failed: failed.length
    };
  }

  /**
   * Verifica si un capítulo está descargado
   */
  isChapterDownloaded(mangaSlug, chapterNumber) {
    const chapterDir = this.getChapterDir(mangaSlug, chapterNumber);
    const manifestPath = path.join(chapterDir, 'manifest.json');
    return fs.existsSync(manifestPath);
  }

  /**
   * Obtiene el manifest de un capítulo descargado
   */
  getChapterManifest(mangaSlug, chapterNumber) {
    const chapterDir = this.getChapterDir(mangaSlug, chapterNumber);
    const manifestPath = path.join(chapterDir, 'manifest.json');

    if (!fs.existsSync(manifestPath)) {
      return null;
    }

    return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
  }

  /**
   * Obtiene la ruta de una imagen específica
   */
  getImagePath(mangaSlug, chapterNumber, pageIndex) {
    const chapterDir = this.getChapterDir(mangaSlug, chapterNumber);
    const filename = `page_${String(pageIndex).padStart(3, '0')}.jpg`;
    const imagePath = path.join(chapterDir, filename);

    if (fs.existsSync(imagePath)) {
      return imagePath;
    }

    return null;
  }

  /**
   * Lista todos los capítulos descargados de un manga
   */
  listDownloadedChapters(mangaSlug) {
    const mangaDir = this.getMangaDir(mangaSlug);

    if (!fs.existsSync(mangaDir)) {
      return [];
    }

    const chapters = [];
    const items = fs.readdirSync(mangaDir);

    items.forEach(item => {
      const match = item.match(/^chapter_(\d+)$/);
      if (match) {
        const chapterNumber = parseInt(match[1]);
        const manifest = this.getChapterManifest(mangaSlug, chapterNumber);

        if (manifest) {
          chapters.push({
            chapterNumber: chapterNumber,
            downloadDate: manifest.downloadDate,
            totalPages: manifest.totalPages,
            downloadedPages: manifest.downloadedPages,
            totalSize: manifest.totalSize,
            totalSizeMB: (manifest.totalSize / 1024 / 1024).toFixed(2)
          });
        }
      }
    });

    return chapters.sort((a, b) => a.chapterNumber - b.chapterNumber);
  }

  /**
   * Elimina un capítulo descargado
   */
  deleteChapter(mangaSlug, chapterNumber) {
    const chapterDir = this.getChapterDir(mangaSlug, chapterNumber);

    if (fs.existsSync(chapterDir)) {
      fs.rmSync(chapterDir, { recursive: true, force: true });
      return { success: true };
    }

    return { success: false, error: 'Chapter not found' };
  }

  /**
   * Obtiene estadísticas de almacenamiento
   */
  getStorageStats() {
    const stats = {
      totalMangas: 0,
      totalChapters: 0,
      totalSize: 0,
      mangaDetails: []
    };

    const mangaDir = path.join(STORAGE_BASE_DIR, 'manga');

    if (!fs.existsSync(mangaDir)) {
      return stats;
    }

    const mangas = fs.readdirSync(mangaDir);

    mangas.forEach(mangaSlug => {
      const chapters = this.listDownloadedChapters(mangaSlug);
      const totalSize = chapters.reduce((sum, ch) => sum + ch.totalSize, 0);

      stats.totalMangas++;
      stats.totalChapters += chapters.length;
      stats.totalSize += totalSize;

      stats.mangaDetails.push({
        mangaSlug: mangaSlug,
        chapters: chapters.length,
        totalSize: totalSize,
        totalSizeMB: (totalSize / 1024 / 1024).toFixed(2)
      });
    });

    return stats;
  }

  /**
   * Formatea tamaño de archivo
   */
  formatFileSize(bytes) {
    if (bytes === 0) return '0 Bytes';

    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
  }
}

// Exportar instancia singleton
export default new StorageService();
