import Foundation
import Testing
import WireProtocol
@testable import TestSupport

@Suite("FakeTransport")
struct FakeTransportTests {
    @Test("scripts connect failures, delivers injected frames, records sends and closes")
    func scriptsFailuresDeliversFramesAndRecordsTraffic() async throws {
        // Arrange
        let transport = FakeTransport()
        let baseURL = try #require(URL(string: "http://192.168.1.5:3000"))
        let endpoint = try #require(HostEndpoint(baseURL: baseURL))
        let attachFrame = #"{"type":"attach","sessionId":null}"#

        // Act + Assert: a scripted failure makes the next connect throw it.
        await transport.scriptConnectFailure()
        await #expect(throws: FakeTransportError.scriptedConnectFailure) {
            _ = try await transport.connect(to: endpoint)
        }

        // Act: connect for real, send one frame, inject one frame, close cleanly.
        let connection = try await transport.connect(to: endpoint)
        try await connection.send(attachFrame)
        await transport.emit(frame: "server-frame-1")
        await transport.finishFrames()

        var received: [String] = []
        for try await frame in connection.frames {
            received.append(frame)
        }
        await connection.close()

        // Assert: injected frames arrived in order and ended with a clean finish.
        #expect(received == ["server-frame-1"])
        // Assert: the double recorded everything the client did.
        #expect(await transport.sentFrames == [attachFrame])
        #expect(await transport.closeCallCount == 1)
        #expect(await transport.connectAttempts == [endpoint, endpoint])
    }
}
