const express = require('express');
const { authenticateToken } = require('../middleware/auth');
const db = require('../database');
const { stringify } = require('csv-stringify/sync');
const { parse } = require('csv-parse/sync');

const router = express.Router();

// Get all games with optional filters
router.get('/', (req, res) => {
  try {
    const {
      enabled,
      minPlayers,
      maxPlayers,
      playerCount,
      drawing,
      length,
      familyFriendly,
      pack
    } = req.query;

    let query = 'SELECT * FROM games WHERE 1=1';
    const params = [];

    if (enabled !== undefined) {
      query += ' AND enabled = ?';
      params.push(enabled === 'true' ? 1 : 0);
    }

    if (playerCount) {
      const count = parseInt(playerCount);
      query += ' AND min_players <= ? AND max_players >= ?';
      params.push(count, count);
    }

    if (drawing === 'only') {
      query += ' AND game_type = ?';
      params.push('Drawing');
    } else if (drawing === 'exclude') {
      query += ' AND (game_type != ? OR game_type IS NULL)';
      params.push('Drawing');
    }

    if (length) {
      if (length === 'short') {
        query += ' AND (length_minutes <= 15 OR length_minutes IS NULL)';
      } else if (length === 'medium') {
        query += ' AND length_minutes > 15 AND length_minutes <= 25';
      } else if (length === 'long') {
        query += ' AND length_minutes > 25';
      }
    }

    if (familyFriendly !== undefined) {
      query += ' AND family_friendly = ?';
      params.push(familyFriendly === 'true' ? 1 : 0);
    }

    if (pack) {
      query += ' AND pack_name = ?';
      params.push(pack);
    }

    query += ' ORDER BY pack_name, title';

    const stmt = db.prepare(query);
    const games = stmt.all(...params);

    res.json(games);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get all packs with their favor bias (MUST be before /:id)
router.get('/packs', (req, res) => {
  try {
    const packs = db.prepare('SELECT * FROM packs ORDER BY name').all();
    res.json(packs);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get pack metadata (MUST be before /:id)
router.get('/meta/packs', (req, res) => {
  try {
    const packs = db.prepare(`
      SELECT 
        pack_name as name,
        COUNT(*) as total_count,
        SUM(CASE WHEN enabled = 1 THEN 1 ELSE 0 END) as enabled_count,
        SUM(play_count) as total_plays
      FROM games
      GROUP BY pack_name
      ORDER BY pack_name
    `).all();
    res.json(packs);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Export games as CSV (MUST be before /:id)
router.get('/export/csv', authenticateToken, (req, res) => {
  try {
    const games = db.prepare('SELECT * FROM games ORDER BY pack_name, title').all();
    
    const records = games.map(game => ({
      'Pack Name': game.pack_name,
      'Title': game.title,
      'Min Players': game.min_players,
      'Max Players': game.max_players,
      'Length (minutes)': game.length_minutes || '',
      'Audience': game.has_audience ? 'Yes' : 'No',
      'Family Friendly': game.family_friendly ? 'Yes' : 'No',
      'Game Type': game.game_type || '',
      'Secondary Type': game.secondary_type || ''
    }));

    const csv = stringify(records, { header: true });
    
    res.setHeader('Content-Type', 'text/csv');
    res.setHeader('Content-Disposition', 'attachment; filename="jackbox-games.csv"');
    res.send(csv);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Set favor bias for a pack (MUST be before /:id)
router.patch('/packs/:name/favor', authenticateToken, (req, res) => {
  try {
    const { favor_bias } = req.body;
    
    // Validate favor_bias value
    if (![1, -1, 0].includes(favor_bias)) {
      return res.status(400).json({ error: 'favor_bias must be 1 (favor), -1 (disfavor), or 0 (neutral)' });
    }

    // Update pack favor bias
    const packStmt = db.prepare('UPDATE packs SET favor_bias = ? WHERE name = ?');
    const packResult = packStmt.run(favor_bias, req.params.name);

    if (packResult.changes === 0) {
      // Pack doesn't exist, create it
      const insertStmt = db.prepare('INSERT INTO packs (name, favor_bias) VALUES (?, ?)');
      insertStmt.run(req.params.name, favor_bias);
    }

    res.json({ 
      message: 'Pack favor bias updated successfully',
      favor_bias
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get single game by ID
router.get('/:id', (req, res) => {
  try {
    const game = db.prepare('SELECT * FROM games WHERE id = ?').get(req.params.id);
    
    if (!game) {
      return res.status(404).json({ error: 'Game not found' });
    }

    res.json(game);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Create new game (admin only)
router.post('/', authenticateToken, (req, res) => {
  try {
    const {
      pack_name,
      title,
      min_players,
      max_players,
      length_minutes,
      has_audience,
      family_friendly,
      game_type,
      secondary_type
    } = req.body;

    if (!pack_name || !title || !min_players || !max_players) {
      return res.status(400).json({ error: 'Missing required fields' });
    }

    const stmt = db.prepare(`
      INSERT INTO games (
        pack_name, title, min_players, max_players, length_minutes,
        has_audience, family_friendly, game_type, secondary_type
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    `);

    const result = stmt.run(
      pack_name,
      title,
      min_players,
      max_players,
      length_minutes || null,
      has_audience ? 1 : 0,
      family_friendly ? 1 : 0,
      game_type || null,
      secondary_type || null
    );

    const newGame = db.prepare('SELECT * FROM games WHERE id = ?').get(result.lastInsertRowid);
    res.status(201).json(newGame);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Update game (admin only)
router.put('/:id', authenticateToken, (req, res) => {
  try {
    const {
      pack_name,
      title,
      min_players,
      max_players,
      length_minutes,
      has_audience,
      family_friendly,
      game_type,
      secondary_type,
      enabled
    } = req.body;

    const stmt = db.prepare(`
      UPDATE games SET
        pack_name = COALESCE(?, pack_name),
        title = COALESCE(?, title),
        min_players = COALESCE(?, min_players),
        max_players = COALESCE(?, max_players),
        length_minutes = ?,
        has_audience = COALESCE(?, has_audience),
        family_friendly = COALESCE(?, family_friendly),
        game_type = ?,
        secondary_type = ?,
        enabled = COALESCE(?, enabled)
      WHERE id = ?
    `);

    const result = stmt.run(
      pack_name || null,
      title || null,
      min_players || null,
      max_players || null,
      length_minutes !== undefined ? length_minutes : null,
      has_audience !== undefined ? (has_audience ? 1 : 0) : null,
      family_friendly !== undefined ? (family_friendly ? 1 : 0) : null,
      game_type !== undefined ? game_type : null,
      secondary_type !== undefined ? secondary_type : null,
      enabled !== undefined ? (enabled ? 1 : 0) : null,
      req.params.id
    );

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

    const updatedGame = db.prepare('SELECT * FROM games WHERE id = ?').get(req.params.id);
    res.json(updatedGame);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Delete game (admin only)
router.delete('/:id', authenticateToken, (req, res) => {
  try {
    const stmt = db.prepare('DELETE FROM games WHERE id = ?');
    const result = stmt.run(req.params.id);

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

    res.json({ message: 'Game deleted successfully' });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Toggle game enabled status (admin only)
router.patch('/:id/toggle', authenticateToken, (req, res) => {
  try {
    const game = db.prepare('SELECT enabled FROM games WHERE id = ?').get(req.params.id);
    
    if (!game) {
      return res.status(404).json({ error: 'Game not found' });
    }

    const newStatus = game.enabled === 1 ? 0 : 1;
    db.prepare('UPDATE games SET enabled = ? WHERE id = ?').run(newStatus, req.params.id);

    const updatedGame = db.prepare('SELECT * FROM games WHERE id = ?').get(req.params.id);
    res.json(updatedGame);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Toggle entire pack (admin only)
router.patch('/packs/:name/toggle', authenticateToken, (req, res) => {
  try {
    const { enabled } = req.body;
    
    if (enabled === undefined) {
      return res.status(400).json({ error: 'enabled status required' });
    }

    const stmt = db.prepare('UPDATE games SET enabled = ? WHERE pack_name = ?');
    const result = stmt.run(enabled ? 1 : 0, req.params.name);

    res.json({ 
      message: `Pack ${enabled ? 'enabled' : 'disabled'} successfully`,
      gamesAffected: result.changes
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Import games from CSV (admin only)
router.post('/import/csv', authenticateToken, (req, res) => {
  try {
    const { csvData, mode } = req.body; // mode: 'append' or 'replace'

    if (!csvData) {
      return res.status(400).json({ error: 'CSV data required' });
    }

    const records = parse(csvData, {
      columns: true,
      skip_empty_lines: true,
      trim: true
    });

    if (mode === 'replace') {
      db.prepare('DELETE FROM games').run();
    }

    const insert = db.prepare(`
      INSERT INTO games (
        pack_name, title, min_players, max_players, length_minutes,
        has_audience, family_friendly, game_type, secondary_type, enabled
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
    `);

    const insertMany = db.transaction((games) => {
      for (const game of games) {
        insert.run(
          game['Game Pack'],
          game['Game Title'],
          parseInt(game['Min. Players']) || 1,
          parseInt(game['Max. Players']) || 8,
          parseLengthMinutes(game['Length']),
          parseBoolean(game['Audience']),
          parseBoolean(game['Family Friendly?']),
          game['Game Type'] || null,
          game['Secondary Type'] || null
        );
      }
    });

    insertMany(records);

    res.json({ 
      message: `Successfully imported ${records.length} games`,
      count: records.length,
      mode
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

function parseLengthMinutes(lengthStr) {
  if (!lengthStr || lengthStr === '????' || lengthStr === '?') {
    return null;
  }
  const match = lengthStr.match(/(\d+)/);
  return match ? parseInt(match[1]) : null;
}

function parseBoolean(value) {
  if (!value || value === '?' || value === '????') {
    return 0;
  }
  return value.toLowerCase() === 'yes' ? 1 : 0;
}

// Set favor bias for a game (1 = favor, -1 = disfavor, 0 = neutral)
router.patch('/:id/favor', authenticateToken, (req, res) => {
  try {
    const { favor_bias } = req.body;
    
    // Validate favor_bias value
    if (![1, -1, 0].includes(favor_bias)) {
      return res.status(400).json({ error: 'favor_bias must be 1 (favor), -1 (disfavor), or 0 (neutral)' });
    }

    const stmt = db.prepare('UPDATE games SET favor_bias = ? WHERE id = ?');
    const result = stmt.run(favor_bias, req.params.id);

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

    res.json({ 
      message: 'Favor bias updated successfully',
      favor_bias
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;

