import Foundation
import Testing
import TestSupport
import WireProtocol
@testable import SessionCore

/// T-iOS-10 · SessionEngine actor (plan §3.2 / §7).
/// Connection lifecycle, attach-first framing, reconnect backoff, gate
/// sequencing, away digest, and terminal failure states — all against
/// TestSupport.FakeTransport + FakeClock: zero real waits, zero network.
@Suite("SessionEngine")
struct SessionEngineTests {
    // MARK: - Server-side frame fixtures (untrusted wire input, hand-built JSON)

    private enum ServerFrames {
        static func attached(_ id: UUID) -> String {
            #"{"type":"attached","sessionId":"\#(id.uuidString.lowercased())"}"#
        }

        static func output(_ data: String) -> String {
            #"{"type":"output","data":"\#(data)"}"#
        }

        static func exit(code: Int, reason: String) -> String {
            #"{"type":"exit","code":\#(code),"reason":"\#(reason)"}"#
        }

        static func status(pending: Bool, gate: String? = nil, detail: String? = nil) -> String {
            var fields = ["\"type\":\"status\"", "\"status\":\"working\"", "\"pending\":\(pending)"]
            if let gate { fields.append("\"gate\":\"\(gate)\"") }
            if let detail { fields.append("\"detail\":\"\(detail)\"") }
            return "{\(fields.joined(separator: ","))}"
        }
    }

    /// Records `eventsSource` calls and serves a scripted timeline response.
    private actor TimelineRecorder {
        private(set) var requestedIds: [UUID] = []
        private let response: [TimelineEvent]

        init(response: [TimelineEvent]) {
            self.response = response
        }

        func fetch(_ id: UUID) -> [TimelineEvent] {
            requestedIds.append(id)
            return response
        }
    }

    // MARK: - Harness

    /// One engine + fakes + a single events iterator (the stream's one consumer).
    private final class Harness {
        let transport = FakeTransport()
        let clock = FakeClock()
        let engine: SessionEngine
        private var iterator: AsyncStream<SessionEvent>.AsyncIterator

        init(
            eventsSource: @escaping @Sendable (UUID) async throws -> [TimelineEvent] = { _ in [] }
        ) throws {
            let baseURL = try #require(URL(string: "http://192.168.1.5:3000"))
            let endpoint = try #require(HostEndpoint(baseURL: baseURL))
            engine = SessionEngine(
                transport: transport, clock: clock, endpoint: endpoint,
                eventsSource: eventsSource
            )
            iterator = engine.events.makeAsyncIterator()
        }

        func next() async -> SessionEvent? {
            await iterator.next()
        }

        /// Standard preamble: open → .connecting → .connected, then the server
        /// confirms the attach and the engine adopts `id`.
        func openAndAdopt(sessionId: UUID? = nil, adopting id: UUID) async {
            await engine.open(sessionId: sessionId, cwd: nil)
            #expect(await next() == .connection(.connecting))
            #expect(await next() == .connection(.connected))
            await transport.emit(frame: ServerFrames.attached(id))
            #expect(await next() == .adopted(sessionId: id))
        }

        /// Frames the client sent on connection `index` (nil if none exists).
        func frames(onConnection index: Int) async -> [String]? {
            let byConnection = await transport.sentFramesByConnection
            guard byConnection.indices.contains(index) else { return nil }
            return byConnection[index]
        }
    }

    // MARK: - Attach-first framing

