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');

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

// Room State
const rooms = {};
const RECONNECT_GRACE_PERIOD = 10000; // 10 seconds
const disconnectedPlayers = new Map(); // Track recently disconnected players
const roomTimeouts = new Map(); // Track room cleanup timeouts

function createInitialGameState() {
    const board = Array(8).fill().map(() => Array(8).fill(null));
    
    // Initialize pieces
    const setupRow = (row, color, pieces) => {
        pieces.forEach((type, col) => {
            board[row][col] = { type, color, hasMoved: false };
        });
    };

    const backRow = ['rook', 'knight', 'bishop', 'queen', 'king', 'bishop', 'knight', 'rook'];
    
    setupRow(0, 'black', backRow);
    setupRow(7, 'white', backRow);
    
    for (let i = 0; i < 8; i++) {
        board[1][i] = { type: 'pawn', color: 'black', hasMoved: false };
        board[6][i] = { type: 'pawn', color: 'white', hasMoved: false };
    }

    return {
        board,
        turn: 'white',
        gameActive: false,
        winner: null,
        check: false, // Is current turn player in check?
        lastMove: null, // { from: {r, c}, to: {r, c} }
        capturedPieces: { white: [], black: [] } // Track captured pieces
    };
}

// Export a function that accepts the IO instance and namespace
module.exports = function(ioInstance, appInstance, roomsDB, appEmitter) {
    // If roomsDB is not passed (standalone mode), try to require it
    if (!roomsDB) {
        try {
            roomsDB = require('../../../admin/server/rooms-db');
        } catch (e) {
            console.warn('Chess: Could not load roomsDB for standalone mode');
        }
    }

    // Function to load rooms from DB
    const loadRooms = () => {
        if (!roomsDB) return;
        
        try {
            // Fetch ALL rooms to distinguish between 'inactive' and 'deleted'
            const dbRooms = roomsDB.getRoomsByGame('chess');
            const dbRoomIds = new Set();

            // 1. Update/Add rooms
            dbRooms.forEach(room => {
                const roomId = `room_${room.id}`;
                dbRoomIds.add(roomId);
                
                if (room.status === 'active') {
                    // ACTIVE ROOMS: Load or Update
                    if (rooms[roomId]) {
                        // Update existing room properties
                        rooms[roomId].name = room.name;
                        rooms[roomId].password = room.password || null;
                        rooms[roomId].type = room.type;
                        rooms[roomId].isProtected = !!room.password;
                        rooms[roomId].isArchived = false; // Ensure not archived
                    } else {
                        // Create new room
                        rooms[roomId] = {
                            id: roomId,
                            name: room.name,
                            password: room.password || null,
                            type: room.type,
                            isProtected: !!room.password,
                            players: { white: null, black: null },
                            gameState: createInitialGameState(),
                            isActive: false,
                            chatHistory: []
                        };
                    }
                } else {
                    // INACTIVE ROOMS: "Just make inactive" (Remove immediately)
                    if (rooms[roomId]) {
                        // Notify players before deleting
                        if (ioInstance) {
                            ioInstance.to(roomId).emit('chat_message', {
                                id: Date.now() + '_sys',
                                sender: 'System',
                                role: 'system',
                                text: '⚠️ This room has been deactivated by the admin.',
                                timestamp: Date.now(),
                                seenBy: []
                            });
                        }
                        delete rooms[roomId];
                    }
                }
            });

            // 2. Handle Deleted Rooms (Rooms in memory but NOT in DB)
            // These should be Archived (Graceful Shutdown)
            Object.keys(rooms).forEach(roomId => {
                if (!dbRoomIds.has(roomId)) {
                    // Room DELETED from DB
                    const room = rooms[roomId];
                    const playerCount = Object.values(room.players).filter(p => p !== null).length;
                    
                    if (playerCount === 0) {
                        // Empty room - delete immediately
                        delete rooms[roomId];
                    } else {
                        // Active room - mark as archived (graceful shutdown)
                        if (!room.isArchived) {
                            room.isArchived = true;
                            // Notify players
                            if (ioInstance) {
                                ioInstance.to(roomId).emit('chat_message', {
                                    id: Date.now() + '_sys',
                                    sender: 'System',
                                    role: 'system',
                                    text: '⚠️ This room has been deleted by the admin. You may finish your current game, but no new players can join.',
                                    timestamp: Date.now(),
                                    seenBy: []
                                });
                            }
                        }
                    }
                }
            });

            console.log(`Chess: Reloaded rooms. Total: ${Object.keys(rooms).length}`);
            
            // Broadcast new room list to all connected clients
            if (ioInstance) {
                ioInstance.emit('room_list', getRoomList());
            }

        } catch (error) {
            console.error('Chess: Error loading rooms from database:', error);
        }
    };

    // Initial Load
    if (roomsDB) {
        loadRooms();
        
        // Listen for updates
        if (appEmitter) {
            appEmitter.on('room_update', ({ gameType }) => {
                if (gameType === 'chess' || !gameType) {
                    console.log('Chess: Received room update event, reloading...');
                    loadRooms();
                }
            });
        }
    } else {
        // Fallback to .env configuration
        let roomCount = 0;
        for (let i = 1; i <= 100; i++) {
            if (process.env[`CHESS_ROOM_${i}_NAME`]) {
                roomCount = i;
            } else if (i > roomCount + 5) {
                break;
            }
        }

        // Initialize rooms found in .env
        for (let i = 1; i <= roomCount; i++) {
            const envName = process.env[`CHESS_ROOM_${i}_NAME`];
            const envPass = process.env[`CHESS_ROOM_${i}_PASS`];
            const envType = process.env[`CHESS_ROOM_${i}_TYPE`] || 'private';
            
            const roomType = (envType === 'public' || envType === 'private') ? envType : 'private';
            
            if (envName) {
                rooms[`room_${i}`] = {
                    id: `room_${i}`,
                    name: envName,
                    password: envPass || null,
                    type: roomType,
                    isProtected: !!envPass,
                    players: { white: null, black: null },
                    gameState: createInitialGameState(),
                    isActive: false,
                    chatHistory: []
                };
            }
        }
        console.log(`Chess: Initialized ${Object.keys(rooms).length} rooms from .env`);
    }

    const router = express.Router();
    
    // If appInstance is provided (production mode), use it to serve static files
    if (appInstance) {
        router.use(express.static(path.join(__dirname, '../public')));
        appInstance.use('/games/chess', router);
    }

    // Use the provided IO instance or the local one
    const ioToUse = ioInstance || io;
    
    // If using a shared IO instance (production), we might need a namespace
    // But since we are using path-based routing in the client, we can just use the default namespace
    // or a specific one if passed. For now, let's stick to the root namespace but 
    // we need to be careful not to conflict with other games if they share events.
    // Ideally, we should use io.of('/chess') but the client is configured for path, not namespace.
    // Given the client uses /chess/socket.io path, the connection comes to the main IO.
    
    // Actually, for single port, we should use Namespaces: io.of('/chess')
    // But our client is configured with `path: '/chess/socket.io'`.
    // If we change to single port, we should probably use Namespaces instead of Path separation.
    // However, to keep it simple and compatible with current client:
    // The client sends to /chess/socket.io. In production single port, we can route that path to socket.io.
    
    // Let's define the connection handler function to be reusable
    const onConnection = (socket) => {
        console.log('User connected to Chess:', socket.id);

        socket.emit('room_list', getRoomList());

        socket.on('get_rooms', () => {
            socket.emit('room_list', getRoomList());
        });

        socket.on('get_players', ({ roomId }) => {
            const room = rooms[roomId];
            if (room) {
                socket.emit('player_update', getPublicPlayers(room));
            }
        });

        socket.on('join_room', ({ roomId, password, role, playerName }) => {
            const room = rooms[roomId];
            if (!room) return socket.emit('error', 'Room not found');
            
            // Prevent joining archived rooms
            if (room.isArchived) {
                return socket.emit('error', 'This room has been closed by the admin.');
            }
    
            // Validate role
            if (role !== 'white' && role !== 'black') {
                 return socket.emit('error', 'Invalid role');
            }

            const disconnectKey = `${roomId}:${role}:${playerName}`;
            const disconnectedInfo = disconnectedPlayers.get(disconnectKey);
            
            if (disconnectedInfo) {
                console.log(`[JOIN] Reconnecting...`);
                disconnectedPlayers.delete(disconnectKey);
                
                // Clear any pending player-specific timeout
                if (disconnectedInfo.timeout) {
                    console.log(`[JOIN] Clearing player timeout`);
                    clearTimeout(disconnectedInfo.timeout);
                }
                
                // Clear the room-level cleanup timeout since a player is reconnecting
                if (roomTimeouts.has(roomId)) {
                    console.log(`Clearing room cleanup timeout for ${roomId} - player reconnecting`);
                    clearTimeout(roomTimeouts.get(roomId));
                    roomTimeouts.delete(roomId);
                }
                
                // Verify password matches what they had before
                if (disconnectedInfo.password !== password) {
                    console.log(`PASSWORD MISMATCH! Saved: "${disconnectedInfo.password}", Provided: "${password}"`);
                    return socket.emit('error', 'Incorrect password');
                }
                console.log('Password verified, allowing reconnection');
            } else {
                // Normal join flow - validate password
                if (room.isProtected) {
                    // Room has a fixed password from .env
                    if (room.password !== password) {
                        return socket.emit('error', 'Incorrect password');
                    }
                    room.isActive = true; // Always active if protected/configured
                } else {
                    // Dynamic password logic (for non-configured rooms)
                    if (room.isActive) {
                        if (room.password && room.password !== password) {
                            return socket.emit('error', 'Incorrect password');
                        }
                    } else {
                        // First player sets the password
                        if (Object.values(room.players).every(p => p === null)) {
                            room.password = password;
                            room.isActive = true;
                        } else if (room.password !== password) {
                             return socket.emit('error', 'Incorrect password');
                        }
                    }
                }
    
                // Check Role Availability
                if (room.players[role]) {
                    // CRITICAL FIX: If player exists but it's the SAME player (name matches) 
                    // and just hasn't been fully disconnected yet (race condition), allow rejoin.
                    if (room.players[role].name === playerName) {
                        console.log(`[JOIN] Player ${playerName} (${role}) found in room but status is ${room.players[role].status}. Treating as immediate reconnect.`);
                        
                        // Force disconnect the old socket if it's different
                        if (room.players[role].id !== socket.id) {
                            console.log(`[JOIN] Overwriting old socket ${room.players[role].id} with new ${socket.id}`);
                        }
                        // Proceed to join (overwrite)
                    } else {
                        return socket.emit('error', `Role ${role} is already taken`);
                    }
                }
    
                // Check Name Uniqueness (if not the same player we just handled above)
                const existingPlayer = Object.values(room.players).find(p => p && p.name === playerName && p !== room.players[role]);
                if (existingPlayer) {
                    return socket.emit('error', `Name "${playerName}" is already taken in this room`);
                }
            }
    
            // Join Room
            socket.join(roomId);
            room.players[role] = { 
                id: socket.id, 
                name: playerName, 
                status: 'online',
                joinedAt: Date.now()
            };
            
            // Notify user
            socket.emit('joined_room', { 
                roomId, 
                role, 
                gameState: room.gameState,
                players: getPublicPlayers(room),
                chatHistory: room.chatHistory || []
            });
    
            // Notify others in room
            ioToUse.to(roomId).emit('player_update', getPublicPlayers(room));
            ioToUse.emit('room_list', getRoomList()); // Update lobby
            
            // Start Game if full
            if (room.players.white && room.players.black) {
                // Generate unique numeric match ID (timestamp + random suffix)
                room.currentMatchId = Date.now() * 1000 + Math.floor(Math.random() * 1000);
                
                room.gameState.gameActive = true;
                ioToUse.to(roomId).emit('game_start', {
                    gameState: room.gameState,
                    matchId: room.currentMatchId
                });
            }
        });

        socket.on('player_status', ({ roomId, status }) => {
            const room = rooms[roomId];
            if (!room) return;
            const role = getPlayerRole(room, socket.id);
            if (role && room.players[role]) {
                room.players[role].status = status;
                ioToUse.to(roomId).emit('player_status_update', { players: getPublicPlayers(room) });
            }
        });

        socket.on('make_move', ({ roomId, move }) => {
            const room = rooms[roomId];
            if (!room) return;
            
            const playerRole = getPlayerRole(room, socket.id);
            if (!playerRole || room.gameState.turn !== playerRole) return;
            
            if (validateMove(room.gameState, move, playerRole)) {
                applyMove(room.gameState, move);
                
                // Check win conditions / check
                if (isCheckmate(room.gameState, room.gameState.turn)) {
                    room.gameState.winner = playerRole;
                    room.gameState.gameActive = false;
                    ioToUse.to(roomId).emit('game_over', { winner: playerRole, reason: 'checkmate' });
                } else if (isStalemate(room.gameState, room.gameState.turn)) {
                    room.gameState.gameActive = false;
                    ioToUse.to(roomId).emit('game_over', { winner: 'draw', reason: 'stalemate' });
                } else if (isCheck(room.gameState, room.gameState.turn)) {
                    room.gameState.check = true;
                } else {
                    room.gameState.check = false;
                }

                console.log('Sending gameState with capturedPieces:', room.gameState.capturedPieces);
                ioToUse.to(roomId).emit('update_game', { gameState: room.gameState });
            }
        });

        socket.on('restart_game', ({ roomId }) => {
            const room = rooms[roomId];
            if (!room) return;
            
            // Generate new unique numeric match ID for restarted game
            room.currentMatchId = Date.now() * 1000 + Math.floor(Math.random() * 1000);
            
            room.gameState = createInitialGameState();
            room.gameState.gameActive = true;
            room.chatHistory = [];
            ioToUse.to(roomId).emit('game_start', {
                gameState: room.gameState,
                matchId: room.currentMatchId
            });
            ioToUse.to(roomId).emit('chat_cleared');
        });

        socket.on('leave_room', ({ roomId }) => {
            handleLeave(socket, roomId, ioToUse);
        });

        socket.on('chat_message', ({ roomId, message }) => {
            const room = rooms[roomId];
            if (!room) return;
            const role = getPlayerRole(room, socket.id);
            if (!role) return;
            
            const chatMessage = {
                id: Date.now() + '_' + role,
                sender: room.players[role].name,
                role: role,
                text: message,
                timestamp: Date.now(),
                seenBy: [role]
            };
            
            if (!room.chatHistory) room.chatHistory = [];
            room.chatHistory.push(chatMessage);
            if (room.chatHistory.length > 50) room.chatHistory.shift();
            
            ioToUse.to(roomId).emit('chat_message', chatMessage);
        });

        socket.on('mark_messages_seen', ({ roomId }) => {
            const room = rooms[roomId];
            if (!room) return;
            const role = getPlayerRole(room, socket.id);
            if (!role) return;
            
            if (room.chatHistory) {
                const seenMessageIds = [];
                room.chatHistory.forEach(msg => {
                    if (!msg.seenBy.includes(role)) {
                        msg.seenBy.push(role);
                        seenMessageIds.push(msg.id);
                    }
                });
                
                if (seenMessageIds.length > 0) {
                    socket.to(roomId).emit('messages_seen', {
                        seenBy: role,
                        messageIds: seenMessageIds
                    });
                }
            }
        });

        socket.on('disconnect', () => {
            for (const roomId in rooms) {
                const room = rooms[roomId];
                if (room.players.white?.id === socket.id || room.players.black?.id === socket.id) {
                    handleLeave(socket, roomId, ioToUse);
                }
            }
        });
    };

    // Attach the connection handler
    ioToUse.on('connection', onConnection);
    
    return router;
};

