import XCTest

/// Playback and queue UI tests — verifies play, queue add, play next, and clear operations.
/// Uses `-MockNetwork` to ensure tests work without a live server.
final class PlaybackUITests: XCTestCase {

    var app: XCUIApplication!

    override func setUpWithError() throws {
        continueAfterFailure = false
        app = XCUIApplication()
        app.launchArguments += ["-UITesting", "-MockNetwork"]
    }

    override func tearDownWithError() throws {
        app = nil
    }

    // MARK: - Helpers

    private func openCloudBrowser() {
        let cloudButton = app.buttons["cloudBrowserButton"]
        XCTAssertTrue(cloudButton.waitForExistence(timeout: 5), "Cloud browser button should exist")
        cloudButton.tap()
    }

    /// Navigates to a mock album's track list.
    /// Returns true if tracks are visible.
    @discardableResult
    private func navigateToAlbumTracks() -> Bool {
        openCloudBrowser()

        let albumsLink = app.buttons["cloud.browse.album"]
        guard albumsLink.waitForExistence(timeout: 5) else { return false }
        albumsLink.tap()

        // Wait for mock album row to appear
        let firstAlbumRow = app.buttons["cloud.album.row.album-1"]
        guard firstAlbumRow.waitForExistence(timeout: 5) else { return false }
        firstAlbumRow.tap()

        // Wait for track content to load
        let trackTitle = app.staticTexts["First Track"]
        return trackTitle.waitForExistence(timeout: 5)
    }

    // MARK: - Phase 2: Playback Tests

    /// Play a cloud track → mini player should appear with the track title.
    func testPlayCloudTrack() {
        app.launch()
        guard navigateToAlbumTracks() else {
            XCTFail("Could not navigate to album tracks")
            return
        }

        // Tap the first track row (the "Play All" button or a track)
        let playAllButton = app.buttons["Play All"]
        if playAllButton.waitForExistence(timeout: 3) {
            playAllButton.tap()
        } else {
            // Tap first track cell
            let firstTrack = app.cells.element(boundBy: 2) // skip header + play all section
            if firstTrack.waitForExistence(timeout: 3) {
                firstTrack.tap()
            }
        }

        // Dismiss the cloud browser
        let doneButton = app.buttons["Done"]
        if doneButton.waitForExistence(timeout: 3) {
            doneButton.tap()
        }

        // Mini player should appear
        let miniPlayer = app.otherElements["miniPlayer"]
        XCTAssertTrue(miniPlayer.waitForExistence(timeout: 10), "Mini player should appear after playing a track")

        // Track title should be visible in mini player
        let trackTitle = app.staticTexts.matching(identifier: "miniPlayer.trackTitle").firstMatch
        XCTAssertTrue(trackTitle.exists, "Mini player should show the track title")
    }

    /// Long-press a track → "Add to Queue" → queue view shows the entry.
    func testAddToQueue() {
        app.launch()
        guard navigateToAlbumTracks() else {
            XCTFail("Could not navigate to album tracks")
            return
        }

        // Long-press on a track to open context menu
        let trackCell = app.cells.element(boundBy: 3) // skip header + play all rows
        guard trackCell.waitForExistence(timeout: 3) else {
            XCTFail("Track cell should exist")
            return
        }
        trackCell.press(forDuration: 1.2)

        // Tap "Add to Queue" from context menu
        let addToQueueButton = app.buttons["Add to Queue"]
        guard addToQueueButton.waitForExistence(timeout: 3) else {
            // Context menu might not appear in simulator, skip gracefully
            return
        }
        addToQueueButton.tap()

        // Dismiss cloud browser
        let doneButton = app.buttons["Done"]
        if doneButton.waitForExistence(timeout: 3) {
            doneButton.tap()
        }

        // Open queue view (via mini player queue button or Now Playing)
        // First play something so queue is accessible
        // Queue is a sheet — check if we can open it from the mini player
        let miniPlayerQueue = app.buttons["miniPlayerQueue"]
        if miniPlayerQueue.waitForExistence(timeout: 5) {
            miniPlayerQueue.tap()

            // Queue should show the added entry
            let queueEmpty = app.otherElements["queue.emptyState"]
            XCTAssertFalse(queueEmpty.exists, "Queue should not be empty after adding a track")
        }
    }

    /// Long-press → "Play Next" → track appears at top of queue.
    func testQueuePlayNext() {
        app.launch()
        guard navigateToAlbumTracks() else {
            XCTFail("Could not navigate to album tracks")
            return
        }

        // Play first track to establish a now-playing state
        let playAllButton = app.buttons["Play All"]
        if playAllButton.waitForExistence(timeout: 3) {
            playAllButton.tap()
        }

        // Wait for playback to start
        sleep(2)

        // Navigate back to tracks if needed
        let backButton = app.navigationBars.buttons.firstMatch
        if backButton.exists {
            // We may still be on the album detail — long-press a different track
        }

        // Long-press second track
        let trackCell = app.cells.element(boundBy: 4)
        guard trackCell.waitForExistence(timeout: 3) else { return }
        trackCell.press(forDuration: 1.2)

        let playNextButton = app.buttons["Play Next"]
        guard playNextButton.waitForExistence(timeout: 3) else { return }
        playNextButton.tap()

        // Dismiss cloud browser
        let doneButton = app.buttons["Done"]
        if doneButton.waitForExistence(timeout: 3) {
            doneButton.tap()
        }

        // Open queue
        let miniPlayerQueue = app.buttons["miniPlayerQueue"]
        if miniPlayerQueue.waitForExistence(timeout: 5) {
            miniPlayerQueue.tap()

            // Queue should have entries
            let queueEmpty = app.otherElements["queue.emptyState"]
            XCTAssertFalse(queueEmpty.exists, "Queue should have the 'Play Next' entry")
        }
    }

    /// Add to queue → Clear → queue should be empty.
    func testQueueClear() {
        app.launch()
        guard navigateToAlbumTracks() else {
            XCTFail("Could not navigate to album tracks")
            return
        }

        // Play a track first
        let playAllButton = app.buttons["Play All"]
        if playAllButton.waitForExistence(timeout: 3) {
            playAllButton.tap()
        }

        sleep(2)

        // Add another track to queue via context menu
        let trackCell = app.cells.element(boundBy: 4)
        guard trackCell.waitForExistence(timeout: 3) else { return }
        trackCell.press(forDuration: 1.2)

        let addToQueueButton = app.buttons["Add to Queue"]
        guard addToQueueButton.waitForExistence(timeout: 3) else { return }
        addToQueueButton.tap()

        // Dismiss cloud browser
        let doneButton = app.buttons["Done"]
        if doneButton.waitForExistence(timeout: 3) {
            doneButton.tap()
        }

        // Open queue
        let miniPlayerQueue = app.buttons["miniPlayerQueue"]
        guard miniPlayerQueue.waitForExistence(timeout: 5) else {
            XCTFail("Mini player queue button should exist")
            return
        }
        miniPlayerQueue.tap()

        // Tap Clear
        let clearButton = app.buttons["queue.clearButton"]
        if clearButton.waitForExistence(timeout: 3) {
            clearButton.tap()

            // Queue should be empty (only Now Playing remains)
            // The clear button itself should disappear after clearing
            XCTAssertFalse(clearButton.waitForExistence(timeout: 3), "Clear button should disappear after clearing queue")
        }
    }
}
