const express = require('express');
const jwt = require('jsonwebtoken');
const GameServer = require('../models/GameServer');
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' });
  }
};

// Register new game server (for GameServer instances to register themselves)
router.post('/register', async (req, res) => {
  try {
    const { serverId, name, type, region, maxPlayers, currentPlayers, gameServerUrl, owner } = req.body;
    
    logger.info(`[API SERVER] Game server registration request:`, {
      serverId, name, type, region, maxPlayers, currentPlayers, gameServerUrl, owner
    });
    
    // Check if server already exists
    const existingServer = await GameServer.findOne({ serverId });
    if (existingServer) {
      // Update existing server
      existingServer.name = name || existingServer.name;
      existingServer.type = type || existingServer.type;
      existingServer.region = region || existingServer.region;
      existingServer.maxPlayers = maxPlayers || existingServer.maxPlayers;
      existingServer.currentPlayers = currentPlayers !== undefined ? currentPlayers : existingServer.currentPlayers;
      existingServer.gameServerUrl = gameServerUrl || existingServer.gameServerUrl;
      existingServer.status = 'waiting';
      existingServer.lastActivity = new Date();
      
      await existingServer.save();
      logger.info(`[API SERVER] Updated existing server: ${serverId} with ${existingServer.currentPlayers} players`);
      
      return res.json({
        success: true,
        message: 'Server updated successfully',
        server: existingServer
      });
    }
    
    // Create new server
    const newServer = new GameServer({
      serverId,
      name: name || `Game Server ${serverId}`,
      type: type || 'public',
      region: region || 'us-east',
      maxPlayers: maxPlayers || 10,
      currentPlayers: currentPlayers !== undefined ? currentPlayers : 0,
      owner: owner || {
        userId: 'system',
        username: 'System'
      },
      status: 'waiting',
      gameServerUrl,
      createdAt: new Date(),
      lastActivity: new Date()
    });
    
    await newServer.save();
    logger.info(`[API SERVER] Registered new server: ${serverId}`);
    
    res.status(201).json({
      success: true,
      message: 'Server registered successfully',
      server: newServer
    });
    
  } catch (error) {
    logger.error('[API SERVER] Error registering server:', error);
    res.status(500).json({ 
      success: false, 
      error: 'Failed to register server' 
    });
  }
});

// Update server status (for GameServer instances to update their status)
router.post('/update-status/:serverId', async (req, res) => {
  try {
    const { serverId } = req.params;
    const { currentPlayers, status } = req.body;
    
    const server = await GameServer.findOne({ serverId });
    if (!server) {
      return res.status(404).json({ 
        success: false, 
        error: 'Server not found' 
      });
    }
    
    if (currentPlayers !== undefined) {
      server.currentPlayers = currentPlayers;
    }
    
    if (status) {
      server.status = status;
    }
    
    server.lastActivity = new Date();
    await server.save();
    
    logger.info(`[API SERVER] Updated server ${serverId} status:`, {
      currentPlayers: server.currentPlayers,
      status: server.status
    });
    
    res.json({
      success: true,
      message: 'Server status updated successfully'
    });
    
  } catch (error) {
    logger.error('[API SERVER] Error updating server status:', error);
    res.status(500).json({ 
      success: false, 
      error: 'Failed to update server status' 
    });
  }
});

// Unregister game server (for GameServer instances to unregister themselves)
router.delete('/unregister/:serverId', async (req, res) => {
  try {
    const { serverId } = req.params;
    
    logger.info(`[API SERVER] Game server unregistration request:`, { serverId });
    
    // Find and remove server
    const server = await GameServer.findOneAndDelete({ serverId });
    
    if (!server) {
      return res.status(404).json({ 
        success: false, 
        error: 'Server not found' 
      });
    }
    
    logger.info(`[API SERVER] Unregistered server: ${serverId}`);
    
    res.json({
      success: true,
      message: 'Server unregistered successfully'
    });
    
  } catch (error) {
    logger.error('[API SERVER] Error unregistering server:', error);
    res.status(500).json({ 
      success: false, 
      error: 'Failed to unregister server' 
    });
  }
});

