import XCTest

/// Comprehensive UI tests for MixBoard iOS.
/// Tests cover: app launch, playlist CRUD, navigation, settings, and Now Playing.
final class MixBoardUITests: XCTestCase {

    var app: XCUIApplication!

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

    override func tearDownWithError() throws {
        app = nil
    }

    // MARK: - App Launch

    func testAppLaunchShowsMixBoardTitle() {
        // The main screen should show "MixBoard" as the navigation title
        let title = app.navigationBars["MixBoard"]
        XCTAssertTrue(title.waitForExistence(timeout: 5), "MixBoard navigation title should exist")
    }

    func testAppLaunchShowsToolbarButtons() {
        // Library button should exist
        let libraryButton = app.buttons["libraryButton"]
        XCTAssertTrue(libraryButton.waitForExistence(timeout: 5), "Library button should exist")

        // Settings button should exist
        let settingsButton = app.buttons["settingsButton"]
        XCTAssertTrue(settingsButton.exists, "Settings button should exist")

        // New playlist button should exist
        let newPlaylistButton = app.buttons["newPlaylistButton"]
        XCTAssertTrue(newPlaylistButton.exists, "New playlist button should exist")
    }

    // MARK: - Empty State

    func testEmptyStateVisible() {
        // On a fresh install with no playlists, the empty state should be visible
        let emptyState = app.staticTexts["No playlists yet"]
        if emptyState.waitForExistence(timeout: 3) {
            XCTAssertTrue(emptyState.exists)
            let subtitle = app.staticTexts["Create a playlist to start building your mix"]
            XCTAssertTrue(subtitle.exists)
        }
        // If playlists already exist from a previous test, that's OK — skip
    }

    // MARK: - Create Playlist

    func testCreatePlaylist() {
        let newPlaylistButton = app.buttons["newPlaylistButton"]
        XCTAssertTrue(newPlaylistButton.waitForExistence(timeout: 5))
        newPlaylistButton.tap()

        // Alert should appear with "New Playlist" title
        let alert = app.alerts["New Playlist"]
        XCTAssertTrue(alert.waitForExistence(timeout: 3), "New Playlist alert should appear")

        // Type a name
        let textField = alert.textFields["Playlist name"]
        XCTAssertTrue(textField.exists, "Playlist name text field should exist")
        textField.tap()
        textField.typeText("UI Test Playlist")

        // Tap Create
        alert.buttons["Create"].tap()

        // Verify the playlist appears in the list
        let playlistCell = app.staticTexts["UI Test Playlist"]
        XCTAssertTrue(playlistCell.waitForExistence(timeout: 3), "Created playlist should appear in the list")
    }

    func testCreatePlaylistCancel() {
        let newPlaylistButton = app.buttons["newPlaylistButton"]
        XCTAssertTrue(newPlaylistButton.waitForExistence(timeout: 5))
        newPlaylistButton.tap()

        let alert = app.alerts["New Playlist"]
        XCTAssertTrue(alert.waitForExistence(timeout: 3))

        // Cancel
        alert.buttons["Cancel"].tap()

        // Alert should dismiss
        XCTAssertFalse(alert.exists)
    }

    // MARK: - Playlist Navigation

    func testNavigateToPlaylistDetail() {
        // Create a playlist first
        createPlaylistViaUI(name: "Detail Test")

        // Tap it
        let cell = app.staticTexts["Detail Test"]
        XCTAssertTrue(cell.waitForExistence(timeout: 3))
        cell.tap()

        // Should navigate to detail view
        let detailView = app.otherElements["playlistDetailView"]
        XCTAssertTrue(detailView.waitForExistence(timeout: 3), "Playlist detail view should appear")
    }

    func testPlaylistDetailShowsHeader() {
        createPlaylistViaUI(name: "Header Test")

        let cell = app.staticTexts["Header Test"]
        XCTAssertTrue(cell.waitForExistence(timeout: 3))
        cell.tap()

        // Should show track count
        let trackCount = app.staticTexts["0 tracks"]
        XCTAssertTrue(trackCount.waitForExistence(timeout: 3), "Track count should show 0 tracks")
    }

    // MARK: - Delete Playlist

    func testDeletePlaylistViaSwipe() {
        createPlaylistViaUI(name: "Delete Me")

        let cell = app.staticTexts["Delete Me"]
        XCTAssertTrue(cell.waitForExistence(timeout: 3))

        // Swipe left to reveal delete
        cell.swipeLeft()

        // Tap delete
        let deleteButton = app.buttons["Delete"]
        if deleteButton.waitForExistence(timeout: 2) {
            deleteButton.tap()
            // Verify it's gone
            XCTAssertFalse(cell.waitForExistence(timeout: 2))
        }
    }

    // MARK: - Library Navigation

    func testOpenLibrarySheet() {
        let libraryButton = app.buttons["libraryButton"]
        XCTAssertTrue(libraryButton.waitForExistence(timeout: 5))
        libraryButton.tap()

        // Library view should appear
        let libraryView = app.otherElements["libraryView"]
        let libraryTitle = app.navigationBars["Library"]
        let appeared = libraryView.waitForExistence(timeout: 3) || libraryTitle.waitForExistence(timeout: 3)
        XCTAssertTrue(appeared, "Library should open as a sheet")
    }

