redo(steps = 1) {
        if (this.isExecuting || this.redoStack.length === 0) return;
        this.isExecuting = true;

        try {
            const redoneCommands = [];
            for (let i = 0; i < steps && this.redoStack.length > 0; i++) {
                const command = this.redoStack.pop();
                command.execute();
                redoneCommands.unshift(command);
            }
            this.undoStack.push(...redoneCommands);
            this.notifyListeners();
        } catch (error) {
            console.error("Error redoing command:", error);
            this.recoverFromSnapshot();
        } finally {
            this.isExecuting = false;
        }
    }
Redoes a specified number of commands from the redo stack.

@param {number} [steps=1] - The number of commands to redo. Defaults to 1 if not specified.
@throws {Error} If an error occurs during the redo operation.

@description
This method performs the following steps:
1. Checks if redo operation is possible (not currently executing and redo stack is not empty).
2. Redoes the specified number of commands or as many as possible if fewer are available.
3. Moves redone commands back to the undo stack.
4. Notifies listeners of the state change.
5. If an error occurs, attempts to recover from the last valid snapshot.

@example
// Redo the last undone command
undoRedoManager.redo();

// Redo the last 3 undone commands
undoRedoManager.redo(3);