// Get server list
router.get('/', authenticateToken, async (req, res) => {
  try {
    const { type, region } = req.query;
    
    // Build filters
    const filters = {};
    if (type) filters.type = type;
    if (region) filters.region = region;
    
    logger.info(`[API SERVER] Fetching servers for user ${req.userId} with filters:`, filters);
    
    // Get available servers from database
    const servers = await GameServer.findAvailableServers(filters);
    
    logger.info(`[API SERVER] Found ${servers.length} servers in database`);
    
    // Format server list for client
    const serverList = servers.map(server => ({
      id: server.serverId,
      name: server.name,
      type: server.type,
      region: server.region,
      currentPlayers: server.currentPlayers,
      maxPlayers: server.maxPlayers,
      status: server.status,
      ownerName: server.owner.username,
      createdAt: server.createdAt,
      lastActivity: server.lastActivity
    }));
    
    logger.info(`[API SERVER] Returning ${serverList.length} servers to client`);
    
    res.json({
      success: true,
      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' });
    }

    // Generate unique server ID
    const serverId = `server_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

    // Get user info from token (you might want to fetch full user data)
    const ownerUsername = req.body.username || 'Unknown'; // This should come from user data

    // Create new server in database
    const newServer = new GameServer({
      serverId,
      name,
      type,
      region,
      maxPlayers,
      owner: {
        userId: req.userId,
        username: ownerUsername
      },
      settings,
      gameServerUrl: process.env.GAME_SERVER_URL || 'https://api.korvarix.com'
    });

    await newServer.save();

    logger.info(`Server created: ${serverId} by user ${req.userId}`);

    res.status(201).json({
      message: 'Server created successfully',
      server: {
        id: newServer.serverId,
        name: newServer.name,
        type: newServer.type,
        region: newServer.region,
        currentPlayers: newServer.currentPlayers,
        maxPlayers: newServer.maxPlayers,
        status: newServer.status,
        ownerName: newServer.owner.username,
        createdAt: newServer.createdAt
      }
    });

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

// Join server
router.post('/:serverId/join', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    
    // Find server in database
    const server = await GameServer.findOne({ serverId });
    
    if (!server) {
      return res.status(404).json({ error: 'Server not found' });
    }
    
    // Check if server can be joined
    if (!server.canJoin()) {
      return res.status(400).json({ error: 'Server is full or offline' });
    }
    
    // Add player to server
    const playerAdded = server.addPlayer();
    if (!playerAdded) {
      return res.status(400).json({ error: 'Server is full' });
    }
    
    await server.save();
    
    logger.info(`User ${req.userId} joined server ${serverId}`);

    res.json({
      message: 'Joined server successfully',
      server: {
        id: server.serverId,
        name: server.name,
        currentPlayers: server.currentPlayers,
        maxPlayers: server.maxPlayers,
        gameServerUrl: server.gameServerUrl
      }
    });

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

// Leave server
router.post('/:serverId/leave', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    
    // Find server in database
    const server = await GameServer.findOne({ serverId });
    
    if (!server) {
      return res.status(404).json({ error: 'Server not found' });
    }
    
    // Remove player from server
    const playerRemoved = server.removePlayer();
    if (playerRemoved) {
      await server.save();
      logger.info(`User ${req.userId} left server ${serverId}`);
    }
    
    // Update player's current server
    const Player = require('../models/Player');
    await Player.findOneAndUpdate(
      { userId: req.userId },
      { currentServer: null }
    );

    res.json({
      message: 'Left server successfully'
    });

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

// Get server details
router.get('/:serverId', authenticateToken, async (req, res) => {
  try {
    const { serverId } = req.params;
    
    const server = await GameServer.findOne({ serverId });
    
    if (!server) {
      return res.status(404).json({ error: 'Server not found' });
    }

    res.json({
      server: {
        id: server.serverId,
        name: server.name,
        type: server.type,
        region: server.region,
        currentPlayers: server.currentPlayers,
        maxPlayers: server.maxPlayers,
        status: server.status,
        ownerName: server.owner.username,
        settings: server.settings,
        createdAt: server.createdAt,
        lastActivity: server.lastActivity
      }
    });

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

// Get user's current server
router.get('/user/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 server = await GameServer.findOne({ serverId: player.currentServer });
    
    if (!server) {
      // Clear invalid server reference
      await Player.findOneAndUpdate(
        { userId: req.userId },
        { currentServer: null }
      );
      return res.json({ currentServer: null });
    }

    res.json({
      currentServer: {
        id: server.serverId,
        name: server.name,
        currentPlayers: server.currentPlayers,
        maxPlayers: server.maxPlayers
      }
    });

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

module.exports = router;
