//
// ProtocolFlowTests.swift — T-iOS-16 测试 1-2：基本协议流程（吸收 spike②）
//
//   1. attach(null) → attached → input "echo hi\r" → output 含 "hi"
//      （附加强断言 RUN:42：证明命令确被 shell 执行，而不是只看到输入回显）
//   2. resize(120,40) → `stty size` 输出 "40 120"；边界 resize 1/1000 各一发，
//      以 stty 实测尺寸生效证明"被接受"（服务器对非法 resize 是静默丢弃，
//      src/protocol.ts:113-115 —— 只有尺寸真变了才证明帧被采纳），且连接存活。
//
// 客户端帧一律 MessageCodec 编码、服务器帧一律 MessageCodec 解码 —— 本 suite
// 同时是冻结契约与真服务器之间的防漂移闸门（plan §9）。

import Foundation
import Testing
import WireProtocol

@Suite("T-iOS-16 协议流程(真服务器)", .serialized, .timeLimit(.minutes(5)))
struct ProtocolFlowTests {

    @Test("attach(null)→attached(101);echo hi → output 含 hi 且命令确被执行")
    func attachEchoRoundtrip() async throws {
        // Arrange
        let server = try await ServerHarness.shared.server()
        let client = WSTestClient(server: server, origin: server.origin)
        defer { client.close() }

        // Act: attach(null) → attached(spike② 阳性对照:自定义 Origin 升级 101)
        let sessionId = try await attachAndAwaitAttached(client: client, sessionId: nil)
        #expect(client.handshakeStatusCode == 101,
                "升级应 101,实际 \(String(describing: client.handshakeStatusCode))")

        var reader = TranscriptReader(client: client)
        try await client.send(shellCommand("echo hi"))
        try await reader.awaitContains("hi")

        // 强断言:$((6*7)) 只有 shell 真执行才会变成 42(回显里只有字面量表达式)。
        try await client.send(shellCommand("echo \"RUN:$((6*7))\""))
        try await reader.awaitContains("RUN:42")

        // Cleanup
        client.close()
        await killSessionBestEffort(server: server, id: sessionId)
    }

    @Test("resize(120,40) → stty size = 40 120;边界 1/1000 均被采纳且连接存活")
    func resizeTakesEffectIncludingBoundaries() async throws {
        // Arrange
        let server = try await ServerHarness.shared.server()
        let client = WSTestClient(server: server, origin: server.origin)
        defer { client.close() }
        let sessionId = try await attachAndAwaitAttached(client: client, sessionId: nil)
        var reader = TranscriptReader(client: client)

        // Act + Assert: 常规尺寸(任务字面用例)。SZ: 哨兵防止把输入回显误判成输出
        //（回显里是字面量 $(stty size),只有命令执行结果才含 "SZ:<rows> <cols>"）。
        try await client.send(.resize(cols: 120, rows: 40))
        try await client.send(shellCommand("echo \"SZ:$(stty size)\""))
        try await reader.awaitContains("SZ:40 120")

        // 边界下限:1×1 被采纳(stty 实测 1 1),连接未断。
        try await client.send(.resize(cols: 1, rows: 1))
        try await client.send(shellCommand("echo \"SZ:$(stty size)\""))
        try await reader.awaitContains("SZ:1 1")

        // 边界上限:1000×1000 被采纳,连接未断。
        try await client.send(.resize(cols: 1000, rows: 1000))
        try await client.send(shellCommand("echo \"SZ:$(stty size)\""))
        try await reader.awaitContains("SZ:1000 1000")

        // Cleanup
        client.close()
        await killSessionBestEffort(server: server, id: sessionId)
    }
}
