const express = require('express');
const jwt = require('jsonwebtoken');
const { getGameSystem } = require('../systems/GameSystem');
const logger = require('../utils/logger');

const router = express.Router();

// Middleware to authenticate JWT token
const authenticateToken = (req, res, next) => {
  const token = req.header('Authorization')?.replace('Bearer ', '');
  
  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET || 'fallback_secret');
    req.userId = decoded.userId;
    next();
  } catch (error) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Get server list
router.get('/', authenticateToken, async (req, res) => {
  try {
    const gameSystem = getGameSystem();
    const serverList = gameSystem.getServerList();
    
    res.json({
      servers: serverList,
      totalServers: serverList.length
    });

  } catch (error) {
    logger.error('Error getting server list:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Create new server
router.post('/create', authenticateToken, async (req, res) => {
  try {
    const { name, type = 'public', maxPlayers = 10, region = 'us-east', settings = {} } = req.body;
    
    if (!name) {
      return res.status(400).json({ error: 'Server name required' });
    }

    if (name.length < 3 || name.length > 50) {
      return res.status(400).json({ error: 'Server name must be between 3 and 50 characters' });
    }

    const gameSystem = getGameSystem();
    
    const serverData = {
      name,
      type,
      maxPlayers,
      region,
      settings,
      ownerId: req.userId,
      ownerName: req.username || 'Unknown'
    };

    const server = await gameSystem.createServer(serverData);
    
    // Auto-join the creator to the server
    await gameSystem.joinServer(server.id, req.userId);
    
    logger.info(`Server created: ${server.id} by user ${req.userId}`);
    
    res.status(201).json({
      message: 'Server created successfully',
      server: {
        id: server.id,
        name: server.name,
        type: server.type,
        maxPlayers: server.maxPlayers,
        currentPlayers: server.players.length,
        region: server.region,
        status: server.status,
        ownerId: server.ownerId,
        createdAt: server.createdAt
      }
    });

  } catch (error) {
    logger.error('Error creating server:', error);
    res.status(500).json({ error: error.message });
  }
});

// Join server
router.post('/:serverId/join', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    const { password } = req.body; // For private servers
    
    if (!serverId) {
      return res.status(400).json({ error: 'Server ID required' });
    }

    const gameSystem = getGameSystem();
    const server = await gameSystem.joinServer(serverId, req.userId);
    
    // Update player's current server
    const Player = require('../models/Player');
    await Player.findOneAndUpdate(
      { userId: req.userId },
      { currentServer: serverId }
    );
    
    logger.info(`User ${req.userId} joined server ${serverId}`);
    
    res.json({
      message: 'Joined server successfully',
      server: {
        id: server.id,
        name: server.name,
        type: server.type,
        maxPlayers: server.maxPlayers,
        currentPlayers: server.players.length,
        region: server.region
      }
    });

  } catch (error) {
    logger.error('Error joining server:', error);
    res.status(500).json({ error: error.message });
  }
});

// Leave server
router.post('/:serverId/leave', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    
    if (!serverId) {
      return res.status(400).json({ error: 'Server ID required' });
    }

    const gameSystem = getGameSystem();
    const server = await gameSystem.leaveServer(serverId, req.userId);
    
    // Update player's current server
    const Player = require('../models/Player');
    await Player.findOneAndUpdate(
      { userId: req.userId },
      { currentServer: null }
    );
    
    logger.info(`User ${req.userId} left server ${serverId}`);
    
    res.json({
      message: 'Left server successfully',
      server: server || null
    });

  } catch (error) {
    logger.error('Error leaving server:', error);
    res.status(500).json({ error: error.message });
  }
});

// Get server details
router.get('/:serverId', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    
    if (!serverId) {
      return res.status(400).json({ error: 'Server ID required' });
    }

    const gameSystem = getGameSystem();
    const server = gameSystem.servers.get(serverId);
    
    if (!server) {
      return res.status(404).json({ error: 'Server not found' });
    }

    // Get player details for all players in the server
    const Player = require('../models/Player');
    const players = await Player.find({ 
      userId: { $in: server.players } 
    }).select('userId username info stats');

    res.json({
      server: {
        id: server.id,
        name: server.name,
        type: server.type,
        maxPlayers: server.maxPlayers,
        currentPlayers: server.players.length,
        region: server.region,
        status: server.status,
        ownerId: server.ownerId,
        createdAt: server.createdAt,
        settings: server.settings
      },
      players: players.map(player => ({
        userId: player.userId,
        username: player.username,
        level: player.stats.level,
        title: player.info.title,
        rank: player.info.rank
      }))
    });

  } catch (error) {
    logger.error('Error getting server details:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Get user's current server
router.get('/current', authenticateToken, async (req, res) => {
  try {
    const Player = require('../models/Player');
    const player = await Player.findOne({ userId: req.userId });
    
    if (!player || !player.currentServer) {
      return res.json({ currentServer: null });
    }

    const gameSystem = getGameSystem();
    const server = gameSystem.servers.get(player.currentServer);
    
    if (!server) {
      // Clear the invalid server reference
      player.currentServer = null;
      await player.save();
      return res.json({ currentServer: null });
    }

    res.json({
      currentServer: {
        id: server.id,
        name: server.name,
        type: server.type,
        maxPlayers: server.maxPlayers,
        currentPlayers: server.players.length,
        region: server.region,
        status: server.status
      }
    });

  } catch (error) {
    logger.error('Error getting current server:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Update server settings (owner only)
router.put('/:serverId/settings', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    const { settings } = req.body;
    
    if (!serverId) {
      return res.status(400).json({ error: 'Server ID required' });
    }

    const gameSystem = getGameSystem();
    const server = gameSystem.servers.get(serverId);
    
    if (!server) {
      return res.status(404).json({ error: 'Server not found' });
    }

    // Check if user is the server owner
    if (server.ownerId !== req.userId) {
      return res.status(403).json({ error: 'Only server owner can update settings' });
    }

    // Update server settings
    server.settings = { ...server.settings, ...settings };
    
    logger.info(`Server settings updated: ${serverId} by user ${req.userId}`);
    
    res.json({
      message: 'Server settings updated successfully',
      settings: server.settings
    });

  } catch (error) {
    logger.error('Error updating server settings:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Delete server (owner only)
router.delete('/:serverId', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    
    if (!serverId) {
      return res.status(400).json({ error: 'Server ID required' });
    }

    const gameSystem = getGameSystem();
    const server = gameSystem.servers.get(serverId);
    
    if (!server) {
      return res.status(404).json({ error: 'Server not found' });
    }

    // Check if user is the server owner
    if (server.ownerId !== req.userId) {
      return res.status(403).json({ error: 'Only server owner can delete server' });
    }

    // Remove all players from the server
    for (const playerId of server.players) {
      await gameSystem.leaveServer(serverId, playerId);
      
      // Update player's current server
      const Player = require('../models/Player');
      await Player.findOneAndUpdate(
        { userId: playerId },
        { currentServer: null }
      );
    }
    
    // Delete the server
    gameSystem.servers.delete(serverId);
    
    logger.info(`Server deleted: ${serverId} by user ${req.userId}`);
    
    res.json({
      message: 'Server deleted successfully'
    });

  } catch (error) {
    logger.error('Error deleting server:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

module.exports = router;
