import Foundation

/// How sync bytes move between the Mac and a phone (SYNC_PROTOCOL §3) — the transport named
/// in a pairing QR and remembered by the phone for reconnects. Everything above it (Noise,
/// frames, messages) is identical across cases.
///
/// On the wire this travels as its raw string inside optional fields, so unknown future
/// values degrade to "unsupported", not decode failures.
public enum SyncTransportHint: String, Sendable, Codable, CaseIterable {
    /// Same-network TCP, discovered over Bonjour or an explicit QR host:port hint.
    case lan
    /// The user's tailnet: both devices run an embedded tsnet node (NucleicTailnet) and the
    /// phone dials the Mac's tailnet IP. Works from anywhere the tailnet reaches.
    case tailnet
    /// The Covalence Relay (SYNC_PROTOCOL §3.2): a Cloudflare Worker room the host and
    /// its devices all dial out to (`RelayFrameChannel` / the host's room listener). The
    /// zero-config fallback when no direct path exists; E2EE-opaque to the relay.
    case relay
    /// A hole-punched peer-to-peer path (Covalence direct, SYNC_PROTOCOL §3.3): a relay
    /// session that upgraded to a direct QUIC connection between the peers. A *runtime*
    /// state only — never written to `nucleic.sync.transports`, never a pairing-QR hint;
    /// the enabled-method that produces it is `.relay` (the Covalence toggle).
    case direct

    /// Short user-facing name ("Connected · Direct (LAN)", the Settings picker, …). LAN is a
    /// same-network *direct* path, so it reads "Direct (LAN)" — parallel to the hole-punched
    /// "Direct (STUN)" (SYNC_PROTOCOL §3.3).
    public var label: String {
        switch self {
        case .lan: "Direct (LAN)"
        case .tailnet: "Tailnet"
        case .relay: "Relay"
        case .direct: "Direct"
        }
    }
}
