/**
 * Game Server - Real-time Multiplayer
 * Handles actual game instances, player connections, and real-time gameplay
 */

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

const logger = require('./utils/logger');
const connectDB = require('./config/database');
const { initializeGameSystems } = require('./systems/GameSystem');
const SocketHandlers = require('./socket/socketHandlers');
const ServerRegistrationService = require('./services/ServerRegistrationService');
const ModService = require('./services/ModService');
const modRoutes = require('./routes/mods');
const { errorHandler, notFound } = require('./middleware/errorHandler');

const app = express();
const server = http.createServer(app);
const io = socketIo(server, {
  cors: {
    origin: ["https://galaxystrike.online", "https://api.korvarix.com", "http://localhost:3000"],
    methods: ["GET", "POST"],
    credentials: true
  }
});

// Middleware
app.use(helmet());
app.use(compression());
app.use(cors({
  origin: ["https://galaxystrike.online", "https://api.korvarix.com", "http://localhost:3000"],
  credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));

// Game Server Routes (minimal - mostly for health checks and server management)
app.get('/health', (req, res) => {
  res.status(200).json({ 
    status: 'Game Server OK', 
    service: 'galaxystrikeonline-game',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    activeServers: Object.keys(gameServers).length,
    connectedPlayers: connectedPlayers.size
  });
});

// Get server status
app.get('/api/game/status', (req, res) => {
  res.json({
    activeServers: Object.keys(gameServers).length,
    connectedPlayers: connectedPlayers.size,
    timestamp: new Date().toISOString()
  });
});

// Mod management routes
app.use('/api/mods', modRoutes);

// Error handling
app.use(notFound);
app.use(errorHandler);

// Global game server instances
const gameServers = {};
let serverRegistration; // Global reference to registration service

// Player tracking
const connectedPlayers = new Set(); // Track actual player connections
let socketHandlers;

io.on('connection', (socket) => {
  logger.info(`Game Server: Player connected - ${socket.id}`);
  socketHandlers.handleConnection(socket);
});

// Handle uncaught errors
process.on('uncaughtException', (error) => {
  logger.error('Uncaught Exception:', error);
});

process.on('unhandledRejection', (reason, promise) => {
  logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

// Graceful shutdown handlers
async function gracefulShutdown(signal) {
  logger.info(`[GRACEFUL SHUTDOWN] Received ${signal}, shutting down gracefully...`);
  
  try {
    // Stop accepting new connections
    server.close(async () => {
      logger.info('[GRACEFUL SHUTDOWN] HTTP server closed');
      
      // Unregister from API
      if (serverRegistration) {
        await serverRegistration.stopHeartbeat();
        const unregistered = await serverRegistration.unregisterWithAPI();
        if (unregistered) {
          logger.info('[GRACEFUL SHUTDOWN] Server unregistered from API successfully');
        } else {
          logger.warn('[GRACEFUL SHUTDOWN] Failed to unregister from API');
        }
      }
      
      // Shutdown mod service
      await ModService.shutdown();
      
      // Close database connections
      const mongoose = require('mongoose');
      await mongoose.connection.close();
      logger.info('[GRACEFUL SHUTDOWN] Database connections closed');
      
      process.exit(0);
    });
    
    // Force shutdown after 30 seconds
    setTimeout(() => {
      logger.error('[GRACEFUL SHUTDOWN] Forced shutdown after timeout');
      process.exit(1);
    }, 30000);
    
  } catch (error) {
    logger.error('[GRACEFUL SHUTDOWN] Error during shutdown:', error);
    process.exit(1);
  }
}

process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));

// Handle Socket.IO adapter errors
io.engine.on('connection_error', (err) => {
  logger.error('Socket.IO connection error:', err);
});

io.of('/').adapter.on('error', (err) => {
  logger.error('Socket.IO adapter error:', err);
});

// Initialize database and game systems
async function startGameServer() {
  try {
    // Connect to database
    await connectDB();
    logger.info('Game Server: Database connected successfully');

    // Initialize mod service
    await ModService.initialize();
    logger.info('Game Server: Mod service initialized');

    // Initialize game systems
    await initializeGameSystems();
    logger.info('Game Server: Game systems initialized');

    // Initialize server registration service
    const gameServerUrl = `https://api.korvarix.com:${process.env.GAME_PORT || 3002}`;
    const apiUrl = process.env.API_SERVER_URL || 'https://api.korvarix.com';
    const serverName = process.env.SERVER_NAME || 'Game Server';
    const serverRegion = process.env.SERVER_REGION || 'us-east';
    const maxPlayers = parseInt(process.env.MAX_PLAYERS) || 10;
    
    serverRegistration = new ServerRegistrationService(gameServerUrl, apiUrl, serverName, serverRegion, maxPlayers);
    
    // Set up player count callback
    serverRegistration.setPlayerCountCallback(() => connectedPlayers.size);
    
    serverRegistration.startHeartbeat();

    // Initialize socket handlers
    socketHandlers = new SocketHandlers(io, gameServers, connectedPlayers);
    
    // Make registration service available to socket handlers
    socketHandlers.serverRegistration = serverRegistration;

    // Start server
    const PORT = process.env.GAME_PORT || 3002; // Game Server on port 3002
    server.listen(PORT, () => {
      logger.info(`Game Server running on port ${PORT}`);
      logger.info('Game Server handles: Real-time Multiplayer, Game Instances, Socket.IO');
      logger.info(`Game Server Name: ${serverName}`);
      logger.info(`Game Server Region: ${serverRegion}`);
      logger.info(`Game Server URL: ${gameServerUrl}`);
      logger.info(`API Server URL: ${apiUrl}`);
    });
  } catch (error) {
    logger.error('Failed to start Game Server:', error);
    process.exit(1);
  }
}

startGameServer();

module.exports = { app, server, io, gameServers };
