//! Virtual network interface (TUN/TAP) abstraction

use bytes::Bytes;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum TunError {
    #[error("failed to create interface: {0}")]
    Create(String),
    #[error("io error: {0}")]
    Io(#[from] std::io::Error),
    #[error("interface not ready")]
    NotReady,
}

/// TUN device configuration
#[derive(Debug, Clone)]
pub struct TunConfig {
    pub name: String,
    pub address: [u8; 4],
    pub netmask: [u8; 4],
    pub mtu: u16,
}

impl Default for TunConfig {
    fn default() -> Self {
        Self {
            name: "ostp0".into(),
            address: [10, 0, 0, 1],
            netmask: [255, 255, 255, 0],
            mtu: 1400,
        }
    }
}

/// Abstract TUN device trait
#[async_trait::async_trait]
pub trait TunDevice: Send + Sync {
    async fn read(&self) -> Result<Bytes, TunError>;
    async fn write(&self, data: &[u8]) -> Result<usize, TunError>;
    fn mtu(&self) -> u16;
}

/// Placeholder TUN implementation (platform-specific impl needed)
pub struct DummyTun {
    config: TunConfig,
}

impl DummyTun {
    pub fn new(config: TunConfig) -> Self {
        Self { config }
    }
}

#[async_trait::async_trait]
impl TunDevice for DummyTun {
    async fn read(&self) -> Result<Bytes, TunError> {
        // Platform-specific: use wintun on Windows, tun-tap on Linux
        Err(TunError::NotReady)
    }

    async fn write(&self, _data: &[u8]) -> Result<usize, TunError> {
        Err(TunError::NotReady)
    }

    fn mtu(&self) -> u16 {
        self.config.mtu
    }
}

/// IP packet routing helper
pub struct Router {
    default_gateway: [u8; 4],
}

impl Router {
    pub fn new(gateway: [u8; 4]) -> Self {
        Self {
            default_gateway: gateway,
        }
    }

    /// Check if IP should be tunneled
    pub fn should_tunnel(&self, dest_ip: &[u8; 4]) -> bool {
        // Don't tunnel local/private ranges by default
        !matches!(
            dest_ip,
            [10, ..] | [127, ..] | [192, 168, ..] | [172, 16..=31, ..]
        )
    }

    pub fn gateway(&self) -> [u8; 4] {
        self.default_gateway
    }
}
