import Foundation
import Testing

@testable import NucleicProtocol

/// The relay data path's pure pieces (mesh P2): URL construction against the Worker's
/// routes, the presence control frame, and the `relayMembership` wire message — the bits a
/// live relay would punish us for getting subtly wrong.
@Suite struct RelayTransportTests {
    private func roundTrip<T: Codable & Equatable>(_ value: T) throws -> T {
        try CBORDecoder().decode(T.self, from: CBOREncoder().encode(value))
    }

    // MARK: - RelayAPI

    @Test func webSocketURLSwapsSchemeAndPinsPath() {
        let wss = RelayAPI.webSocketURL(base: RelayAPI.defaultBaseURL, connectionToken: "tok.sig")
        #expect(wss.absoluteString == "wss://relay.nucleic.blakeslee.xyz/relay?t=tok.sig")
        // Dev override on plain http (wrangler dev) becomes ws, and any path on the base is
        // replaced — the Worker serves /relay at the root.
        let ws = RelayAPI.webSocketURL(
            base: URL(string: "http://localhost:8787/ignored")!, connectionToken: "t")
        #expect(ws.absoluteString == "ws://localhost:8787/relay?t=t")
    }

    @Test func baseURLPrefersOverride() {
        #expect(RelayAPI.baseURL(nil) == RelayAPI.defaultBaseURL)
        #expect(RelayAPI.baseURL("https://edge.example.com").host == "edge.example.com")
        #expect(RelayAPI.baseURL("") == RelayAPI.defaultBaseURL) // empty string isn't a URL override
    }

    // MARK: - Presence (room.ts broadcastPresence)

    @Test func presenceParsesPeersAndHostFlag() {
        let hosted = RelayPresence.parse(
            #"{"t":"presence","peers":[{"deviceId":"h","role":"host"},{"deviceId":"p","role":"client"}]}"#)
        #expect(hosted?.hasHost == true)
        #expect(hosted?.peers.count == 2)

        let hostless = RelayPresence.parse(#"{"t":"presence","peers":[{"deviceId":"p","role":"client"}]}"#)
        #expect(hostless?.hasHost == false)
    }

    @Test func presenceIgnoresOtherControlFrames() {
        #expect(RelayPresence.parse(#"{"t":"wake","deviceId":"p"}"#) == nil)
        #expect(RelayPresence.parse("not json") == nil)
    }

    // MARK: - relayMembership wire message

    @Test func relayMembershipRoundTrips() throws {
        let membership = WireRelayMembership(
            roomID: "a1b2", token: "payload.sig", url: "https://edge.example.com", exp: 1_780_000_000)
        let decoded = try roundTrip(HostMsg.relayMembership(membership))
        #expect(decoded == .relayMembership(membership))
    }

    @Test func relayMembershipOptionalsDefaultNil() throws {
        let minimal = WireRelayMembership(roomID: "r", token: "t")
        let decoded = try roundTrip(minimal)
        #expect(decoded.url == nil)
        #expect(decoded.exp == nil)
    }
}
