import APIClient
import Foundation
import HostRegistry
import SessionCore
import TestSupport
import Testing
import WireProtocol
@testable import WebTerm

/// T-iOS-26 · "在此仓库开新会话" 的接线证明：`TerminalSessionController` 以
/// `spawnCwd` + `bootstrapInput` 启动时，线上帧序 = `attach(null, cwd)` →
/// `input("claude\r")`（engine 的 attach-first 队列语义保证 bootstrap 绝不
/// 先于 attach 出线）；带 sessionId 的常规打开则既无 cwd 也无 bootstrap。
///
/// 真 `SessionEngine` over `FakeTransport`（零真实等待）：帧断言经
/// `openTask` + `waitUntilProcessed` 双屏障（open+send 已提交 ∧ attach
/// 握手已完成 → 帧必已落地）。
@MainActor
@Suite("ProjectOpenWiring")
struct ProjectOpenWiringTests {
    private struct Fixture {
        let transport: FakeTransport
        let host: HostRegistry.Host
        let environment: AppEnvironment
    }

    private func makeFixture() throws -> Fixture {
        let baseURL = try #require(URL(string: "http://192.168.1.5:3000"))
        let endpoint = try #require(HostEndpoint(baseURL: baseURL))
        let transport = FakeTransport()
        let defaults = try #require(UserDefaults(suiteName: "ProjectOpenWiringTests"))
        return Fixture(
            transport: transport,
            host: HostRegistry.Host(id: UUID(), name: "书房 Mac", endpoint: endpoint),
            environment: AppEnvironment(
                hostStore: InMemoryHostStore(),
                lastSessionStore: UserDefaultsLastSessionStore(defaults: defaults),
                http: FakeHTTPTransport(),
                termTransport: transport,
                probe: { _ in .failure(.timeout) }
            )
        )
    }

    /// 双屏障：controller 的 open+bootstrap Task 完成（send 已提交/入队）∧
    /// attach 握手完成（.connecting/.connected 已到 VM → 队列已冲刷）。
    private func awaitAttachSettled(_ controller: TerminalSessionController) async {
        await controller.openTask?.value
        await controller.terminalViewModel.waitUntilProcessed(eventCount: 2)
    }

    @Test("spawn 变体：帧序 = attach(null, cwd) → input(claude\\r)")
    func spawnSendsAttachWithCwdThenBootstrapInput() async throws {
        let fixture = try makeFixture()
        let controller = TerminalSessionController(
            host: fixture.host, sessionId: nil, environment: fixture.environment,
            onPendingChanged: { _, _ in },
            spawnCwd: "/repos/api",
            bootstrapInput: ProjectLaunch.claudeBootstrapInput
        )

        controller.start()
        await awaitAttachSettled(controller)

        let frames = await fixture.transport.sentFrames
        #expect(frames == [
            MessageCodec.encode(.attach(sessionId: nil, cwd: "/repos/api")),
            MessageCodec.encode(.input(data: ProjectLaunch.claudeBootstrapInput)),
        ])
        controller.teardown()
    }

    @Test("常规打开（带 sessionId）：只有 attach，无 cwd、无 bootstrap")
    func plainOpenSendsBareAttach() async throws {
        let fixture = try makeFixture()
        let sessionId = UUID()
        let controller = TerminalSessionController(
            host: fixture.host, sessionId: sessionId,
            environment: fixture.environment,
            onPendingChanged: { _, _ in }
        )

        controller.start()
        await awaitAttachSettled(controller)

        let frames = await fixture.transport.sentFrames
        #expect(frames == [MessageCodec.encode(.attach(sessionId: sessionId, cwd: nil))])
        controller.teardown()
    }
}
