// bc.js - Главный файл сервера Battle Club

const express = require('express');
const http = require('http'); // Используем HTTP, так как SSL будет на Node.js прокси (server.js)
const { Server } = require('socket.io');
const path = require('path');

// Импорт серверных модулей
const auth = require('./server_modules/auth');
const GameManager = require('./server_modules/gameManager');
const db = require('./server_modules/db'); // Импорт для инициализации соединения с БД (хотя пул создается при require)
const GAME_CONFIG = require('./server_modules/config'); // Конфиг игры
// gameData импортируется внутри GameInstance и GameLogic

const app = express();
const server = http.createServer(app);

// Настройка Socket.IO
const io = new Server(server, {
    cors: {
        origin: "https://pavel-chagovsky.com:3200", // Указываем точный origin, включая порт, откуда придет запрос К ПРОКСИ
        // Если доступ будет с нескольких доменов или портов, можно использовать массив:
        // origin: ["https://pavel-chagovsky.com:3200", "https://oleg-okhotnikov.ru:3200"],
        // Или для разработки можно временно использовать "*", но это менее безопасно:
        // origin: "*",
        methods: ["GET", "POST"]
    }
});

// Раздача статических файлов из папки 'public'
app.use(express.static(path.join(__dirname, 'public')));

// Создаем экземпляр GameManager
const gameManager = new GameManager(io);

// Хранилище информации о залогиненных пользователях по socket.id
const loggedInUsers = {}; // { socket.id: { userId: ..., username: ... } }

// Обработка подключений Socket.IO
io.on('connection', (socket) => {
    console.log(`[BC App HTTP] Socket.IO User connected: ${socket.id}`);

    socket.userData = null;

    socket.on('register', async (data) => {
        console.log(`[BC App HTTP Socket.IO] Register attempt for username: "${data?.username}" from ${socket.id}`);
        const result = await auth.registerUser(data?.username, data?.password);
        if (result.success) {
            console.log(`[BC App HTTP Socket.IO] Registration successful for ${result.username} (${result.userId})`);
        } else {
            console.warn(`[BC App HTTP Socket.IO] Registration failed for "${data?.username}": ${result.message}`);
        }
        socket.emit('registerResponse', result);
    });

    socket.on('login', async (data) => {
        console.log(`[BC App HTTP Socket.IO] Login attempt for username: "${data?.username}" from ${socket.id}`);
        const result = await auth.loginUser(data?.username, data?.password);
        if (result.success) {
            console.log(`[BC App HTTP Socket.IO] Login successful for ${result.username} (${result.userId}). Assigning to socket ${socket.id}.`);
            socket.userData = { userId: result.userId, username: result.username };
            loggedInUsers[socket.id] = socket.userData;
            gameManager.handleRequestGameState(socket, socket.userData.userId);
        } else {
            console.warn(`[BC App HTTP Socket.IO] Login failed for "${data?.username}": ${result.message}`);
            socket.userData = null;
            if (loggedInUsers[socket.id]) delete loggedInUsers[socket.id];
        }
        socket.emit('loginResponse', result);
    });

    socket.on('logout', () => {
        console.log(`[BC App HTTP Socket.IO] Logout for user ${socket.userData?.username || socket.id}`);
        gameManager.handleDisconnect(socket.id, socket.userData?.userId || socket.id);
        socket.userData = null;
        if (loggedInUsers[socket.id]) delete loggedInUsers[socket.id];
    });

    socket.on('createGame', (data) => {
        const identifier = socket.userData?.userId || socket.id;
        const mode = data?.mode || 'ai';
        if (mode === 'pvp' && !socket.userData) {
            socket.emit('gameError', { message: 'Необходимо войти в систему для создания PvP игры.' });
            return;
        }
        console.log(`[BC App HTTP Socket.IO] Create Game request from ${socket.userData?.username || socket.id} (Identifier: ${identifier}). Mode: ${mode}, Character: ${data?.characterKey}`);
        const characterKey = data?.characterKey || 'elena';
        gameManager.createGame(socket, mode, characterKey, identifier);
    });

    socket.on('joinGame', (data) => {
        if (!socket.userData) {
            socket.emit('gameError', { message: 'Необходимо войти в систему для присоединения к игре.' });
            return;
        }
        console.log(`[BC App HTTP Socket.IO] Join Game request from ${socket.userData.username} (${socket.id}). Game ID: ${data?.gameId}`);
        const gameId = data?.gameId;
        const identifier = socket.userData.userId;
        if (gameId) {
            gameManager.joinGame(socket, gameId, identifier);
        } else {
            socket.emit('gameError', { message: 'Не указан ID игры для присоединения.' });
        }
    });

    socket.on('findRandomGame', (data) => {
        if (!socket.userData) {
            socket.emit('gameError', { message: 'Необходимо войти в систему для поиска игры.' });
            return;
        }
        console.log(`[BC App HTTP Socket.IO] Find Random Game request from ${socket.userData.username} (${socket.id}). Preferred Character: ${data?.characterKey}`);
        const characterKey = data?.characterKey || 'elena';
        const identifier = socket.userData.userId;
        gameManager.findAndJoinRandomPvPGame(socket, characterKey, identifier);
    });

    socket.on('requestPvPGameList', () => {
        console.log(`[BC App HTTP Socket.IO] Request PvP Game List from ${socket.userData?.username || socket.id}`);
        const availableGames = gameManager.getAvailablePvPGamesListForClient();
        socket.emit('availablePvPGamesList', availableGames);
    });

    socket.on('requestGameState', () => {
        if (!socket.userData) {
            console.log(`[BC App HTTP Socket.IO] Request Game State from unauthenticated socket ${socket.id}.`);
            socket.emit('gameNotFound', { message: 'Необходимо войти для восстановления игры.' });
            return;
        }
        console.log(`[BC App HTTP Socket.IO] Request Game State from ${socket.userData.username} (${socket.id}).`);
        gameManager.handleRequestGameState(socket, socket.userData.userId);
    });

    socket.on('playerAction', (actionData) => {
        const identifier = socket.userData?.userId || socket.id;
        gameManager.handlePlayerAction(identifier, actionData);
    });

    socket.on('disconnect', (reason) => {
        const identifier = socket.userData?.userId || socket.id;
        console.log(`[BC App HTTP Socket.IO] User disconnected: ${socket.id} (Причина: ${reason}). Identifier: ${identifier}`);
        gameManager.handleDisconnect(socket.id, identifier);
        if (loggedInUsers[socket.id]) {
            delete loggedInUsers[socket.id];
        }
    });
});

// Запуск HTTP сервера
const PORT = process.env.BC_INTERNAL_PORT || 3200; // Внутренний порт для bc.js
const HOSTNAME = '127.0.0.1';                      // Слушать ТОЛЬКО на localhost

server.listen(PORT, HOSTNAME, () => { // Явно указываем HOSTNAME
    console.log(`Battle Club HTTP Application Server running at http://${HOSTNAME}:${PORT}`);
    console.log(`This server should only be accessed locally by the reverse proxy.`);
    console.log(`Serving static files from: ${path.join(__dirname, 'public')}`);
});

// Обработка необработанных промис-ошибок
process.on('unhandledRejection', (reason, promise) => {
    console.error('[BC App HTTP UNHANDLED REJECTION] Unhandled Rejection at:', promise, 'reason:', reason);
});

process.on('uncaughtException', (err) => {
    console.error('[BC App HTTP UNCAUGHT EXCEPTION] Caught exception:', err);
});