const logger = require('../utils/logger');
const Player = require('../models/Player');
const Ship = require('../models/Ship');
const Inventory = require('../models/Inventory');
const Economy = require('./EconomySystem');

class GameSystem {
  constructor() {
    this.players = new Map();
    this.servers = new Map();
    this.economy = new Economy();
  }

  async initializeGameSystems() {
    logger.info('Initializing server-side game systems...');
    
    // Initialize economy system
    await this.economy.initialize();
    
    logger.info('Game systems initialized successfully');
  }

  // Player management
  async createPlayer(userId, playerData) {
    try {
      const player = new Player({
        userId,
        ...playerData,
        createdAt: new Date(),
        lastLogin: new Date()
      });
      
      await player.save();
      this.players.set(userId, player);
      
      logger.info(`Created new player for user: ${userId}`);
      return player;
    } catch (error) {
      logger.error('Error creating player:', error);
      throw error;
    }
  }

  async loadPlayer(userId) {
    try {
      let player = this.players.get(userId);
      
      if (!player) {
        player = await Player.findOne({ userId }).populate('ships inventory');
        if (player) {
          this.players.set(userId, player);
        }
      }
      
      return player;
    } catch (error) {
      logger.error('Error loading player:', error);
      throw error;
    }
  }

  async savePlayer(userId) {
    try {
      const player = this.players.get(userId);
      if (player) {
        await player.save();
        logger.info(`Saved player data for user: ${userId}`);
      }
    } catch (error) {
      logger.error('Error saving player:', error);
      throw error;
    }
  }

  // Ship management
  async addShipToPlayer(userId, shipData) {
    try {
      const player = await this.loadPlayer(userId);
      if (!player) {
        throw new Error('Player not found');
      }

      const ship = new Ship({
        ...shipData,
        userId,
        acquiredAt: new Date()
      });

      await ship.save();
      player.ships.push(ship._id);
      await player.save();

      logger.info(`Added ship ${ship.name} to player ${userId}`);
      return ship;
    } catch (error) {
      logger.error('Error adding ship to player:', error);
      throw error;
    }
  }

  async equipShip(userId, shipId) {
    try {
      const player = await this.loadPlayer(userId);
      if (!player) {
        throw new Error('Player not found');
      }

      const ship = await Ship.findOne({ _id: shipId, userId });
      if (!ship) {
        throw new Error('Ship not found');
      }

      // Unequip current ship
      if (player.currentShip) {
        await Ship.findByIdAndUpdate(player.currentShip, { isEquipped: false });
      }

      // Equip new ship
      ship.isEquipped = true;
      await ship.save();
      
      player.currentShip = ship._id;
      await player.save();

      logger.info(`Equipped ship ${ship.name} for player ${userId}`);
      return ship;
    } catch (error) {
      logger.error('Error equipping ship:', error);
      throw error;
    }
  }

  // Server management
  async createServer(serverData) {
    try {
      const serverId = `server_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      
      const server = {
        id: serverId,
        ...serverData,
        createdAt: new Date(),
        players: [],
        status: 'active'
      };

      this.servers.set(serverId, server);
      logger.info(`Created new server: ${serverId}`);
      
      return server;
    } catch (error) {
      logger.error('Error creating server:', error);
      throw error;
    }
  }

  async joinServer(serverId, userId) {
    try {
      const server = this.servers.get(serverId);
      if (!server) {
        throw new Error('Server not found');
      }

      if (server.players.length >= server.maxPlayers) {
        throw new Error('Server is full');
      }

      if (!server.players.includes(userId)) {
        server.players.push(userId);
      }

      logger.info(`Player ${userId} joined server ${serverId}`);
      return server;
    } catch (error) {
      logger.error('Error joining server:', error);
      throw error;
    }
  }

  async leaveServer(serverId, userId) {
    try {
      const server = this.servers.get(serverId);
      if (!server) {
        throw new Error('Server not found');
      }

      server.players = server.players.filter(id => id !== userId);
      
      if (server.players.length === 0) {
        this.servers.delete(serverId);
        logger.info(`Server ${serverId} deleted (no players)`);
      }

      logger.info(`Player ${userId} left server ${serverId}`);
      return server;
    } catch (error) {
      logger.error('Error leaving server:', error);
      throw error;
    }
  }

  getServerList() {
    return Array.from(this.servers.values()).map(server => ({
      id: server.id,
      name: server.name,
      type: server.type,
      maxPlayers: server.maxPlayers,
      currentPlayers: server.players.length,
      status: server.status,
      region: server.region,
      createdAt: server.createdAt
    }));
  }

  // Game actions
  async processGameAction(userId, actionData) {
    try {
      const player = await this.loadPlayer(userId);
      if (!player) {
        throw new Error('Player not found');
      }

      switch (actionData.type) {
        case 'dungeon_enter':
          return await this.handleDungeonEnter(player, actionData);
        case 'ship_upgrade':
          return await this.handleShipUpgrade(player, actionData);
        case 'item_purchase':
          return await this.handleItemPurchase(player, actionData);
        case 'daily_reward':
          return await this.handleDailyReward(player, actionData);
        default:
          throw new Error('Unknown action type');
      }
    } catch (error) {
      logger.error('Error processing game action:', error);
      throw error;
    }
  }

  async handleDungeonEnter(player, data) {
    // Dungeon logic will be implemented here
    logger.info(`Player ${player.userId} entering dungeon`);
    return { success: true, message: 'Dungeon entered' };
  }

  async handleShipUpgrade(player, data) {
    // Ship upgrade logic will be implemented here
    logger.info(`Player ${player.userId} upgrading ship`);
    return { success: true, message: 'Ship upgraded' };
  }

  async handleItemPurchase(player, data) {
    // Item purchase logic will be implemented here
    logger.info(`Player ${player.userId} purchasing item`);
    return { success: true, message: 'Item purchased' };
  }

  async handleDailyReward(player, data) {
    // Daily reward logic will be implemented here
    logger.info(`Player ${player.userId} claiming daily reward`);
    return { success: true, message: 'Daily reward claimed' };
  }
}

// Singleton instance
let gameSystem = null;

async function initializeGameSystems() {
  if (!gameSystem) {
    gameSystem = new GameSystem();
    try {
      await gameSystem.initializeGameSystems();
    } catch (error) {
      logger.error('Failed to initialize game systems:', error);
      throw error;
    }
  }
  return gameSystem;
}

function getGameSystem() {
  if (!gameSystem) {
    logger.warn('Game system not initialized. Call initializeGameSystems() first.');
    return null;
  }
  return gameSystem;
}

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