require('dotenv').config();
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
const path = require('path');

// Serve static files
app.use(express.static(path.join(__dirname, '../public')));

// Clean URLs for About and Contact pages
app.get('/about', (req, res) => {
    res.sendFile(path.join(__dirname, '../public/about.html'));
});

app.get('/contact', (req, res) => {
    res.sendFile(path.join(__dirname, '../public/contact.html'));
});

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Import Admin Panel and Analytics
const adminServer = require('../admin/server/index.js');
const analyticsCollector = require('../admin/server/analytics-collector-sqlite');
const gamesDB = require('../admin/server/games-db');
const { checkMaintenanceMode } = require('../admin/server/middleware');

// Mount Admin Panel
adminServer(app);

// Apply maintenance mode check (after admin is mounted, before other routes)
app.use(checkMaintenanceMode);

// Public API to get enabled// API Routes
app.get('/api/games', (req, res) => {
    try {
        const games = gamesDB.getEnabledGames();
        res.json(gamesDB.formatGames(games));
    } catch (error) {
        console.error('Error fetching games:', error);
        res.status(500).json({ error: 'Failed to fetch games' });
    }
});

app.get('/api/testimonials', (req, res) => {
    try {
        const testimonialsDB = require('../admin/server/testimonials-db');
        const testimonials = testimonialsDB.getAllTestimonials();
        res.json(testimonials);
    } catch (error) {
        console.error('Error fetching testimonials:', error);
        res.status(500).json({ error: 'Failed to fetch testimonials' });
    }
});

// Public stats endpoint
app.get('/api/public-stats', async (req, res) => {
    try {
        const stats = await analyticsCollector.getPublicStats();
        res.json(stats);
    } catch (error) {
        console.error('Error fetching public stats:', error);
        res.status(500).json({ error: 'Failed to fetch stats' });
    }
});

// Public maintenance status endpoint
app.get('/api/maintenance-status', (req, res) => {
    try {
        const settingsDB = require('../admin/server/settings-db');
        const maintenanceMode = settingsDB.get('maintenance_mode') === 'true';
        const maintenanceEta = settingsDB.get('maintenance_eta') || '';
        res.json({ maintenanceMode, eta: maintenanceEta });
    } catch (error) {
        console.error('Error fetching maintenance status:', error);
        res.status(500).json({ maintenanceMode: false, eta: '' });
    }
});

// User game stats endpoint
app.get('/api/sessions/game-stats/:gameId', async (req, res) => {
    try {
        const { gameId } = req.params;
        // Generate same user ID as tracking system
        const ip = req.ip || req.connection.remoteAddress;
        const userAgent = req.headers['user-agent'];
        const userId = analyticsCollector.generateUserId(ip, userAgent);

        const stats = await analyticsCollector.getUserGameStats(userId, gameId);
        res.json(stats);
    } catch (error) {
        console.error('Error fetching user game stats:', error);
        res.status(500).json({ error: 'Failed to fetch stats' });
    }
});

// Public tracking endpoint
app.post('/api/track', async (req, res) => {
    try {
        const { eventType, userId, sessionId, gameName, duration, timestamp, url } = req.body;

        // Get user IP for fingerprinting
        const ip = req.ip || req.connection.remoteAddress;
        const userAgent = req.headers['user-agent'];
        const generatedUserId = analyticsCollector.generateUserId(ip, userAgent);

        switch (eventType) {
            case 'page_view':
                await analyticsCollector.trackPageView(generatedUserId, gameName, userAgent);
                break;

            case 'game_start':
                const { matchId } = req.body;
                await analyticsCollector.trackGameStart(generatedUserId, gameName, sessionId, userAgent, matchId);
                break;

            case 'game_end':
                // Extract all potential metric fields from request body
                // The tracking system spreads extraData directly into the event
                const { result, level, difficulty, score, matchId: endMatchId, playerRole, metrics } = req.body;
                
                // Support both formats:
                // 1. Direct format (Snake): {result, level, score}
                // 2. Nested format (Sudoku): {metrics: {result, difficulty, mistakes}}
                let gameMetrics = {};
                
                if (metrics && typeof metrics === 'object') {
                    // Nested format - use the metrics object directly
                    gameMetrics = metrics;
                } else {
                    // Direct format - construct from individual fields
                    if (result) gameMetrics.result = result;
                    if (level !== undefined) gameMetrics.level = level;
                    if (difficulty) gameMetrics.difficulty = difficulty;
                    if (score !== undefined && score !== null) gameMetrics.score = score;
                    if (endMatchId) gameMetrics.matchId = endMatchId;
                    if (playerRole) gameMetrics.playerRole = playerRole;
                }
                
                await analyticsCollector.trackGameEnd(sessionId, duration, gameMetrics);
                break;

            default:
                console.log('Unknown event type:', eventType);
        }

        res.json({ success: true });
    } catch (error) {
        console.error('Tracking error:', error);
        res.status(500).json({ error: 'Tracking failed' });
    }
});

