import express from 'express';
import cors from 'cors';
import path from 'path';
import { fileURLToPath } from 'url';
import {
  getMangaInfo,
  getMangaChapters,
  getChapterImages,
  getPopularMangas
} from './scraper.js';
import storageService from './storage.js';

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

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(cors());
app.use(express.json());

// Serve static files from storage directory
app.use('/storage', express.static(path.join(__dirname, '../storage')));

// Cache simple (en memoria, se puede mejorar con Redis)
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutos

function getCached(key) {
  const cached = cache.get(key);
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }
  return null;
}

function setCache(key, data) {
  cache.set(key, { data, timestamp: Date.now() });
}

// Routes

/**
 * @route   GET /api/health
 * @desc    Health check endpoint
 */
app.get('/api/health', (req, res) => {
  res.json({ status: 'ok', message: 'MangaReader API is running' });
});

/**
 * @route   GET /api/mangas/popular
 * @desc    Obtener lista de mangas populares
 * @query   ?force=true - Ignorar cache
 */
app.get('/api/mangas/popular', async (req, res) => {
  try {
    const { force } = req.query;

    if (!force) {
      const cached = getCached('popular');
      if (cached) {
        return res.json(cached);
      }
    }

    const mangas = await getPopularMangas();
    setCache('popular', mangas);

    res.json(mangas);
  } catch (error) {
    console.error('Error getting popular mangas:', error);
    res.status(500).json({
      error: 'Error obteniendo mangas populares',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/manga/:slug
 * @desc    Obtener información de un manga específico
 * @param   slug - Slug del manga (ej: one-piece_1695365223767)
 */
app.get('/api/manga/:slug', async (req, res) => {
  try {
    const { slug } = req.params;
    const cacheKey = `manga_${slug}`;

    const cached = getCached(cacheKey);
    if (cached) {
      return res.json(cached);
    }

    const manga = await getMangaInfo(slug);
    setCache(cacheKey, manga);

    res.json(manga);
  } catch (error) {
    console.error('Error getting manga info:', error);
    res.status(500).json({
      error: 'Error obteniendo información del manga',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/manga/:slug/chapters
 * @desc    Obtener lista de capítulos de un manga
 * @param   slug - Slug del manga
 */
app.get('/api/manga/:slug/chapters', async (req, res) => {
  try {
    const { slug } = req.params;
    const cacheKey = `chapters_${slug}`;

    const cached = getCached(cacheKey);
    if (cached) {
      return res.json(cached);
    }

    const chapters = await getMangaChapters(slug);
    setCache(cacheKey, chapters);

    res.json(chapters);
  } catch (error) {
    console.error('Error getting manga chapters:', error);
    res.status(500).json({
      error: 'Error obteniendo capítulos del manga',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/chapter/:slug/images
 * @desc    Obtener imágenes de un capítulo
 * @param   slug - Slug del capítulo (ej: one-piece_1695365223767-1172)
 * @query   ?force=true - Ignorar cache
 */
app.get('/api/chapter/:slug/images', async (req, res) => {
  try {
    const { slug } = req.params;
    const { force } = req.query;
    const cacheKey = `images_${slug}`;

    if (!force) {
      const cached = getCached(cacheKey);
      if (cached) {
        return res.json(cached);
      }
    }

    const images = await getChapterImages(slug);
    setCache(cacheKey, images);

    res.json(images);
  } catch (error) {
    console.error('Error getting chapter images:', error);
    res.status(500).json({
      error: 'Error obteniendo imágenes del capítulo',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/manga/:slug/full
 * @desc    Obtener info completa del manga con capítulos
 * @param   slug - Slug del manga
 */
app.get('/api/manga/:slug/full', async (req, res) => {
  try {
    const { slug } = req.params;
    const cacheKey = `full_${slug}`;

    const cached = getCached(cacheKey);
    if (cached) {
      return res.json(cached);
    }

    // Obtener info y capítulos en paralelo
    const [manga, chapters] = await Promise.all([
      getMangaInfo(slug),
      getMangaChapters(slug)
    ]);

    const fullData = {
      ...manga,
      chapters: chapters
    };

    setCache(cacheKey, fullData);

    res.json(fullData);
  } catch (error) {
    console.error('Error getting full manga data:', error);
    res.status(500).json({
      error: 'Error obteniendo datos completos del manga',
      message: error.message
    });
  }
});

// ==================== STORAGE ENDPOINTS ====================

/**
 * @route   POST /api/download
 * @desc    Request to download a chapter
 * @body    { mangaSlug, chapterNumber, imageUrls }
 */
app.post('/api/download', async (req, res) => {
  try {
    const { mangaSlug, chapterNumber, imageUrls } = req.body;

    if (!mangaSlug || !chapterNumber || !imageUrls) {
      return res.status(400).json({
        error: 'Missing required fields',
        required: ['mangaSlug', 'chapterNumber', 'imageUrls']
      });
    }

    if (!Array.isArray(imageUrls)) {
      return res.status(400).json({
        error: 'imageUrls must be an array'
      });
    }

    console.log(`\n📥 Download request received:`);
    console.log(`   Manga: ${mangaSlug}`);
    console.log(`   Chapter: ${chapterNumber}`);
    console.log(`   Images: ${imageUrls.length}`);

    const result = await storageService.downloadChapter(
      mangaSlug,
      chapterNumber,
      imageUrls
    );

    res.json(result);
  } catch (error) {
    console.error('Error downloading chapter:', error);
    res.status(500).json({
      error: 'Error descargando capítulo',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/storage/chapters/:mangaSlug
 * @desc    List downloaded chapters for a manga
 * @param   mangaSlug - Slug of the manga
 */
app.get('/api/storage/chapters/:mangaSlug', (req, res) => {
  try {
    const { mangaSlug } = req.params;
    const chapters = storageService.listDownloadedChapters(mangaSlug);

    res.json({
      mangaSlug: mangaSlug,
      totalChapters: chapters.length,
      chapters: chapters
    });
  } catch (error) {
    console.error('Error listing downloaded chapters:', error);
    res.status(500).json({
      error: 'Error listando capítulos descargados',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/storage/chapter/:mangaSlug/:chapterNumber
 * @desc    Check if a chapter is downloaded and return manifest
 * @param   mangaSlug - Slug of the manga
 * @param   chapterNumber - Chapter number
 */
app.get('/api/storage/chapter/:mangaSlug/:chapterNumber', (req, res) => {
  try {
    const { mangaSlug, chapterNumber } = req.params;

    const manifest = storageService.getChapterManifest(
      mangaSlug,
      parseInt(chapterNumber)
    );

    if (!manifest) {
      return res.status(404).json({
        error: 'Capítulo no encontrado',
        message: `Chapter ${chapterNumber} of ${mangaSlug} is not downloaded`
      });
    }

    res.json(manifest);
  } catch (error) {
    console.error('Error getting chapter manifest:', error);
    res.status(500).json({
      error: 'Error obteniendo manifest del capítulo',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/storage/image/:mangaSlug/:chapterNumber/:pageIndex
 * @desc    Serve an image from a downloaded chapter
 * @param   mangaSlug - Slug of the manga
 * @param   chapterNumber - Chapter number
 * @param   pageIndex - Page index (1-based)
 */
app.get('/api/storage/image/:mangaSlug/:chapterNumber/:pageIndex', (req, res) => {
  try {
    const { mangaSlug, chapterNumber, pageIndex } = req.params;

    const imagePath = storageService.getImagePath(
      mangaSlug,
      parseInt(chapterNumber),
      parseInt(pageIndex)
    );

    if (!imagePath) {
      return res.status(404).json({
        error: 'Imagen no encontrada',
        message: `Page ${pageIndex} of chapter ${chapterNumber} not found`
      });
    }

    res.sendFile(imagePath);
  } catch (error) {
    console.error('Error serving image:', error);
    res.status(500).json({
      error: 'Error sirviendo imagen',
      message: error.message
    });
  }
});

/**
 * @route   DELETE /api/storage/chapter/:mangaSlug/:chapterNumber
 * @desc    Delete a downloaded chapter
 * @param   mangaSlug - Slug of the manga
 * @param   chapterNumber - Chapter number
 */
app.delete('/api/storage/chapter/:mangaSlug/:chapterNumber', (req, res) => {
  try {
    const { mangaSlug, chapterNumber } = req.params;

    const result = storageService.deleteChapter(
      mangaSlug,
      parseInt(chapterNumber)
    );

    if (!result.success) {
      return res.status(404).json({
        error: 'Capítulo no encontrado',
        message: result.error
      });
    }

    res.json({
      success: true,
      message: `Chapter ${chapterNumber} of ${mangaSlug} deleted successfully`
    });
  } catch (error) {
    console.error('Error deleting chapter:', error);
    res.status(500).json({
      error: 'Error eliminando capítulo',
      message: error.message
    });
  }
});

/**
 * @route   GET /api/storage/stats
 * @desc    Get storage statistics
 */
app.get('/api/storage/stats', (req, res) => {
  try {
    const stats = storageService.getStorageStats();

    res.json({
      totalMangas: stats.totalMangas,
      totalChapters: stats.totalChapters,
      totalSize: stats.totalSize,
      totalSizeMB: (stats.totalSize / 1024 / 1024).toFixed(2),
      totalSizeFormatted: storageService.formatFileSize(stats.totalSize),
      mangaDetails: stats.mangaDetails
    });
  } catch (error) {
    console.error('Error getting storage stats:', error);
    res.status(500).json({
      error: 'Error obteniendo estadísticas de almacenamiento',
      message: error.message
    });
  }
});

// ==================== END OF STORAGE ENDPOINTS ====================

// Error handler
app.use((err, req, res, next) => {
  console.error('Unhandled error:', err);
  res.status(500).json({
    error: 'Error interno del servidor',
    message: err.message
  });
});

// 404 handler
app.use((req, res) => {
  res.status(404).json({
    error: 'Endpoint no encontrado',
    path: req.path
  });
});

// Start server
app.listen(PORT, () => {
  console.log(`🚀 MangaReader API corriendo en puerto ${PORT}`);
  console.log(`📚 API disponible en: http://localhost:${PORT}/api`);
  console.log(`\nEndpoints disponibles:`);
  console.log(`\n  📖 MANGA ENDPOINTS:`);
  console.log(`  GET  /api/health`);
  console.log(`  GET  /api/mangas/popular`);
  console.log(`  GET  /api/manga/:slug`);
  console.log(`  GET  /api/manga/:slug/chapters`);
  console.log(`  GET  /api/chapter/:slug/images`);
  console.log(`  GET  /api/manga/:slug/full`);
  console.log(`\n  💾 STORAGE ENDPOINTS:`);
  console.log(`  POST /api/download`);
  console.log(`  GET  /api/storage/chapters/:mangaSlug`);
  console.log(`  GET  /api/storage/chapter/:mangaSlug/:chapterNumber`);
  console.log(`  GET  /api/storage/image/:mangaSlug/:chapterNumber/:pageIndex`);
  console.log(`  DEL  /api/storage/chapter/:mangaSlug/:chapterNumber`);
  console.log(`  GET  /api/storage/stats`);
  console.log(`\n  📁 Static files: /storage`);
});