// Standalone execution
if (require.main === module) {
    app.use(express.static(path.join(__dirname, '../public')));
    const PORT = process.env.PORT || 3001; // Default to 3001 for standalone
    server.listen(PORT, () => {
      console.log(`Chess server listening on *:${PORT}`);
    });
    
    // Initialize standalone socket logic
    module.exports(io);
}

// Updated handleLeave to accept io instance
function handleLeave(socket, roomId, ioInstance) {
    console.log(`[LEAVE] handleLeave called for socket ${socket.id} in room ${roomId}`);
    const room = rooms[roomId];
    if (!room) {
        console.log(`[LEAVE] Room ${roomId} not found`);
        return;
    }

    const role = getPlayerRole(room, socket.id);
    console.log(`[LEAVE] Player role: ${role}`);
    
    if (role) {
        const playerInfo = room.players[role];
        
        // Store disconnected player info for reconnection grace period
        const disconnectKey = `${roomId}:${role}:${playerInfo.name}`;
        console.log(`[LEAVE] Player ${playerInfo.name} (${role}) disconnecting. Key: ${disconnectKey}`);
        
        // Create timeout to remove player from room if they don't return
        const playerTimeoutId = setTimeout(() => {
            console.log(`[TIMEOUT] Player grace period expired for ${playerInfo.name} (${role})`);
            
            // Check if still disconnected (and room still exists)
            if (rooms[roomId] && rooms[roomId].players[role] && rooms[roomId].players[role].status === 'disconnected') {
                 console.log(`[TIMEOUT] Removing player ${role} from room`);
                 rooms[roomId].players[role] = null; // Remove from room
                 disconnectedPlayers.delete(disconnectKey); // Remove from reconnect map
                 
                 // Notify others
                 ioInstance.to(roomId).emit('player_update', getPublicPlayers(rooms[roomId]));
                 ioInstance.emit('room_list', getRoomList());
            }
        }, RECONNECT_GRACE_PERIOD);

        disconnectedPlayers.set(disconnectKey, {
            roomId,
            role,
            name: playerInfo.name,
            password: room.password,
            gameState: room.gameState,
            timeout: playerTimeoutId // Store timeout to clear on reconnect
        });
        console.log(`[LEAVE] Set disconnectedPlayers entry for ${disconnectKey}`);
        
        room.players[role].status = 'disconnected'; // Mark as disconnected
        socket.leave(roomId);
        
        // Check if both players are now disconnected
        const whiteKey = room.players.white ? null : `${roomId}:white:${playerInfo.role === 'white' ? playerInfo.name : (room.players.white?.name || '')}`;
        const blackKey = room.players.black ? null : `${roomId}:black:${playerInfo.role === 'black' ? playerInfo.name : (room.players.black?.name || '')}`;
        
        // Get all disconnect keys for this room
        let whiteDisconnected = false;
        let blackDisconnected = false;
        
        for (const [key, value] of disconnectedPlayers) {
            if (value.roomId === roomId) {
                if (value.role === 'white') whiteDisconnected = true;
                if (value.role === 'black') blackDisconnected = true;
            }
        }
        
        // If both players are disconnected, start room termination countdown
        if (whiteDisconnected && blackDisconnected) {
            console.log(`Both players disconnected from room ${roomId}, starting 10-second termination countdown`);
            
            // Clear any existing termination timeout
            if (room.terminationTimeout) {
                clearTimeout(room.terminationTimeout);
            }
            
            room.terminationTimeout = setTimeout(() => {
                // Double-check both are still disconnected
                let stillBothDisconnected = true;
                let whiteStillDisconnected = false;
                let blackStillDisconnected = false;
                
                for (const [key, value] of disconnectedPlayers) {
                    if (value.roomId === roomId) {
                        if (value.role === 'white') whiteStillDisconnected = true;
                        if (value.role === 'black') blackStillDisconnected = true;
                    }
                }
                
                stillBothDisconnected = whiteStillDisconnected && blackStillDisconnected;
                
                if (stillBothDisconnected) {
                    console.log(`Resetting room ${roomId} - both players remained disconnected for 10 seconds`);
                    
                    // Clear individual player timeouts
                    for (const [key, value] of disconnectedPlayers) {
                        if (value.roomId === roomId) {
                            if (value.timeout) clearTimeout(value.timeout);
                            disconnectedPlayers.delete(key);
                        }
                    }
                    
                    // Reset the room instead of deleting it
                    if (!room.isProtected) {
                        room.password = null;
                        room.isActive = false;
                    }
                    room.gameState = createInitialGameState();
                    room.chatHistory = [];
                    ioInstance.emit('room_list', getRoomList());
                } else {
                    console.log(`Room ${roomId} termination cancelled - a player reconnected`);
                }
            }, 10000); // 10 seconds
        }
        
        if (room.players.white || room.players.black) {
            ioInstance.to(roomId).emit('player_left', { role });
            ioInstance.to(roomId).emit('player_update', getPublicPlayers(room));
        }
        ioInstance.emit('room_list', getRoomList());
    }
}

