//! UDP throughput measurement

use std::time::Duration;

use super::super::error::ProfilingError;
use super::iperf::{IperfClient, IperfConfig};
use super::protocol::Protocol;

/// UDP throughput measurement result
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ThroughputResult {
    pub server: String,
    pub target_bandwidth_bps: u64,
    pub actual_bandwidth_bps: f64,
    pub packet_loss_percent: f64,
}

impl Default for ThroughputResult {
    fn default() -> Self {
        Self {
            server: "unknown".to_string(),
            target_bandwidth_bps: 0,
            actual_bandwidth_bps: 0.0,
            packet_loss_percent: 0.0,
        }
    }
}

/// Test UDP throughput with target bandwidth
pub fn test_udp_throughput(
    server: &str,
    bandwidth_bps: u64,
) -> Result<ThroughputResult, ProfilingError> {
    super::super::logging::log_info(&format!(
        "Testing UDP throughput to {} (target: {} Mbps)",
        server,
        bandwidth_bps / 1_000_000
    ));

    let client = IperfClient::new(server)?;

    let config = IperfConfig::new()
        .with_server(server)
        .with_duration(Duration::from_secs(10))
        .with_protocol(Protocol::Udp)
        .with_bandwidth_limit(bandwidth_bps);

    let result = client.run_iperf_test(&config)?;

    Ok(ThroughputResult {
        server: server.to_string(),
        target_bandwidth_bps: bandwidth_bps,
        actual_bandwidth_bps: result.bandwidth_bps,
        packet_loss_percent: result.packet_loss_percent.unwrap_or(0.0),
    })
}
