// BackgroundLifecycleUITests.swift
// T-2.10 — Background lifecycle UI tests.
//
// Launch args used:
//   --uitest                   existing arg: skips live WS, shows placeholder
//   --uitest-with-stub-connection  NEW (T-2.10): impl agent must add handling
//                              in MainTerminalView.initialBootstrap() so that
//                              a stub/in-process connection is established and
//                              the background lifecycle hooks (suspend/resume)
//                              fire and update the status bar. Without this arg
//                              the app uses plain --uitest mode (no connection,
//                              no reconnect status text) and the Reconnecting
//                              assertions below FAIL — which is the intended
//                              failing state for TDD step 1.
//
// Status bar text expected values (T-2.10 impl):
//   • During reconnect window: "Reconnecting…"   (new)
//   • After reconnect settled: "● <sessionId>"   (existing connected text)
//
// Currently MainTerminalView shows "Connecting…" for .connecting state (not
// "Reconnecting…") and --uitest-with-stub-connection is not handled at all.
// All assertions about "Reconnecting…" will therefore FAIL on the TDD branch.

import XCTest

@MainActor
final class BackgroundLifecycleUITests: XCTestCase {

    override func setUpWithError() throws {
        continueAfterFailure = false
    }

    // =========================================================================
    // MARK: 1. Crash-safety smoke test (should PASS — regression guard)
    // =========================================================================

    /// The app must survive a background → foreground transition without
    /// crashing, regardless of connection state.
    func test_backgroundForeground_appDoesNotCrash() throws {
        let app = XCUIApplication()
        // Use --uitest so no real WS is needed; lifecycle hooks still fire.
        app.launchArguments = ["--uitest", "--reset-state"]
        app.launch()

        XCTAssertTrue(app.wait(for: .runningForeground, timeout: 10),
                      "App must reach runningForeground state")

        // Background the app
        XCUIDevice.shared.press(.home)
        // Brief wait in background
        Thread.sleep(forTimeInterval: 0.5)

        // Foreground the app
        app.activate()

        // Verify the app returned to foreground (no crash / hang)
        XCTAssertTrue(app.wait(for: .runningForeground, timeout: 5),
                      "App must return to runningForeground after activate() — crash guard")
    }

    // =========================================================================
    // MARK: 2. Status bar shows "Reconnecting…" after foreground transition
    //
    // FAILS until impl adds:
    //   (a) --uitest-with-stub-connection launch arg handling in
    //       MainTerminalView.initialBootstrap() that creates a stub connection
    //       so lifecycle hooks fire and status text updates.
    //   (b) "Reconnecting…" (not "Connecting…") text in the status bar when
    //       SessionConnection re-enters .connecting after a suspend/resume.
    //   (c) The background lifecycle wiring in MainTerminalView (subscribe to
    //       AppState.lifecycleTransitions, call suspend/resume on the active
    //       connection).
    // =========================================================================

    /// After returning to foreground, the status bar must briefly show
    /// "Reconnecting…" (not just "Connecting…") to indicate this is a
    /// re-connection of an existing session, not a first-time attach.
    ///
    /// FAILS: --uitest-with-stub-connection is not handled → app shows
    ///        "● uitest" (plain --uitest behaviour) → "Reconnecting…" not found.
    func test_statusBar_showsReconnectingAfterForeground() throws {
        let app = XCUIApplication()
        // --uitest-with-stub-connection: impl agent must add this mode.
        // Until then, the app falls back to --uitest behavior ("● uitest").
        app.launchArguments = ["--uitest", "--uitest-with-stub-connection", "--reset-state"]
        app.launch()

        XCTAssertTrue(app.wait(for: .runningForeground, timeout: 10),
                      "App must launch successfully")

        // Background the app
        XCUIDevice.shared.press(.home)
        Thread.sleep(forTimeInterval: 0.5)

        // Foreground the app
        app.activate()

        // After foregrounding, status bar must show "Reconnecting…" briefly.
        // Query by text content — the status bar text element has no accessibility
        // identifier yet. Impl agent should add accessibilityIdentifier
        // "statusbar.connectionStatus" to the connectionStatus Text in StatusBar.swift.
        let reconnectingText = app.staticTexts.matching(
            NSPredicate(format: "label CONTAINS 'Reconnecting'")
        ).firstMatch

        XCTAssertTrue(
            reconnectingText.waitForExistence(timeout: 3.0),
            "T-2.10: Status bar must show 'Reconnecting…' (or similar) text " +
            "during the reconnect window after app foreground. " +
            "MISSING IMPL: (1) add --uitest-with-stub-connection mode, " +
            "(2) update MainTerminalView status wiring for .connecting during resume, " +
            "(3) show 'Reconnecting…' not 'Connecting…' when lastSeq != nil."
        )
    }

    /// After ~2 seconds the status must revert from "Reconnecting…" to the
    /// normal connected indicator ("● <sessionId>" or "● stub").
    ///
    /// FAILS: prerequisite test_statusBar_showsReconnectingAfterForeground
    ///        also fails; continueAfterFailure=false so this test is skipped.
    ///        When the impl is complete, this guard prevents the reconnect
    ///        state from being stuck forever.
    func test_statusBar_recoversFromReconnectingWithin2s() throws {
        let app = XCUIApplication()
        app.launchArguments = ["--uitest", "--uitest-with-stub-connection", "--reset-state"]
        app.launch()

        XCTAssertTrue(app.wait(for: .runningForeground, timeout: 10),
                      "App must launch successfully")

        XCUIDevice.shared.press(.home)
        Thread.sleep(forTimeInterval: 0.5)
        app.activate()

        // First the reconnecting state must appear
        let reconnectingText = app.staticTexts.matching(
            NSPredicate(format: "label CONTAINS 'Reconnecting'")
        ).firstMatch
        XCTAssertTrue(reconnectingText.waitForExistence(timeout: 3.0),
                      "T-2.10: Must see 'Reconnecting…' state first (prerequisite)")

        // Then it must disappear (connected text takes over) within 2 s
        let normalStatus = app.staticTexts.matching(
            NSPredicate(format: "label BEGINSWITH '●'")
        ).firstMatch

        XCTAssertTrue(normalStatus.waitForExistence(timeout: 2.0),
                      "T-2.10: Status bar must revert to '● <sessionId>' within 2 s " +
                      "after the reconnect completes (P-3 acceptance)")
    }

    // =========================================================================
    // MARK: 3. Multiple background/foreground cycles are stable
    //
    // FAILS: same missing impl as above; smoke guards for future regression.
    // =========================================================================

    /// Two consecutive background→foreground cycles must not crash.
    func test_repeatedBackgroundForeground_doesNotCrash() throws {
        let app = XCUIApplication()
        app.launchArguments = ["--uitest", "--reset-state"]
        app.launch()

        XCTAssertTrue(app.wait(for: .runningForeground, timeout: 10))

        for i in 0..<2 {
            XCUIDevice.shared.press(.home)
            Thread.sleep(forTimeInterval: 0.3)
            app.activate()
            XCTAssertTrue(app.wait(for: .runningForeground, timeout: 5),
                          "App must survive bg/fg cycle \(i + 1)")
        }
    }
}