function getRoomList() {
    return Object.values(rooms)
        .filter(r => !r.isArchived) // Hide archived rooms from lobby
        .map(r => {
        const hasPlayers = r.players.white || r.players.black;
        const roomData = {
            id: r.id,
            name: r.name,
            type: r.type,
            players: {
                white: r.players.white ? { name: r.players.white.name, joinedAt: r.players.white.joinedAt } : null,
                black: r.players.black ? { name: r.players.black.name, joinedAt: r.players.black.joinedAt } : null
            },
            isActive: hasPlayers && r.isActive
        };
        if (r.type === 'public') roomData.password = r.password;
        return roomData;
    });
}

function getPublicPlayers(room) {
    return {
        white: room.players.white ? { name: room.players.white.name, status: room.players.white.status } : null,
        black: room.players.black ? { name: room.players.black.name, status: room.players.black.status } : null
    };
}

function getPlayerRole(room, socketId) {
    if (room.players.white?.id === socketId) return 'white';
    if (room.players.black?.id === socketId) return 'black';
    return null;
}

// --- Chess Logic ---

function validateMove(gameState, move, playerRole, silent = false) {
    const { from, to } = move;
    const board = gameState.board;

    // Safety check for move object
    if (!from || !to || typeof from.r === 'undefined' || typeof from.c === 'undefined' || typeof to.r === 'undefined' || typeof to.c === 'undefined') {
        if (!silent) console.error('Invalid move object:', move);
        return false;
    }

    // Bounds check
    if (from.r < 0 || from.r >= 8 || from.c < 0 || from.c >= 8 || to.r < 0 || to.r >= 8 || to.c < 0 || to.c >= 8) {
        if (!silent) console.log('Move out of bounds');
        return false;
    }

    const piece = board[from.r][from.c];

    if (!piece) {
        if (!silent) console.log('No piece at source');
        return false;
    }
    if (piece.color !== playerRole) {
        if (!silent) console.log('Piece color mismatch');
        return false;
    }
    
    // Check if target square has own piece
    if (board[to.r][to.c] && board[to.r][to.c].color === playerRole) {
        if (!silent) console.log('Target occupied by own piece');
        return false;
    }

    // Basic movement rules
    if (!isValidPieceMove(piece, from, to, board)) {
        if (!silent) console.log(`Invalid piece move for ${piece.type} from ${from.r},${from.c} to ${to.r},${to.c}`);
        return false;
    }

    // Check if move puts own king in check (simulate move)
    const tempBoard = JSON.parse(JSON.stringify(board));
    tempBoard[to.r][to.c] = tempBoard[from.r][from.c];
    tempBoard[from.r][from.c] = null;
    
    // Handle en passant simulation
    if (piece.type === 'pawn' && from.c !== to.c && !board[to.r][to.c]) {
         tempBoard[from.r][to.c] = null;
    }

    if (isCheck({ ...gameState, board: tempBoard }, playerRole)) {
        if (!silent) console.log('Move puts king in check');
        return false;
    }

    return true;
}

