use std::net::IpAddr;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum OverlayError {
#[error("Overlay transport not available: {0}")]
TransportNotAvailable(String),
#[error("Transport command failed: {0}")]
TransportCommand(String),
#[error("Boringtun device error: {0}")]
BoringtunDevice(String),
#[error("Invalid CIDR notation: {0}")]
InvalidCidr(String),
#[error("No available IP addresses in CIDR range")]
NoAvailableIps,
#[error("IP address {0} is already allocated")]
IpAlreadyAllocated(IpAddr),
#[error("IP address {0} is not within CIDR range {1}")]
IpNotInRange(IpAddr, String),
#[error("Overlay interface '{0}' already exists")]
InterfaceExists(String),
#[error("Overlay interface '{0}' not found")]
InterfaceNotFound(String),
#[error("Peer with public key '{0}' not found")]
PeerNotFound(String),
#[error("Peer at {ip} is unreachable: {reason}")]
PeerUnreachable { ip: IpAddr, reason: String },
#[error("Configuration error: {0}")]
Config(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("Overlay network already initialized at {0}")]
AlreadyInitialized(String),
#[error("Overlay network not initialized. Run init_leader or join first")]
NotInitialized,
#[error("Permission denied: {0}. This operation typically requires root privileges")]
PermissionDenied(String),
#[error("Operation timed out: {0}")]
Timeout(String),
#[error("Invalid key format: {0}")]
InvalidKey(String),
#[error("Network configuration error: {0}")]
NetworkConfig(String),
#[error("DNS error: {0}")]
Dns(String),
#[error("STUN discovery failed: {0}")]
StunDiscovery(String),
#[error("Hole punch failed for peer {peer}: {reason}")]
HolePunchFailed { peer: String, reason: String },
#[error("TURN relay error: {0}")]
TurnRelay(String),
#[error("NAT traversal failed for peer {peer}: exhausted all candidates")]
NatTraversalFailed { peer: String },
#[error("No STUN servers configured")]
NoStunServers,
}
pub type Result<T> = std::result::Result<T, OverlayError>;