// Middleware to check if game is enabled
app.use(async (req, res, next) => {
    const match = req.path.match(/^\/games\/([^\/]+)/);
    if (match) {
        const gameId = match[1];
        try {
            const game = gamesDB.getGameById(gameId);
            if (game) {
                // Check if game is disabled
                if (!game.enabled) {
                    return res.status(403).sendFile(path.join(__dirname, '../public/error/game-disabled.html'));
                }
                
                // Check if game is in maintenance mode
                // Admins can bypass this check (requires session)
                // Note: We need to ensure session middleware is available here if we want admin bypass
                // Currently session is only in admin router. We might need to move session middleware up.
                // For now, let's just check the flag.
                if (game.maintenance_mode) {
                    // Check for admin bypass if session exists
                    // We need to check if req.session exists and is authenticated
                    // But session middleware is mounted in adminServer, which is a router.
                    // To share session, we should mount session middleware on the main app.
                    
                    // For now, we'll just show maintenance page.
                    // If we want admin bypass, we need to restructure session handling.
                    
                    return res.status(503).render('maintenance', {
                        message: game.maintenance_message || `The game ${game.name} is currently undergoing maintenance.`,
                        eta: game.maintenance_eta || null
                    });
                }
            }
        } catch (error) {
            console.error('[CheckGameEnabled] Error checking game status:', error);
        }
    }
    next();
});

// Enforce trailing slash for game routes to ensure relative paths work
app.use(async (req, res, next) => {
    const games = ['chess', 'bagh-chal', 'ludo', 'letterquest', 'sudoku', 'gomoku', 'neon-snake'];
    
    // Check for game path and redirect if needed
    const gamePath = games.find(game => req.path === `/games/${game}`);
    if (gamePath) {
        return res.redirect(req.path + '/');
    }
    // Redirect old paths to new paths
    const oldGamePath = games.find(game => req.path === `/${game}` || req.path === `/${game}/`);
    if (oldGamePath) {
        return res.redirect(`/games/${oldGamePath}/`);
    }
    
    next();
});

// Import Game Modules
const chessServer = require('../games/chess/server/index.js');
const baghChalServer = require('../games/bagh_chal/server/index.js');
const neonSnakeServer = require('../games/neon_snake/server/index.js');
const ludoServer = require('../games/ludo/server/index.js');
const letterquestServer = require('../games/letterquest/server/index.js');
const sudokuServer = require('../games/sudoku/server/index.js');
const gomokuServer = require('../games/gomoku/server/index.js');

// Import Rooms DB and Event Emitter
const roomsDB = require('../admin/server/rooms-db');
const appEmitter = require('../admin/server/events');

// Initialize Games
// Pass the main IO instance, the app for routing, roomsDB, and appEmitter
console.log('Mounting Chess Server...');
const chessIo = io.of('/chess');
chessServer(chessIo, app, roomsDB, appEmitter);

console.log('Mounting Bagh Chal Server...');
const baghChalIo = io.of('/bagh-chal');
baghChalServer(baghChalIo, app, roomsDB, appEmitter);

console.log('Mounting Neon Snake Server...');
const neonSnakeIo = io.of('/neon-snake');
neonSnakeServer(neonSnakeIo, app, roomsDB, appEmitter);

console.log('Mounting Ludo Server...');
const ludoIo = io.of('/ludo');
ludoServer(ludoIo, app, roomsDB, appEmitter);

console.log('Mounting LetterQuest Server...');
const letterquestIo = io.of('/letterquest');
letterquestServer(letterquestIo, app, roomsDB, appEmitter);

console.log('Mounting Sudoku Server...');
const sudokuIo = io.of('/sudoku');
sudokuServer(sudokuIo, app, roomsDB, appEmitter);

console.log('Mounting Gomoku Server...');
const gomokuIo = io.of('/gomoku');
gomokuServer(gomokuIo, app, roomsDB, appEmitter);

// 404 Handler - Must be last
app.use((req, res) => {
    res.status(404).sendFile(path.join(__dirname, '../public/error/404.html'));
});

// Start Server
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
   console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   🚀 Game Portal Production Server
   listening on port ${PORT}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Games available at:
   - http://localhost:${PORT}/games/chess/
   - http://localhost:${PORT}/games/bagh-chal/
   - http://localhost:${PORT}/games/neon-snake/
   - http://localhost:${PORT}/games/ludo/
   - http://localhost:${PORT}/games/letterquest/
   - http://localhost:${PORT}/games/sudoku/
   - http://localhost:${PORT}/games/gomoku/
   
   🔐 Admin Panel:
   - http://localhost:${PORT}/admin
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  `);
});
