/**
 * Game Server - Based on Client LocalServer Infrastructure
 * Handles real-time multiplayer game instances and gameplay
 */

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const cors = require('cors');
const dotenv = require('dotenv');
require('dotenv').config();

const logger = require('./utils/logger');
const connectDB = require('./config/database');

const app = express();
const server = http.createServer(app);
const io = socketIo(server, {
  cors: {
    origin: ["http://localhost:3000", "http://127.0.0.1:3000", "file://"],
    methods: ["GET", "POST"],
    credentials: true
  }
});

// Game state
const gameInstances = new Map();
const connectedClients = new Map();

// Middleware
app.use(cors({
  origin: ["http://localhost:3000", "http://127.0.0.1:3000", "file://"],
  credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));

// Health check endpoint
app.get('/health', (req, res) => {
  res.status(200).json({ 
    status: 'OK', 
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    mode: 'game-server',
    activeInstances: gameInstances.size,
    connectedClients: connectedClients.size
  });
});

// API version endpoint
app.get('/api/ssc/version', (req, res) => {
  res.status(200).json({ 
    version: '1.0.0',
    service: 'galaxystrikeonline-game-server',
    timestamp: new Date().toISOString(),
    mode: 'multiplayer'
  });
});

// Game data endpoints (similar to LocalServer)
app.post('/api/game/player/:id/save', (req, res) => {
  const playerId = req.params.id;
  const playerData = req.body;
  
  // Store player data in game instance
  if (connectedClients.has(playerId)) {
    connectedClients.get(playerId).playerData = playerData;
    
    // Broadcast to other players in same instance
    const instanceId = connectedClients.get(playerId).instanceId;
    if (gameInstances.has(instanceId)) {
      io.to(instanceId).emit('playerDataUpdated', {
        playerId,
        timestamp: Date.now()
      });
    }
  }
  
  res.status(200).json({
    success: true,
    message: 'Player data saved to game server'
  });
});

app.get('/api/game/player/:id', (req, res) => {
  const playerId = req.params.id;
  
  if (connectedClients.has(playerId)) {
    const playerData = connectedClients.get(playerId).playerData;
    res.status(200).json({
      success: true,
      player: playerData
    });
  } else {
    res.status(404).json({
      success: false,
      error: 'Player not connected to game server'
    });
  }
});

// Game system routes
app.use('/api/crafting', require('./routes/crafting'));
app.use('/api/quests', require('./routes/quests'));
app.use('/api/skills', require('./routes/skills'));
app.use('/api/ships', require('./routes/ships'));
app.use('/api/idle', require('./routes/idle'));
app.use('/api/dungeons', require('./routes/dungeons'));
app.use('/api/base', require('./routes/base'));

// Socket.IO handlers (based on LocalServer)
io.on('connection', (socket) => {
  console.log('[GAME SERVER] Client connected:', socket.id);
  connectedClients.set(socket.id, {
    connectedAt: Date.now(),
    playerData: null,
    instanceId: null
  });
  
  // Update player count on API server when new player connects
  updatePlayerCountOnAPI();
  
  // Authentication (similar to LocalServer)
  socket.on('authenticate', (data) => {
    console.log('[GAME SERVER] Authenticating client:', socket.id, data);
    
    // In production, validate with API server
    socket.emit('authenticated', {
      success: true,
      user: {
        id: data.userId || socket.id,
        username: data.username || 'Game Player',
        token: 'game-token-' + Date.now()
      }
    });
  });
  
  // Game data events (similar to LocalServer)
  socket.on('saveGameData', (data) => {
    console.log('[GAME SERVER] Saving game data for:', socket.id);
    
    if (connectedClients.has(socket.id)) {
      connectedClients.get(socket.id).playerData = data;
    }
    
    socket.emit('gameDataSaved', {
      success: true,
      timestamp: Date.now()
    });
  });
  
  socket.on('loadGameData', (data) => {
    console.log('[GAME SERVER] Loading game data for:', socket.id);
    
    const playerData = connectedClients.get(socket.id)?.playerData || {};
    
    socket.emit('gameDataLoaded', {
      success: true,
      data: playerData
    });
  });
  
  // Game-specific events
  socket.on('joinGameInstance', (data) => {
    const { instanceId } = data;
    
    if (!gameInstances.has(instanceId)) {
      gameInstances.set(instanceId, {
        id: instanceId,
        players: new Set(),
        createdAt: Date.now()
      });
    }
    
    const instance = gameInstances.get(instanceId);
    instance.players.add(socket.id);
    
    connectedClients.get(socket.id).instanceId = instanceId;
    socket.join(instanceId);
    
    socket.emit('joinedGameInstance', {
      instanceId,
      playerCount: instance.players.size
    });
    
    // Notify other players
    socket.to(instanceId).emit('playerJoinedInstance', {
      playerId: socket.id,
      playerCount: instance.players.size
    });
  });
  
  socket.on('leaveGameInstance', (data) => {
    const clientData = connectedClients.get(socket.id);
    if (clientData && clientData.instanceId) {
      const instance = gameInstances.get(clientData.instanceId);
      if (instance) {
        instance.players.delete(socket.id);
        socket.leave(clientData.instanceId);
        
        // Clean up empty instances
        if (instance.players.size === 0) {
          gameInstances.delete(clientData.instanceId);
        }
        
        // Notify other players
        socket.to(clientData.instanceId).emit('playerLeftInstance', {
          playerId: socket.id,
          playerCount: instance.players.size
        });
      }
      
      clientData.instanceId = null;
    }
  });
  
  socket.on('gameAction', (data) => {
    const clientData = connectedClients.get(socket.id);
    if (clientData && clientData.instanceId) {
      // Broadcast game action to other players in same instance
      socket.to(clientData.instanceId).emit('gameAction', {
        playerId: socket.id,
        action: data,
        timestamp: Date.now()
      });
    }
  });
  
  socket.on('disconnect', () => {
    console.log('[GAME SERVER] Client disconnected:', socket.id);
    
    const clientData = connectedClients.get(socket.id);
    if (clientData && clientData.instanceId) {
      const instance = gameInstances.get(clientData.instanceId);
      if (instance) {
        instance.players.delete(socket.id);
        
        // Clean up empty instances
        if (instance.players.size === 0) {
          gameInstances.delete(clientData.instanceId);
        }
        
        // Notify other players
        socket.to(clientData.instanceId).emit('playerLeftInstance', {
          playerId: socket.id,
          playerCount: instance.players.size
        });
      }
    }
    
    connectedClients.delete(socket.id);
    
    // Update player count on API server
    updatePlayerCountOnAPI();
  });
});

// Update player count on API server
async function updatePlayerCountOnAPI() {
  try {
    const apiServerUrl = 'http://localhost:3001';
    const currentPlayers = connectedClients.size;
    
    console.log(`[GAME SERVER] Updating player count: ${currentPlayers} players`);
    
    const response = await fetch(`${apiServerUrl}/api/servers/update-status/devgame-server-3002`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        currentPlayers: currentPlayers,
        status: currentPlayers > 0 ? 'active' : 'waiting'
      })
    });
    
    if (response.ok) {
      const result = await response.json();
      console.log(`[GAME SERVER] Player count updated:`, result);
    } else {
      console.error(`[GAME SERVER] Failed to update player count: ${response.status}`);
    }
  } catch (error) {
    console.error('[GAME SERVER] Error updating player count:', error);
  }
}

