Examples
Input: [('addSong', 1, 'A'), ('addSong', 2, 'B'), ('addSong', 3, 'C'), ('play', 1), ('queueSong', 2), ('queueSong', 3), ('next',), ('getNowPlaying',), ('prev',), ('pause',), ('getNowPlaying',), ('addFavorite', 1), ('addFavorite', 2), ('addFavorite', 3), ('listFavorites',)]
Expected Output: ['OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', (2, 'B', 'playing'), 'OK', 'OK', (1, 'A', 'paused'), 'OK', 'OK', 'OK', [1, 2, 3]]
Explanation: Basic flow: play song 1, queue songs 2 and 3, move next to 2, go back to 1, pause it, then fill the favorites list to its capacity.
Input: [('addSong', 10, 'X'), ('addSong', 10, 'X2'), ('play', 99), ('next',), ('prev',), ('pause',), ('addFavorite', 10), ('addSong', 11, 'Y'), ('addSong', 12, 'Z'), ('addSong', 13, 'W'), ('addFavorite', 11), ('addFavorite', 12), ('addFavorite', 13), ('listFavorites',)]
Expected Output: ['OK', 'ERROR: DuplicateSong', 'ERROR: SongNotFound', 'ERROR: NoNextSong', 'ERROR: NoPreviousSong', 'ERROR: NothingPlaying', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'ERROR: FavoritesFull', [10, 11, 12]]
Explanation: Covers duplicate song insertion, invalid play, navigation on empty history/queue, pausing when nothing is selected, and deterministic rejection of a fourth favorite.
Input: [('addSong', 1, 'A'), ('addSong', 2, 'B'), ('addSong', 3, 'C'), ('play', 1), ('queueSong', 2), ('queueSong', 1), ('addFavorite', 1), ('next',), ('removeSong', 2), ('getNowPlaying',), ('prev',), ('getNowPlaying',), ('removeSong', 1), ('listFavorites',), ('next',), ('queueSong', 2)]
Expected Output: ['OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', None, 'OK', (1, 'A', 'playing'), 'OK', [], 'ERROR: NoNextSong', 'ERROR: SongNotFound']
Explanation: Removing the currently playing song stops playback. Later `prev()` can still reach an earlier valid song. Removing song 1 also clears it from favorites, and stale queued copies are skipped so `next()` fails.
Input: []
Expected Output: []
Explanation: No operations means no results.
Input: [('addSong', 1, 'A'), ('addSong', 2, 'B'), ('addSong', 3, 'C'), ('play', 1), ('queueSong', 2), ('queueSong', 3), ('next',), ('prev',), ('next',), ('getNowPlaying',)]
Expected Output: ['OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'OK', (2, 'B', 'playing')]
Explanation: After moving from 1 to 2, `prev()` returns to 1 and stores 2 in forward history. The next `next()` must use that forward history first, so it returns to 2 before considering queued song 3.