/**
 * Game System - Manages game instances and real-time multiplayer logic
 */

const logger = require('../utils/logger');

class GameSystem {
  constructor() {
    this.gameInstances = new Map(); // serverId -> game instance
    this.playerConnections = new Map(); // socketId -> player data
  }

  async initializeGameSystems() {
    logger.info('Initializing Game Server systems...');
    
    // Initialize any game systems needed
    this.initializeEconomySystem();
    this.initializeDungeonSystem();
    
    logger.info('Game Server systems initialized successfully');
  }

  initializeEconomySystem() {
    // Economy system initialization for game server
    logger.info('Economy System initialized for Game Server');
  }

  initializeDungeonSystem() {
    // Dungeon system initialization for game server
    logger.info('Dungeon System initialized for Game Server');
  }

  createGameInstance(serverData) {
    const gameId = serverData.id;
    
    const gameInstance = {
      id: gameId,
      name: serverData.name,
      type: serverData.type,
      region: serverData.region,
      maxPlayers: serverData.maxPlayers,
      currentPlayers: 0,
      players: new Map(), // socketId -> player data
      gameState: {
        active: false,
        startTime: null,
        currentDungeon: null,
        enemies: new Map(),
        items: new Map(),
        environment: null
      },
      createdAt: new Date(),
      lastActivity: new Date()
    };

    this.gameInstances.set(gameId, gameInstance);
    logger.info(`Game instance created: ${gameId} - ${serverData.name}`);
    
    return gameInstance;
  }

  joinGameInstance(socket, serverId, playerData) {
    const gameInstance = this.gameInstances.get(serverId);
    
    if (!gameInstance) {
      logger.error(`Game instance not found: ${serverId}`);
      return false;
    }

    if (gameInstance.currentPlayers >= gameInstance.maxPlayers) {
      logger.warn(`Game instance full: ${serverId}`);
      return false;
    }

    // Add player to game instance
    gameInstance.players.set(socket.id, {
      socketId: socket.id,
      userId: playerData.userId,
      username: playerData.username,
      joinedAt: new Date(),
      isReady: false,
      ship: playerData.currentShip || null,
      stats: playerData.stats || { level: 1, health: 100 }
    });

    // Track player connection
    this.playerConnections.set(socket.id, {
      gameId: serverId,
      socket: socket,
      data: playerData
    });

    gameInstance.currentPlayers++;
    gameInstance.lastActivity = new Date();

    // Join socket to game room
    socket.join(`game_${serverId}`);

    logger.info(`Player ${playerData.username} joined game instance ${serverId}`);
    
    return gameInstance;
  }

  leaveGameInstance(socket, serverId) {
    const gameInstance = this.gameInstances.get(serverId);
    
    if (!gameInstance) {
      logger.error(`Game instance not found: ${serverId}`);
      return false;
    }

    const player = gameInstance.players.get(socket.id);
    if (player) {
      gameInstance.players.delete(socket.id);
      gameInstance.currentPlayers--;
      gameInstance.lastActivity = new Date();

      // Leave socket room
      socket.leave(`game_${serverId}`);

      // Remove player connection tracking
      this.playerConnections.delete(socket.id);

      logger.info(`Player ${player.username} left game instance ${serverId}`);

      // Clean up empty game instances
      if (gameInstance.currentPlayers === 0) {
        this.cleanupGameInstance(serverId);
      }

      return true;
    }

    return false;
  }

  cleanupGameInstance(serverId) {
    const gameInstance = this.gameInstances.get(serverId);
    
    if (gameInstance && gameInstance.currentPlayers === 0) {
      this.gameInstances.delete(serverId);
      logger.info(`Cleaned up empty game instance: ${serverId}`);
    }
  }

  getGameInstance(serverId) {
    return this.gameInstances.get(serverId);
  }

  getAllGameInstances() {
    return Array.from(this.gameInstances.values()).map(instance => ({
      id: instance.id,
      name: instance.name,
      type: instance.type,
      region: instance.region,
      currentPlayers: instance.currentPlayers,
      maxPlayers: instance.maxPlayers,
      gameState: instance.gameState.active ? 'active' : 'waiting',
      createdAt: instance.createdAt
    }));
  }

  getPlayerConnection(socketId) {
    return this.playerConnections.get(socketId);
  }

  // Game action handlers
  handlePlayerAction(socket, actionType, actionData) {
    const connection = this.playerConnections.get(socket.id);
    if (!connection) {
      logger.warn(`No connection found for socket: ${socket.id}`);
      return false;
    }

    const gameInstance = this.gameInstances.get(connection.gameId);
    if (!gameInstance) {
      logger.warn(`No game instance found for player: ${socket.id}`);
      return false;
    }

    const player = gameInstance.players.get(socket.id);
    if (!player) {
      logger.warn(`Player not found in game instance: ${socket.id}`);
      return false;
    }

    // Handle different action types
    switch (actionType) {
      case 'move':
        return this.handlePlayerMove(gameInstance, player, actionData);
      case 'attack':
        return this.handlePlayerAttack(gameInstance, player, actionData);
      case 'interact':
        return this.handlePlayerInteract(gameInstance, player, actionData);
      case 'chat':
        return this.handlePlayerChat(gameInstance, player, actionData);
      default:
        logger.warn(`Unknown action type: ${actionType}`);
        return false;
    }
  }

  handlePlayerMove(gameInstance, player, moveData) {
    // Update player position
    player.position = moveData.position;
    gameInstance.lastActivity = new Date();

    // Broadcast movement to other players in the game
    const socket = this.playerConnections.get(player.socketId)?.socket;
    if (socket) {
      socket.to(`game_${gameInstance.id}`).emit('playerMoved', {
        playerId: player.socketId,
        username: player.username,
        position: moveData.position
      });
    }

    return true;
  }

  handlePlayerAttack(gameInstance, player, attackData) {
    // Handle combat logic
    logger.info(`Player ${player.username} attacked in game ${gameInstance.id}`);
    
    // Broadcast attack to other players
    const socket = this.playerConnections.get(player.socketId)?.socket;
    if (socket) {
      socket.to(`game_${gameInstance.id}`).emit('playerAttacked', {
        playerId: player.socketId,
        username: player.username,
        target: attackData.target,
        damage: attackData.damage
      });
    }

    return true;
  }

  handlePlayerInteract(gameInstance, player, interactData) {
    // Handle interaction logic (picking up items, activating objects, etc.)
    logger.info(`Player ${player.username} interacted in game ${gameInstance.id}`);
    
    return true;
  }

  handlePlayerChat(gameInstance, player, chatData) {
    // Handle chat messages
    const message = {
      playerId: player.socketId,
      username: player.username,
      message: chatData.message,
      timestamp: new Date()
    };

    // Broadcast chat to all players in the game
    const socket = this.playerConnections.get(player.socketId)?.socket;
    if (socket) {
      socket.to(`game_${gameInstance.id}`).emit('chatMessage', message);
    }

    return true;
  }
}

// Singleton instance
let gameSystem = null;

async function initializeGameSystems() {
  if (!gameSystem) {
    gameSystem = new GameSystem();
    await gameSystem.initializeGameSystems();
  }
  return gameSystem;
}

function getGameSystem() {
  return gameSystem;
}

module.exports = {
  GameSystem,
  initializeGameSystems,
  getGameSystem
};
