import Foundation
import Testing

@testable import NucleicProtocol

/// Wire round-trips for full-transcript mesh sync (`fetchTranscript` + its holder replies).
@Suite struct TranscriptSyncWireTests {
    private func roundTrip<T: Codable & Equatable>(_ value: T) throws -> T {
        try CBORDecoder().decode(T.self, from: CBOREncoder().encode(value))
    }

    private func event(_ seq: UInt64) -> AgentEvent {
        AgentEvent(
            sessionID: SessionID(rawValue: "s1"), seq: seq, at: Date(timeIntervalSince1970: 1),
            backend: .claudeCode, nativeType: nil,
            kind: .assistantText(TextChunk(messageID: "m", text: "hi \(seq)", isPartial: false)))
    }

    @Test func fetchRequestRoundTrips() throws {
        let msg = ClientMsg.fetchTranscript(TranscriptFetch(
            requestID: "r1", sessionID: SessionID(rawValue: "s1"), afterSeq: 42))
        #expect(try roundTrip(msg) == msg)
    }

    @Test func chunkReplyRoundTrips() throws {
        let msg = HostMsg.transcriptChunk(TranscriptChunk(
            requestID: "r1", sessionID: SessionID(rawValue: "s1"), batchIndex: 0,
            events: [event(1), event(2), event(3)]))
        #expect(try roundTrip(msg) == msg)
    }

    @Test func completeReplyRoundTrips() throws {
        // With header bytes (full fetch)…
        let full = HostMsg.transcriptFetchComplete(TranscriptFetchComplete(
            requestID: "r1", sessionID: SessionID(rawValue: "s1"), throughSeq: 3,
            headerJSON: Data("{\"header\":true}".utf8)))
        #expect(try roundTrip(full) == full)
        // …and without (a top-up).
        let topUp = HostMsg.transcriptFetchComplete(TranscriptFetchComplete(
            requestID: "r1", sessionID: SessionID(rawValue: "s1"), throughSeq: 3))
        #expect(try roundTrip(topUp) == topUp)
    }

    @Test func unavailableReplyRoundTrips() throws {
        let msg = HostMsg.transcriptUnavailable(TranscriptUnavailable(
            requestID: "r1", sessionID: SessionID(rawValue: "s1"), reason: .notHeld))
        #expect(try roundTrip(msg) == msg)
    }

    @Test func capabilityDefaultsFalseForOlderPeer() throws {
        // A welcome that predates the flag (key absent) must decode to `false` so we never send
        // `fetchTranscript` to a peer that would throw on the unknown tag.
        let legacy = WireCapabilities(canModifyToolInput: true, allowAlwaysScopes: [.session])
        #expect(legacy.canSyncTranscripts == false)
        #expect(try roundTrip(legacy).canSyncTranscripts == false)
        // …and a peer that advertises it round-trips true.
        let modern = WireCapabilities(
            canModifyToolInput: true, allowAlwaysScopes: [.session], canSyncTranscripts: true)
        #expect(try roundTrip(modern).canSyncTranscripts == true)
    }
}