function isValidPieceMove(piece, from, to, board) {
    const dr = to.r - from.r;
    const dc = to.c - from.c;
    const absDr = Math.abs(dr);
    const absDc = Math.abs(dc);

    switch (piece.type) {
        case 'pawn':
            const direction = piece.color === 'white' ? -1 : 1;
            const startRow = piece.color === 'white' ? 6 : 1;
            
            // Move forward 1
            if (dc === 0 && dr === direction && !board[to.r][to.c]) return true;
            // Move forward 2
            if (dc === 0 && dr === 2 * direction && from.r === startRow && !board[to.r][to.c] && !board[from.r + direction][from.c]) return true;
            // Capture
            if (absDc === 1 && dr === direction && board[to.r][to.c] && board[to.r][to.c].color !== piece.color) return true;
            // En Passant (TODO: Add state tracking for en passant)
            return false;
        case 'rook':
            if (dr !== 0 && dc !== 0) return false;
            return isPathClear(from, to, board);
        case 'knight':
            return (absDr === 2 && absDc === 1) || (absDr === 1 && absDc === 2);
        case 'bishop':
            if (absDr !== absDc) return false;
            return isPathClear(from, to, board);
        case 'queen':
            if (dr !== 0 && dc !== 0 && absDr !== absDc) return false;
            return isPathClear(from, to, board);
        case 'king':
            return absDr <= 1 && absDc <= 1;
    }
    return false;
}

