import express from 'express';
import multer from 'multer';
import path from 'path';
import fs from 'fs/promises';
import { v4 as uuidv4 } from 'uuid';
import { authenticateToken, checkUsageLimits } from '../middleware/auth.js';
import { ProcessingBatch } from '../models/ProcessingBatch.js';
import { ProcessingJob } from '../models/ProcessingJob.js';
import { User } from '../models/User.js';
import { batchProcessor } from '../services/batchProcessor.js';
import { imageProcessor } from '../services/imageProcessor.js';
import { fileCleanupService } from '../services/fileCleanup.js';

const router = express.Router();

// Configure multer for file uploads
const storage = multer.diskStorage({
  destination: async (req, file, cb) => {
    const uploadDir = path.join('./uploads', req.user.id.toString());
    await fs.mkdir(uploadDir, { recursive: true });
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    const uniqueName = `${Date.now()}-${Math.round(Math.random() * 1E9)}-${file.originalname}`;
    cb(null, uniqueName);
  }
});

const upload = multer({
  storage,
  limits: {
    fileSize: 50 * 1024 * 1024, // 50MB max file size
    files: 100 // Max 100 files per batch
  },
  fileFilter: (req, file, cb) => {
    const allowedTypes = /jpeg|jpg|png|gif|svg|heic|bmp|tiff/;
    const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
    const mimetype = allowedTypes.test(file.mimetype) || file.mimetype === 'image/heic';

    if (mimetype && extname) {
      return cb(null, true);
    } else {
      cb(new Error(`File "${file.originalname}" is not a supported image format. Supported formats: JPG, PNG, GIF, SVG, HEIC, BMP, TIFF`));
    }
  }
});

// Start batch processing
router.post('/batch', authenticateToken, checkUsageLimits, upload.array('images'), async (req, res) => {
  try {
    const files = req.files;
    const options = JSON.parse(req.body.options || '{}');
    const batchName = req.body.batchName || `Batch ${new Date().toISOString()}`;

    if (!files || files.length === 0) {
      return res.status(400).json({ error: 'No images provided' });
    }

    // Validate and set default options
    const validatedOptions = {
      format: options.format || 'webp',
      quality: Math.min(100, Math.max(10, parseInt(options.quality) || 80)),
      namingTemplate: options.namingTemplate || '{name}-optimized',
      seoKeywords: options.seoKeywords || '',
      preserveMetadata: options.preserveMetadata !== false
    };

    const batchId = uuidv4();
    const totalOriginalSize = files.reduce((sum, file) => sum + file.size, 0);

    // Create batch record
    await ProcessingBatch.create({
      id: batchId,
      userId: req.user.id,
      name: batchName,
      totalFiles: files.length,
      totalOriginalSize,
      optimizationSettings: validatedOptions
    });

    // Start background processing
    batchProcessor.processBatch(batchId, files, validatedOptions, req.user.id)
      .catch(error => {
        console.error('Batch processing error:', error);
      });

    res.json({
      batchId,
      status: 'processing',
      totalFiles: files.length,
      message: 'Batch processing started'
    });

  } catch (error) {
    console.error('Batch creation error:', error);
    res.status(500).json({ error: 'Failed to start batch processing' });
  }
});

// Get batch status
router.get('/batch/:batchId', authenticateToken, async (req, res) => {
  try {
    const { batchId } = req.params;
    
    // Validate UUID format
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
    if (!uuidRegex.test(batchId)) {
      return res.status(400).json({ error: 'Invalid batch ID format' });
    }

    const batchStatus = await batchProcessor.getBatchStatus(batchId);

    if (!batchStatus) {
      return res.status(404).json({ error: 'Batch not found' });
    }

    // Ensure user owns this batch
    if (batchStatus.user_id !== req.user.id) {
      return res.status(403).json({ error: 'Access denied' });
    }

    res.json(batchStatus);
  } catch (error) {
    console.error('Get batch status error:', error);
    res.status(500).json({ error: 'Failed to get batch status' });
  }
});