// Start server
const PORT = process.env.PORT || 3002;

async function startServer() {
  try {
    // Connect to database
    await connectDB();
    
    server.listen(PORT, async () => {
      console.log(`[GAME SERVER] Game server running on port ${PORT}`);
      console.log(`[GAME SERVER] Socket.IO ready for multiplayer connections`);
      
      // Register with API server
      await registerWithAPIServer();
      
      // Start periodic player count updates
      setInterval(updatePlayerCountOnAPI, 30000); // Update every 30 seconds
    });
  } catch (error) {
    console.error('[GAME SERVER] Failed to start server:', error);
    process.exit(1);
  }
}

// Register this GameServer with the API server
async function registerWithAPIServer() {
  try {
    // Force use of local API server for development
    const apiServerUrl = 'http://localhost:3001';
    const gameServerUrl = 'https://dev.gameserver.galaxystrike.online';
    
    const serverData = {
      serverId: `devgame-server-${PORT}`,
      name: 'Dev Game Server',
      type: 'public', // Must be 'public' or 'private' according to model
      region: 'Europe',
      maxPlayers: 100, // Hardcoded to allow 100 players
      currentPlayers: 0,
      gameServerUrl: gameServerUrl,
      owner: {
        userId: 'developer',
        username: 'Developer'
      }
    };
    
    console.log(`[GAME SERVER] Registering with API server at ${apiServerUrl}`);
    console.log(`[GAME SERVER] Server data:`, serverData);
    
    const response = await fetch(`${apiServerUrl}/api/servers/register`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(serverData)
    });
    
    if (response.ok) {
      const result = await response.json();
      console.log(`[GAME SERVER] Successfully registered with API server:`, result);
    } else {
      const errorText = await response.text();
      console.error(`[GAME SERVER] Failed to register with API server: ${response.status}`);
      console.error(`[GAME SERVER] Error response:`, errorText);
    }
  } catch (error) {
    console.error('[GAME SERVER] Error registering with API server:', error);
  }
}

startServer();

module.exports = { app, server, io, gameInstances, connectedClients };