function isPathClear(from, to, board) {
    const dr = Math.sign(to.r - from.r);
    const dc = Math.sign(to.c - from.c);
    let r = from.r + dr;
    let c = from.c + dc;

    while (r !== to.r || c !== to.c) {
        if (board[r][c]) return false;
        r += dr;
        c += dc;
    }
    return true;
}

function applyMove(gameState, move) {
    const { from, to } = move;
    const piece = gameState.board[from.r][from.c];
    const targetPiece = gameState.board[to.r][to.c];
    
    // Track captured piece
    if (targetPiece) {
        gameState.capturedPieces[targetPiece.color].push(targetPiece.type);
    }
    
    // Handle En Passant capture
    if (piece.type === 'pawn' && from.c !== to.c && !targetPiece) {
        // En passant capture
        const capturedPawn = gameState.board[from.r][to.c];
        if (capturedPawn && capturedPawn.type === 'pawn') {
            gameState.capturedPieces[capturedPawn.color].push('pawn');
            gameState.board[from.r][to.c] = null;
        }
    }
    
    // Move piece
    gameState.board[to.r][to.c] = piece;
    gameState.board[from.r][from.c] = null;
    piece.hasMoved = true;
    
    // Pawn promotion (auto-queen for now)
    if (piece.type === 'pawn' && (to.r === 0 || to.r === 7)) {
        piece.type = 'queen';
    }

    gameState.lastMove = move;
    gameState.turn = gameState.turn === 'white' ? 'black' : 'white';
}