// Get user's processing history
router.get('/batches', authenticateToken, async (req, res) => {
  try {
    const limit = Math.min(50, parseInt(req.query.limit) || 20);
    const batches = await ProcessingBatch.findByUserId(req.user.id, limit);
    res.json(batches);
  } catch (error) {
    console.error('Get batches error:', error);
    res.status(500).json({ error: 'Failed to fetch processing history' });
  }
});

// Download processed batch
router.get('/download/:batchId', authenticateToken, async (req, res) => {
  try {
    const { batchId } = req.params;
    
    // Validate UUID format
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
    if (!uuidRegex.test(batchId)) {
      return res.status(400).json({ error: 'Invalid batch ID format' });
    }

    const batch = await ProcessingBatch.findById(batchId);

    if (!batch) {
      return res.status(404).json({ error: 'Batch not found' });
    }

    if (batch.user_id !== req.user.id) {
      return res.status(403).json({ error: 'Access denied' });
    }

    if (batch.status !== 'completed') {
      return res.status(400).json({ error: 'Batch not completed yet' });
    }

    const zipPath = path.join('./output', `${batchId}.zip`);
    
    try {
      await fs.access(zipPath);
      res.download(zipPath, `optimized-images-${batchId}.zip`);
    } catch (error) {
      return res.status(404).json({ error: 'Download file not found or expired' });
    }

  } catch (error) {
    console.error('Download error:', error);
    res.status(500).json({ error: 'Download failed' });
  }
});

// Single image processing endpoint
router.post('/single', authenticateToken, checkUsageLimits, upload.single('image'), async (req, res) => {
  try {
    const file = req.file;
    const options = JSON.parse(req.body.options || '{}');

    if (!file) {
      return res.status(400).json({ error: 'No image provided' });
    }

    const validatedOptions = {
      format: options.format || 'webp',
      quality: Math.min(100, Math.max(10, parseInt(options.quality) || 80)),
      preserveMetadata: options.preserveMetadata !== false
    };

    // Process single image using buffer
    const buffer = await fs.readFile(file.path);
    const result = await imageProcessor.processImageBuffer(buffer, validatedOptions);

    // Generate filename
    const originalName = path.parse(file.originalname).name;
    const outputExtension = imageProcessor.getOutputExtension(validatedOptions.format);
    const outputFilename = `${originalName}-optimized.${outputExtension}`;

    // Update user usage
    await User.updateUsage(req.user.id, 1);

    // Clean up uploaded file
    await fs.unlink(file.path);

    res.json({
      originalFilename: file.originalname,
      outputFilename,
      originalSize: result.originalSize,
      optimizedSize: result.optimizedSize,
      compressionRatio: result.compressionRatio,
      buffer: result.buffer.toString('base64')
    });

  } catch (error) {
    console.error('Single image processing error:', error);
    res.status(500).json({ error: 'Image processing failed' });
  }
});

export default router;
// Add cleanup stats endpoint for monitoring
router.get('/cleanup-stats', authenticateToken, async (req, res) => {
  try {
    // Only allow admin users to see cleanup stats (you can modify this logic)
    const stats = await fileCleanupService.getCleanupStats();
    res.json(stats);
  } catch (error) {
    console.error('Cleanup stats error:', error);
    res.status(500).json({ error: 'Failed to get cleanup stats' });
  }
});

// Manual cleanup trigger endpoint (for admin use)
router.post('/cleanup', authenticateToken, async (req, res) => {
  try {
    // Only allow admin users to trigger manual cleanup
    await fileCleanupService.cleanupOldFiles();
    res.json({ message: 'Manual cleanup completed successfully' });
  } catch (error) {
    console.error('Manual cleanup error:', error);
    res.status(500).json({ error: 'Manual cleanup failed' });
  }
});