    @Test("open() sends attach as the very first frame; pre-open sends queue behind it in order")
    func attachIsFirstFrameAndEarlierSendsQueueBehindIt() async throws {
        // Arrange
        let harness = try Harness()
        // Act: user input arrives BEFORE open (must never precede attach).
        await harness.engine.send(.input(data: "queued-before-open"))
        await harness.engine.open(sessionId: nil, cwd: nil)
        #expect(await harness.next() == .connection(.connecting))
        #expect(await harness.next() == .connection(.connected))

        // Assert: first frame is attach(null), queued input follows, no resize
        // (no dims are known yet — server spawned 80x24, src/server.ts:714-717).
        let frames = try #require(await harness.frames(onConnection: 0))
        #expect(frames == [
            MessageCodec.encode(.attach(sessionId: nil, cwd: nil)),
            MessageCodec.encode(.input(data: "queued-before-open")),
        ])
    }

    @Test("open() forwards a valid absolute cwd and drops an invalid relative one")
    func openForwardsValidCwdAndDropsInvalidCwd() async throws {
        // Arrange / Act: valid absolute cwd.
        let withCwd = try Harness()
        await withCwd.engine.open(sessionId: nil, cwd: "/Users/dev/proj")
        #expect(await withCwd.next() == .connection(.connecting))
        #expect(await withCwd.next() == .connection(.connected))

        // Assert
        let cwdFrames = try #require(await withCwd.frames(onConnection: 0))
        #expect(cwdFrames.first == MessageCodec.encode(.attach(sessionId: nil, cwd: "/Users/dev/proj")))

        // Act: relative cwd would make the server DROP the whole attach frame
        // (src/protocol.ts:142-149) — the engine must strip it, not send it.
        let withBadCwd = try Harness()
        await withBadCwd.engine.open(sessionId: nil, cwd: "relative/path")
        #expect(await withBadCwd.next() == .connection(.connecting))
        #expect(await withBadCwd.next() == .connection(.connected))

        // Assert
        let strippedFrames = try #require(await withBadCwd.frames(onConnection: 0))
        #expect(strippedFrames.first == MessageCodec.encode(.attach(sessionId: nil, cwd: nil)))
    }

    @Test("open() with a non-v4 UUID attaches null instead of a frame the server would discard")
    func openWithNonV4SessionIdAttachesNull() async throws {
        // Arrange: version nibble '1' — fails the server's SESSION_ID_RE, so the
        // server would silently drop the attach and the connection would hang.
        let nonV4 = try #require(UUID(uuidString: "12345678-1234-1234-1234-123456789abc"))
        let harness = try Harness()

        // Act
        await harness.engine.open(sessionId: nonV4, cwd: nil)
        #expect(await harness.next() == .connection(.connecting))
        #expect(await harness.next() == .connection(.connected))

        // Assert
        let frames = try #require(await harness.frames(onConnection: 0))
        #expect(frames.first == MessageCodec.encode(.attach(sessionId: nil, cwd: nil)))
    }

    // MARK: - Adoption

    @Test("attached frame emits adopted; a server-issued NEW id replaces the requested one on re-attach")
    func adoptsServerIssuedIdAndReattachesWithIt() async throws {
        // Arrange: ask for an id the server does not know — it creates a fresh
        // session and returns a NEW id (src/session/manager.ts:166-173).
        let requestedId = UUID()
        let serverIssuedId = UUID()
        let harness = try Harness()

        // Act
        await harness.engine.open(sessionId: requestedId, cwd: nil)
        #expect(await harness.next() == .connection(.connecting))
        #expect(await harness.next() == .connection(.connected))
        await harness.transport.emit(frame: ServerFrames.attached(serverIssuedId))

        // Assert: adopted carries the SERVER's id.
        #expect(await harness.next() == .adopted(sessionId: serverIssuedId))
        let firstFrames = try #require(await harness.frames(onConnection: 0))
        #expect(firstFrames.first == MessageCodec.encode(.attach(sessionId: requestedId, cwd: nil)))

        // Act: drop the transport, let the backoff timer fire.
        await harness.transport.emitError(FakeTransportError.scriptedConnectFailure)
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)
        harness.clock.advance(by: .seconds(1))
        #expect(await harness.next() == .connection(.connected))

        // Assert: the re-attach uses the ADOPTED id, not the requested one.
        let secondFrames = try #require(await harness.frames(onConnection: 1))
        #expect(secondFrames.first == MessageCodec.encode(.attach(sessionId: serverIssuedId, cwd: nil)))
    }

    // MARK: - Output ordering

    @Test("output frames are delivered in order with none dropped")
    func outputFramesDeliverInOrder() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)

        // Act: replay-then-live shape — three frames in a row.
        await harness.transport.emit(frame: ServerFrames.output("replay"))
        await harness.transport.emit(frame: ServerFrames.output("live-1"))
        await harness.transport.emit(frame: ServerFrames.output("live-2"))

        // Assert
        #expect(await harness.next() == .output("replay"))
        #expect(await harness.next() == .output("live-1"))
        #expect(await harness.next() == .output("live-2"))
    }

    // MARK: - Exit is terminal

    @Test("exit(code:-1) emits exited and never reconnects (spawn failure is terminal)")
    func exitMinusOneIsTerminalWithoutReconnect() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)

        // Act: M4 path — server sends exit(-1, reason) then closes the WS.
        await harness.transport.emit(frame: ServerFrames.exit(code: -1, reason: "spawn failed"))
        await harness.transport.finishFrames()

        // Assert: exited, then a deliberate closed — and the stream FINISHES
        // (no .reconnecting can ever follow).
        #expect(await harness.next() == .exited(code: -1, reason: "spawn failed"))
        #expect(await harness.next() == .connection(.closed))
        #expect(await harness.next() == nil)
        #expect(harness.clock.pendingSleeperCount == 0)
        #expect(await harness.transport.connectAttempts.count == 1)

        // Assert: the engine is inert after exit — sends are dropped, counted.
        await harness.engine.send(.input(data: "too late"))
        #expect(await harness.engine.droppedOutboundFrameCount == 1)
    }

    // MARK: - Reconnect

    @Test("transport error → reconnecting event; clock advance auto-reconnects and re-attaches the SAME session id")
    func disconnectSchedulesBackoffAndReattachesSameId() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)

        // Act: the wire dies; input typed while offline must queue.
        await harness.transport.emitError(FakeTransportError.scriptedConnectFailure)
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)
        await harness.engine.send(.input(data: "typed-offline"))
        harness.clock.advance(by: .seconds(1))

        // Assert: reconnected; attach FIRST (same id), offline input flushed behind it.
        #expect(await harness.next() == .connection(.connected))
        let secondFrames = try #require(await harness.frames(onConnection: 1))
        #expect(secondFrames == [
            MessageCodec.encode(.attach(sessionId: sessionId, cwd: nil)),
            MessageCodec.encode(.input(data: "typed-offline")),
        ])
    }

    @Test("repeated connect failures walk the backoff ladder with rising attempt counts")
    func repeatedConnectFailuresWalkBackoffLadder() async throws {
        // Arrange: the first two connect attempts fail outright.
        let harness = try Harness()
        await harness.transport.scriptConnectFailure()
        await harness.transport.scriptConnectFailure()

        // Act / Assert: 1s then 2s rungs (mirrors public/terminal-session.ts).
        await harness.engine.open(sessionId: nil, cwd: nil)
        #expect(await harness.next() == .connection(.connecting))
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)
        harness.clock.advance(by: .seconds(1))
        #expect(await harness.next() == .connection(.reconnecting(attempt: 2, next: .seconds(2))))
        await harness.clock.waitForSleepers(count: 1)
        harness.clock.advance(by: .seconds(2))
        #expect(await harness.next() == .connection(.connected))
        #expect(await harness.transport.connectAttempts.count == 3)
    }

    // MARK: - Foregrounding (latest-writer-wins sizing)

    @Test("notifyForegrounded while connected sends only a resize — no reconnect")
    func notifyForegroundedWhileConnectedSendsResizeOnly() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)

        // Act
        await harness.engine.notifyForegrounded(dims: (cols: 120, rows: 40))

        // Assert
        let frames = try #require(await harness.frames(onConnection: 0))
        #expect(frames.last == MessageCodec.encode(.resize(cols: 120, rows: 40)))
        #expect(await harness.transport.connectAttempts.count == 1)
    }

    @Test("notifyForegrounded while disconnected reconnects immediately and re-sends dims after attach")
    func notifyForegroundedWhileDisconnectedReconnectsNowWithResize() async throws {
        // Arrange: connected, then the wire dies and the engine parks in backoff.
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)
        await harness.transport.emitError(FakeTransportError.scriptedConnectFailure)
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)

        // Act: foreground — connect NOW, no clock advance at all.
        await harness.engine.notifyForegrounded(dims: (cols: 100, rows: 30))

        // Assert: reconnected without the timer; attach first, then the dims
        // (latest-writer-wins — this device reclaims full-screen).
        #expect(await harness.next() == .connection(.connected))
        let secondFrames = try #require(await harness.frames(onConnection: 1))
        #expect(secondFrames == [
            MessageCodec.encode(.attach(sessionId: sessionId, cwd: nil)),
            MessageCodec.encode(.resize(cols: 100, rows: 30)),
        ])
        #expect(harness.clock.pendingSleeperCount == 0)
    }

    @Test("dims learned from send(.resize) are replayed right after attach on reconnect")
    func lastKnownDimsFromSendResizeReplayOnReattach() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)
        await harness.engine.send(.resize(cols: 90, rows: 30))

        // Act: invalid dims must be dropped, not stored (server would discard).
        await harness.engine.send(.resize(cols: 0, rows: 30))
        await harness.transport.emitError(FakeTransportError.scriptedConnectFailure)
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)
        harness.clock.advance(by: .seconds(1))

        // Assert
        #expect(await harness.next() == .connection(.connected))
        let secondFrames = try #require(await harness.frames(onConnection: 1))
        #expect(secondFrames == [
            MessageCodec.encode(.attach(sessionId: sessionId, cwd: nil)),
            MessageCodec.encode(.resize(cols: 90, rows: 30)),
        ])
        #expect(await harness.engine.droppedOutboundFrameCount == 1)
    }

    // MARK: - Gate sequencing

    @Test("gate rising edge → gate(epoch 1); falling edge → gate(nil); stale approve dropped via canDecide")
    func gateSequencingAndStaleApproveDropped() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)
        let approveFrame = MessageCodec.encode(.approve(mode: nil))

        // Act: approve BEFORE any gate ever rose → dropped.
        await harness.engine.send(.approve(mode: nil))
        #expect(await harness.engine.droppedDecisionCount == 1)

        // Act: rising edge mints epoch 1.
        await harness.transport.emit(frame: ServerFrames.status(pending: true, gate: "tool", detail: "Bash"))
        #expect(await harness.next() == .gate(GateState(kind: .tool, detail: "Bash", epoch: 1)))

        // Act: approve while the gate is held → sent.
        await harness.engine.send(.approve(mode: nil))
        #expect(await harness.transport.sentFrames.filter { $0 == approveFrame }.count == 1)

        // Act: falling edge lifts the gate.
        await harness.transport.emit(frame: ServerFrames.status(pending: false))
        #expect(await harness.next() == .gate(nil))

        // Assert: post-resolution approve/reject are STALE — never sent
        // (GateTracker.canDecide, 防误批新 gate).
        await harness.engine.send(.approve(mode: nil))
        await harness.engine.send(.reject)
        #expect(await harness.transport.sentFrames.filter { $0 == approveFrame }.count == 1)
        #expect(await harness.transport.sentFrames.contains(MessageCodec.encode(.reject)) == false)
        #expect(await harness.engine.droppedDecisionCount == 3)
    }

    @Test("gate decisions are never queued while disconnected — dropped, not replayed")
    func gateDecisionWhileDisconnectedIsDroppedNotQueued() async throws {
        // Arrange: a tool gate is held, then the wire dies.
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)
        await harness.transport.emit(frame: ServerFrames.status(pending: true, gate: "tool"))
        #expect(await harness.next() == .gate(GateState(kind: .tool, detail: nil, epoch: 1)))
        await harness.transport.emitError(FakeTransportError.scriptedConnectFailure)
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)

        // Act: a decision tapped while offline must NOT be queued for later —
        // by reconnect time the gate may be a DIFFERENT one.
        await harness.engine.send(.approve(mode: nil))
        harness.clock.advance(by: .seconds(1))
        #expect(await harness.next() == .connection(.connected))

        // Assert: re-attach flushed no approve.
        let secondFrames = try #require(await harness.frames(onConnection: 1))
        #expect(secondFrames == [MessageCodec.encode(.attach(sessionId: sessionId, cwd: nil))])
        #expect(await harness.engine.droppedDecisionCount == 1)
    }

    // MARK: - Away digest

    @Test("reconnect emits exactly one digest, reduced from eventsSource since the disconnect")
    func reconnectEmitsExactlyOneDigest() async throws {
        // Arrange: one away-window event (far future `at`) and one ancient
        // event (at: 0) that the `since` filter must exclude.
        let sessionId = UUID()
        let awayEvent = TimelineEvent(at: Int.max / 2, class: "tool", toolName: "Bash", label: "ran Bash")
        let staleEvent = TimelineEvent(at: 0, class: "done", toolName: nil, label: "finished")
        let recorder = TimelineRecorder(response: [awayEvent, staleEvent])
        let harness = try Harness(eventsSource: { await recorder.fetch($0) })
        await harness.openAndAdopt(adopting: sessionId)

        // Act: disconnect → backoff → reconnect → server confirms the attach.
        await harness.transport.emitError(FakeTransportError.scriptedConnectFailure)
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)
        harness.clock.advance(by: .seconds(1))
        #expect(await harness.next() == .connection(.connected))
        await harness.transport.emit(frame: ServerFrames.attached(sessionId))
        #expect(await harness.next() == .adopted(sessionId: sessionId))

        // Assert: exactly one digest; the stale event is filtered by `since`.
        let expected = AwayDigest(
            toolRuns: 1, waitingCount: 0, sawDone: false, sawStuck: false,
            recent: [awayEvent]
        )
        #expect(await harness.next() == .digest(expected))
        #expect(await recorder.requestedIds == [sessionId])

        // Assert: no second digest sneaks in ahead of live traffic.
        await harness.transport.emit(frame: ServerFrames.output("after-digest"))
        #expect(await harness.next() == .output("after-digest"))
    }

    @Test("initial connect emits no digest — there was no away window")
    func initialConnectEmitsNoDigest() async throws {
        // Arrange
        let sessionId = UUID()
        let recorder = TimelineRecorder(response: [])
        let harness = try Harness(eventsSource: { await recorder.fetch($0) })

        // Act
        await harness.openAndAdopt(adopting: sessionId)
        await harness.transport.emit(frame: ServerFrames.output("first"))

        // Assert: the event right after adoption is live output, not a digest,
        // and the events source was never consulted.
        #expect(await harness.next() == .output("first"))
        #expect(await recorder.requestedIds.isEmpty)
    }

    // MARK: - Non-retryable failure

    @Test("replayTooLarge → connection(.failed(.replayTooLarge)) and reconnection STOPS")
    func replayTooLargeIsTerminalAndNeverBacksOff() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)

        // Act: the transport classifies EMSGSIZE as the typed error (T-iOS-9).
        await harness.transport.emitError(TermTransportError.replayTooLarge)

        // Assert: explicit terminal failure, stream finished, NO backoff —
        // retrying would deterministically fail forever (plan §1).
        #expect(await harness.next() == .connection(.failed(.replayTooLarge)))
        #expect(await harness.next() == nil)
        #expect(harness.clock.pendingSleeperCount == 0)
        harness.clock.advance(by: .seconds(60))
        #expect(await harness.transport.connectAttempts.count == 1)
    }

    // MARK: - Close

    @Test("close() closes the transport, finishes the events stream, and leaks no tasks")
    func closeClosesTransportAndFinishesEvents() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)

        // Act
        await harness.engine.close()

        // Assert: deliberate detach (PTY keeps running server-side).
        #expect(await harness.transport.closeCallCount == 1)
        #expect(await harness.next() == .connection(.closed))
        await confirmation("events stream finishes after close") { streamFinished in
            while await harness.next() != nil {}
            streamFinished()
        }
        #expect(harness.clock.pendingSleeperCount == 0)

        // Assert: close is idempotent.
        await harness.engine.close()
        #expect(await harness.transport.closeCallCount == 1)
    }

    @Test("close() during backoff cancels the retry timer — no reconnect ever fires")
    func closeDuringBackoffCancelsRetryTimer() async throws {
        // Arrange: parked in the 1s backoff sleep.
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)
        await harness.transport.emitError(FakeTransportError.scriptedConnectFailure)
        #expect(await harness.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        await harness.clock.waitForSleepers(count: 1)

        // Act
        await harness.engine.close()

        // Assert: sleeper cancelled, stream done, and time passing changes nothing.
        #expect(await harness.next() == .connection(.closed))
        #expect(await harness.next() == nil)
        #expect(harness.clock.pendingSleeperCount == 0)
        harness.clock.advance(by: .seconds(60))
        #expect(await harness.transport.connectAttempts.count == 1)
    }

    // MARK: - Untrusted input

    @Test("malformed server frames are dropped and counted; the stream keeps flowing")
    func malformedFramesAreDroppedAndCounted() async throws {
        // Arrange
        let sessionId = UUID()
        let harness = try Harness()
        await harness.openAndAdopt(adopting: sessionId)

        // Act: garbage, unknown type, wrong-typed required field — then a
        // valid frame that must still arrive.
        await harness.transport.emit(frame: "not json at all")
        await harness.transport.emit(frame: #"{"type":"mystery"}"#)
        await harness.transport.emit(frame: #"{"type":"output","data":42}"#)
        await harness.transport.emit(frame: ServerFrames.output("still alive"))

        // Assert
        #expect(await harness.next() == .output("still alive"))
        #expect(await harness.engine.droppedServerFrameCount == 3)
    }

    // MARK: - Ping wiring (internal hook, T-iOS-9 integration)

    /// Pops scripted pong verdicts; answers `true` once the script runs out.
    private actor PongVerdicts {
        private var verdicts: [Bool]

        init(_ verdicts: [Bool]) {
            self.verdicts = verdicts
        }

        func pop() -> Bool {
            verdicts.isEmpty ? true : verdicts.removeFirst()
        }
    }

    private struct ScriptedPinger: ConnectionPinger {
        let verdicts: PongVerdicts

        func ping() async -> Bool {
            await verdicts.pop()
        }
    }

    /// FakeTransport that also exposes the SessionCore-internal ping hook.
    private struct PingableFakeTransport: PingableTermTransport {
        let base: FakeTransport
        let pinger: ScriptedPinger

        func connect(to endpoint: HostEndpoint) async throws -> TransportConnection {
            try await base.connect(to: endpoint)
        }

        func connectPingable(to endpoint: HostEndpoint) async throws
            -> (connection: TransportConnection, pinger: any ConnectionPinger) {
            (try await base.connect(to: endpoint), pinger)
        }
    }

    @Test("pongMissLimit consecutive missed pongs tear the connection down into the reconnect path")
    func missedPongsTriggerReconnect() async throws {
        // Arrange: an engine on a PINGABLE transport whose pongs never arrive.
        let base = FakeTransport()
        let clock = FakeClock()
        let verdicts = PongVerdicts([false, false])
        let transport = PingableFakeTransport(base: base, pinger: ScriptedPinger(verdicts: verdicts))
        let baseURL = try #require(URL(string: "http://192.168.1.5:3000"))
        let endpoint = try #require(HostEndpoint(baseURL: baseURL))
        let engine = SessionEngine(
            transport: transport, clock: clock, endpoint: endpoint,
            eventsSource: { _ in [] }
        )
        var iterator = engine.events.makeAsyncIterator()

        // Act: connect; the ping scheduler parks on the injected clock.
        await engine.open(sessionId: nil, cwd: nil)
        #expect(await iterator.next() == .connection(.connecting))
        #expect(await iterator.next() == .connection(.connected))
        await clock.waitForSleepers(count: 1)
        // Miss #1 — tolerated (pongMissLimit = 2); scheduler re-parks.
        clock.advance(by: Tunables.pingInterval)
        await clock.waitForSleepers(count: 1)
        // Miss #2 — connection declared lost; engine must close it and back off.
        clock.advance(by: Tunables.pingInterval)

        // Assert: the half-dead connection was torn down (close → stream finish)
        // and the normal reconnect path took over. Never "looks connected but dead".
        #expect(await iterator.next() == .connection(.reconnecting(attempt: 1, next: .seconds(1))))
        #expect(await base.closeCallCount == 1)
    }
}