function isCheck(gameState, color) {
    // Find King
    let kingPos;
    for (let r = 0; r < 8; r++) {
        for (let c = 0; c < 8; c++) {
            const p = gameState.board[r][c];
            if (p && p.type === 'king' && p.color === color) {
                kingPos = { r, c };
                break;
            }
        }
    }
    if (!kingPos) return false; // Should not happen

    // Check if any opponent piece can attack king
    const opponent = color === 'white' ? 'black' : 'white';
    for (let r = 0; r < 8; r++) {
        for (let c = 0; c < 8; c++) {
            const p = gameState.board[r][c];
            if (p && p.color === opponent) {
                if (isValidPieceMove(p, { r, c }, kingPos, gameState.board)) return true;
            }
        }
    }
    return false;
}

function isCheckmate(gameState, color) {
    if (!isCheck(gameState, color)) return false;
    
    // Try all possible moves for current player
    for (let r = 0; r < 8; r++) {
        for (let c = 0; c < 8; c++) {
            const p = gameState.board[r][c];
            if (p && p.color === color) {
                // Try all target squares
                for (let tr = 0; tr < 8; tr++) {
                    for (let tc = 0; tc < 8; tc++) {
                        if (validateMove(gameState, { from: {r, c}, to: {r: tr, c: tc} }, color)) {
                            return false; // Found a valid move
                        }
                    }
                }
            }
        }
    }
    return true;
}

function isStalemate(gameState, color) {
    if (isCheck(gameState, color)) return false;
    
    console.log(`Checking stalemate for ${color}`);
    let validMovesFound = 0;

    // Check if player has ANY valid moves
    for (let r = 0; r < 8; r++) {
        for (let c = 0; c < 8; c++) {
            const p = gameState.board[r][c];
            if (p && p.color === color) {
                for (let tr = 0; tr < 8; tr++) {
                    for (let tc = 0; tc < 8; tc++) {
                        if (validateMove(gameState, { from: {r, c}, to: {r: tr, c: tc} }, color, true)) { // Pass true to suppress logs
                            validMovesFound++;
                            return false;
                        }
                    }
                }
            }
        }
    }
    console.log(`Stalemate detected for ${color}. Valid moves: ${validMovesFound}`);
    return true;
}



