const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const { authenticate } = require('../middleware/auth');
const { modifyLimiter, heavyLimiter, readLimiter } = require('../middleware/rateLimiter');
const { db } = require('../database/db');
const logger = require('../utils/logger');
const { parseM3U } = require('../utils/m3uParser');
const {
  validatePlaylist,
  validateIdParam,
  validateBulkDelete,
  createValidationMiddleware
} = require('../middleware/inputValidation');
const { validatePlaylistName } = require('../utils/inputValidator');

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadDir = path.join(__dirname, '../../data/uploads');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true, mode: 0o755 });
    }
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, 'playlist-' + uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({
  storage,
  limits: { fileSize: 50 * 1024 * 1024 }, // 50MB
  fileFilter: (req, file, cb) => {
    if (file.mimetype === 'audio/x-mpegurl' || file.originalname.endsWith('.m3u') || file.originalname.endsWith('.m3u8')) {
      cb(null, true);
    } else {
      cb(new Error('Only M3U files are allowed'));
    }
  }
});

// Get all playlists for user
router.get('/', authenticate, readLimiter, (req, res) => {
  db.all(
    'SELECT * FROM playlists WHERE user_id = ? ORDER BY created_at DESC',
    [req.user.userId],
    (err, playlists) => {
      if (err) {
        logger.error('Error fetching playlists:', err);
        return res.status(500).json({ error: 'Failed to fetch playlists' });
      }
      res.json(playlists);
    }
  );
});

// Add playlist from URL
router.post('/url', authenticate, modifyLimiter, validatePlaylist, async (req, res) => {
  const { name, url, username, password, category, type } = req.body;

  let playlistUrl = url;
  if (username && password) {
    playlistUrl = url.replace('username=', `username=${username}`).replace('password=', `password=${password}`);
  }

  db.run(
    'INSERT INTO playlists (user_id, name, url, type, category) VALUES (?, ?, ?, ?, ?)',
    [req.user.userId, name, playlistUrl, type || 'live', category],
    async function(err) {
      if (err) {
        logger.error('Error adding playlist:', err);
        return res.status(500).json({ error: 'Failed to add playlist' });
      }

      const playlistId = this.lastID;

      try {
        await parseM3U(playlistUrl, playlistId);
        res.status(201).json({ 
          message: 'Playlist added successfully', 
          id: playlistId 
        });
      } catch (error) {
        logger.error('Error parsing M3U:', error);
        res.status(500).json({ error: 'Failed to parse playlist' });
      }
    }
  );
});

// Upload M3U file
router.post('/upload', authenticate, heavyLimiter, upload.single('file'), async (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }

  const { name, category, type } = req.body;
  
  // Validate playlist name if provided
  if (name) {
    const validation = validatePlaylistName(name);
    if (!validation.valid) {
      // Clean up uploaded file
      if (fs.existsSync(req.file.path)) {
        fs.unlinkSync(req.file.path);
      }
      return res.status(400).json({ error: validation.errors.join(', ') });
    }
  }
  
  const filename = req.file.filename;
  const filePath = req.file.path;

  db.run(
    'INSERT INTO playlists (user_id, name, filename, type, category) VALUES (?, ?, ?, ?, ?)',
    [req.user.userId, name || req.file.originalname, filename, type || 'live', category],
    async function(err) {
      if (err) {
        logger.error('Error saving playlist:', err);
        return res.status(500).json({ error: 'Failed to save playlist' });
      }

      const playlistId = this.lastID;

      try {
        await parseM3U(filePath, playlistId, true);
        res.status(201).json({ 
          message: 'Playlist uploaded successfully', 
          id: playlistId,
          filename 
        });
      } catch (error) {
        logger.error('Error parsing uploaded M3U:', error);
        res.status(500).json({ error: 'Failed to parse playlist' });
      }
    }
  );
});

// Delete playlist
router.delete('/:id', authenticate, modifyLimiter, validateIdParam, (req, res) => {
  const playlistId = req.params.id;

  db.get(
    'SELECT * FROM playlists WHERE id = ? AND user_id = ?',
    [playlistId, req.user.userId],
    (err, playlist) => {
      if (err) {
        logger.error('Error fetching playlist:', err);
        return res.status(500).json({ error: 'Failed to delete playlist' });
      }

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

      // Delete file if exists
      if (playlist.filename) {
        const filePath = path.join(__dirname, '../../data/uploads', playlist.filename);
        if (fs.existsSync(filePath)) {
          fs.unlinkSync(filePath);
        }
      }

      db.run('DELETE FROM playlists WHERE id = ?', [playlistId], (err) => {
        if (err) {
          logger.error('Error deleting playlist:', err);
          return res.status(500).json({ error: 'Failed to delete playlist' });
        }
        res.json({ message: 'Playlist deleted successfully' });
      });
    }
  );
});

// Bulk delete playlists
router.post('/bulk-delete', authenticate, modifyLimiter, validateBulkDelete, (req, res) => {
  const { ids } = req.body;

  const placeholders = ids.map(() => '?').join(',');
  const query = `DELETE FROM playlists WHERE id IN (${placeholders}) AND user_id = ?`;

  db.run(query, [...ids, req.user.userId], function(err) {
    if (err) {
      logger.error('Error bulk deleting playlists:', err);
      return res.status(500).json({ error: 'Failed to delete playlists' });
    }
    res.json({ message: 'Playlists deleted successfully', deleted: this.changes });
  });
});

// Rename playlist
const validatePlaylistRename = createValidationMiddleware({
  params: {
    id: (value) => {
      const num = parseInt(value, 10);
      if (isNaN(num) || num < 1) {
        return { valid: false, errors: ['Invalid playlist ID'], sanitized: null };
      }
      return { valid: true, errors: [], sanitized: num };
    }
  },
  body: {
    name: validatePlaylistName
  }
});

router.patch('/:id', authenticate, modifyLimiter, validatePlaylistRename, (req, res) => {
  const { name } = req.body;
  const playlistId = req.params.id;

  db.run(
    'UPDATE playlists SET name = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? AND user_id = ?',
    [name, playlistId, req.user.userId],
    function(err) {
      if (err) {
        logger.error('Error renaming playlist:', err);
        return res.status(500).json({ error: 'Failed to rename playlist' });
      }

      if (this.changes === 0) {
        return res.status(404).json({ error: 'Playlist not found' });
      }

      res.json({ message: 'Playlist renamed successfully' });
    }
  );
});

module.exports = router;