    func testLibraryBrowseModes() {
        let libraryButton = app.buttons["libraryButton"]
        XCTAssertTrue(libraryButton.waitForExistence(timeout: 5))
        libraryButton.tap()

        // Check browse mode buttons exist
        let modes = ["Folders", "Songs", "Artists", "Albums", "Genres"]
        for mode in modes {
            let button = app.buttons[mode]
            if button.waitForExistence(timeout: 2) {
                XCTAssertTrue(button.exists, "\(mode) browse mode button should exist")
            }
        }
    }

    // MARK: - Settings Navigation

    func testOpenSettingsSheet() {
        let settingsButton = app.buttons["settingsButton"]
        XCTAssertTrue(settingsButton.waitForExistence(timeout: 5))
        settingsButton.tap()

        // Settings view should appear
        let settingsTitle = app.navigationBars["Settings"]
        XCTAssertTrue(settingsTitle.waitForExistence(timeout: 3), "Settings should open as a sheet")
    }

    func testSettingsShowsSkinSection() {
        let settingsButton = app.buttons["settingsButton"]
        XCTAssertTrue(settingsButton.waitForExistence(timeout: 5))
        settingsButton.tap()

        // Check that skin options are visible
        let skinSection = app.staticTexts["Skin"]
        XCTAssertTrue(skinSection.waitForExistence(timeout: 3), "Skin section should be visible")
    }

    func testSettingsShowsMixTargetsSection() {
        let settingsButton = app.buttons["settingsButton"]
        XCTAssertTrue(settingsButton.waitForExistence(timeout: 5))
        settingsButton.tap()

        let mixTargetsSection = app.staticTexts["Mix Targets"]
        XCTAssertTrue(mixTargetsSection.waitForExistence(timeout: 3), "Mix Targets section should be visible")
    }

    func testSwitchSkin() {
        let settingsButton = app.buttons["settingsButton"]
        XCTAssertTrue(settingsButton.waitForExistence(timeout: 5))
        settingsButton.tap()

        // Tap on a skin option
        let vinylButton = app.buttons.matching(NSPredicate(format: "label CONTAINS 'Vinyl'")).firstMatch
        if vinylButton.waitForExistence(timeout: 3) {
            vinylButton.tap()
            // Skin should now be selected (checkmark should appear)
            // We just verify no crash — theme switching is tested in unit tests
        }
    }

    func testSettingsShowsLibraryStats() {
        let settingsButton = app.buttons["settingsButton"]
        XCTAssertTrue(settingsButton.waitForExistence(timeout: 5))
        settingsButton.tap()

        // Scroll down to Library section
        let librarySection = app.staticTexts["Library"]
        if librarySection.waitForExistence(timeout: 2) {
            XCTAssertTrue(app.staticTexts["Tracks"].exists || app.staticTexts.matching(NSPredicate(format: "label CONTAINS 'Tracks'")).count > 0)
        }
    }

    // MARK: - Mini Player

    func testMiniPlayerNotVisibleWithoutTrack() {
        // When no track is playing, mini player should not be visible
        let miniPlayer = app.otherElements["miniPlayer"]
        XCTAssertFalse(miniPlayer.exists, "Mini player should not be visible without a playing track")
    }

    // MARK: - Now Playing

    func testNowPlayingNotShownInitially() {
        // Now Playing should not be shown on launch
        let nowPlayingTitle = app.staticTexts["nowPlayingTitle"]
        XCTAssertFalse(nowPlayingTitle.exists, "Now Playing should not be shown initially")
    }

    // MARK: - Multiple Playlist Operations

    func testCreateMultiplePlaylists() {
        createPlaylistViaUI(name: "Playlist Alpha")
        createPlaylistViaUI(name: "Playlist Beta")
        createPlaylistViaUI(name: "Playlist Gamma")

        XCTAssertTrue(app.staticTexts["Playlist Alpha"].waitForExistence(timeout: 3))
        XCTAssertTrue(app.staticTexts["Playlist Beta"].exists)
        XCTAssertTrue(app.staticTexts["Playlist Gamma"].exists)
    }

    // MARK: - Orientation (iPad)

    func testLandscapeDoesNotCrash() {
        XCUIDevice.shared.orientation = .landscapeLeft
        sleep(1)
        let title = app.navigationBars["MixBoard"]
        XCTAssertTrue(title.waitForExistence(timeout: 3))

        // Rotate back
        XCUIDevice.shared.orientation = .portrait
        sleep(1)
        XCTAssertTrue(title.waitForExistence(timeout: 3))
    }

    // MARK: - Helpers

    /// Create a playlist using the UI flow.
    private func createPlaylistViaUI(name: String) {
        let newPlaylistButton = app.buttons["newPlaylistButton"]
        guard newPlaylistButton.waitForExistence(timeout: 5) else {
            XCTFail("New playlist button not found")
            return
        }
        newPlaylistButton.tap()

        let alert = app.alerts["New Playlist"]
        guard alert.waitForExistence(timeout: 3) else {
            XCTFail("New Playlist alert not found")
            return
        }

        let textField = alert.textFields["Playlist name"]
        textField.tap()
        textField.typeText(name)
        alert.buttons["Create"].tap()

        // Wait for the playlist to appear
        _ = app.staticTexts[name].waitForExistence(timeout: 3)
    }
}

// MARK: - Launch Performance Test

final class MixBoardLaunchPerformanceTests: XCTestCase {

    func testLaunchPerformance() throws {
        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
            measure(metrics: [XCTApplicationLaunchMetric()]) {
                XCUIApplication().launch()
            }
        }
    }
}
