import XCTest

/// Smoke tests - run on every PR. Must complete in <2 minutes.
///
/// Tests that the app launches successfully, the auth screen renders correctly,
/// and core navigation is functional. These are the minimum-viability tests
/// that must pass before any PR can merge.
///
/// Zero sleep() calls -- all waits are condition-based.
final class SmokeTests: AuthenticatedUITestCase {

    // MARK: - App Launch

    func testAppLaunches() {
        let tabBar = app.tabBars.firstMatch
        let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
        let onboarding = app.descendants(matching: .any)
            .matching(identifier: UITestID.Onboarding.startFreshButton).firstMatch
        let loginField = app.textFields[UITestID.Auth.usernameField]

        let mainAppeared = residencesTab.waitForExistence(timeout: 10)
        let loginAppeared = loginField.waitForExistence(timeout: 3)
        let onboardingAppeared = onboarding.waitForExistence(timeout: 3)

        XCTAssertTrue(loginAppeared || mainAppeared || onboardingAppeared, "App should show login, main, or onboarding screen on launch")
    }

    // MARK: - Login Screen Elements

    func testLoginScreenElements() {
        let tabBar = app.tabBars.firstMatch
        if tabBar.exists {
            return // Already logged in, skip login screen element checks
        }

        let emailField = app.textFields[UITestID.Auth.usernameField]
        let passwordField = app.secureTextFields[UITestID.Auth.passwordField].exists
            ? app.secureTextFields[UITestID.Auth.passwordField]
            : app.textFields[UITestID.Auth.passwordField]
        let loginButton = app.buttons[UITestID.Auth.loginButton]

        guard emailField.exists else {
            return // Already logged in, skip
        }

        XCTAssertTrue(emailField.exists, "Email field should exist")
        XCTAssertTrue(passwordField.exists, "Password field should exist")
        XCTAssertTrue(loginButton.exists, "Login button should exist")
    }

    // MARK: - Login Flow

    func testLoginWithExistingCredentials() {
        let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
        XCTAssertTrue(residencesTab.waitForExistence(timeout: 15), "Should be on main screen after login")
    }

    // MARK: - Tab Navigation

    func testMainTabsExistAfterLogin() {
        let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
        guard residencesTab.waitForExistence(timeout: 15) else {
            XCTFail("Main screen did not appear")
            return
        }

        let tasksTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
        let contractorsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Contractors'")).firstMatch
        let documentsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Doc'")).firstMatch

        XCTAssertTrue(residencesTab.exists, "Residences tab should exist")
        XCTAssertTrue(tasksTab.exists, "Tasks tab should exist")
        XCTAssertTrue(contractorsTab.exists, "Contractors tab should exist")
        XCTAssertTrue(documentsTab.exists, "Documents tab should exist")
    }

    func testTabNavigation() {
        let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
        guard residencesTab.waitForExistence(timeout: 15) else {
            XCTFail("Main screen did not appear")
            return
        }

        // Navigate through all tabs — verify each by checking that navigation didn't crash
        // and the tab bar remains visible (proving the screen loaded)
        navigateToTasks()
        XCTAssertTrue(app.tabBars.firstMatch.waitForExistence(timeout: navigationTimeout), "Tab bar should remain after navigating to Tasks")

        navigateToContractors()
        XCTAssertTrue(app.tabBars.firstMatch.waitForExistence(timeout: navigationTimeout), "Tab bar should remain after navigating to Contractors")

        navigateToDocuments()
        XCTAssertTrue(app.tabBars.firstMatch.waitForExistence(timeout: navigationTimeout), "Tab bar should remain after navigating to Documents")

        navigateToResidences()
        XCTAssertTrue(app.tabBars.firstMatch.waitForExistence(timeout: navigationTimeout), "Tab bar should remain after navigating to Residences")
    }
}
