//! Rhai bindings for network profiling functions

use super::super::rhai_error_handling::handle_optional_result;
use rhai::Engine;

// Wrapper functions for cleaner registration
fn measure_bandwidth(server: &str, duration_sec: i64) -> super::bandwidth::BandwidthResult {
    use std::time::Duration;
    handle_optional_result(
        super::bandwidth::measure_bandwidth(server, Duration::from_secs(duration_sec as u64)),
        || super::bandwidth::BandwidthResult::default(),
        "Bandwidth measurement",
    )
}

fn measure_bandwidth_upload(server: &str, duration_sec: i64) -> super::bandwidth::BandwidthResult {
    use std::time::Duration;
    handle_optional_result(
        super::bandwidth::measure_bandwidth_upload(
            server,
            Duration::from_secs(duration_sec as u64),
        ),
        || super::bandwidth::BandwidthResult::default(),
        "Upload bandwidth measurement",
    )
}

fn measure_bandwidth_download(
    server: &str,
    duration_sec: i64,
) -> super::bandwidth::BandwidthResult {
    use std::time::Duration;
    handle_optional_result(
        super::bandwidth::measure_bandwidth_download(
            server,
            Duration::from_secs(duration_sec as u64),
        ),
        || super::bandwidth::BandwidthResult::default(),
        "Download bandwidth measurement",
    )
}

fn measure_latency(host: &str, count: i64) -> super::latency::LatencyResult {
    handle_optional_result(
        super::latency::measure_latency(host, count as u32),
        || super::latency::LatencyResult::default(),
        "Latency measurement",
    )
}

fn run_jitter_test(server: &str) -> super::jitter::JitterResult {
    handle_optional_result(
        super::jitter::run_jitter_test(server),
        || super::jitter::JitterResult::default(),
        "Jitter test",
    )
}

fn test_udp_throughput(server: &str, bandwidth_bps: i64) -> super::throughput::ThroughputResult {
    handle_optional_result(
        super::throughput::test_udp_throughput(server, bandwidth_bps as u64),
        || super::throughput::ThroughputResult::default(),
        "UDP throughput test",
    )
}

/// Register network profiling module with Rhai engine
pub fn register_network_module(engine: &mut Engine) -> Result<(), Box<rhai::EvalAltResult>> {
    // Register LatencyResult type and its getters
    engine.register_type::<super::latency::LatencyResult>();
    engine.register_get("host", |result: &mut super::latency::LatencyResult| {
        result.host.clone()
    });
    engine.register_get("min_ms", |result: &mut super::latency::LatencyResult| {
        result.min_ms
    });
    engine.register_get("max_ms", |result: &mut super::latency::LatencyResult| {
        result.max_ms
    });
    engine.register_get("avg_ms", |result: &mut super::latency::LatencyResult| {
        result.avg_ms
    });
    engine.register_get("stddev_ms", |result: &mut super::latency::LatencyResult| {
        result.stddev_ms
    });
    engine.register_get(
        "packet_loss_percent",
        |result: &mut super::latency::LatencyResult| result.packet_loss_percent,
    );
    engine.register_get("samples", |result: &mut super::latency::LatencyResult| {
        result.samples as i64
    });

    // Register BandwidthResult type and its getters
    engine.register_type::<super::bandwidth::BandwidthResult>();
    engine.register_get(
        "upload_bps",
        |result: &mut super::bandwidth::BandwidthResult| result.upload_bps,
    );
    engine.register_get(
        "download_bps",
        |result: &mut super::bandwidth::BandwidthResult| result.download_bps,
    );
    engine.register_get(
        "server",
        |result: &mut super::bandwidth::BandwidthResult| result.server.clone(),
    );
    engine.register_get(
        "duration_sec",
        |result: &mut super::bandwidth::BandwidthResult| result.duration.as_secs() as i64,
    );
    // Convenience getters for Mbps (more common unit)
    engine.register_get(
        "upload_mbps",
        |result: &mut super::bandwidth::BandwidthResult| result.upload_bps / 1_000_000.0,
    );
    engine.register_get(
        "download_mbps",
        |result: &mut super::bandwidth::BandwidthResult| result.download_bps / 1_000_000.0,
    );

    // Register IperfResult type and its getters
    engine.register_type_with_name::<super::IperfResult>("IperfResult");
    engine.register_get("bandwidth_bps", |result: &mut super::IperfResult| {
        result.bandwidth_bps
    });
    engine.register_get("retransmits", |result: &mut super::IperfResult| {
        result.retransmits
    });
    engine.register_get("jitter_ms", |result: &mut super::IperfResult| {
        result.jitter_ms
    });
    engine.register_get("packet_loss_percent", |result: &mut super::IperfResult| {
        result.packet_loss_percent
    });
    engine.register_get("duration", |result: &mut super::IperfResult| {
        result.duration
    });

    // Register JitterResult type and its getters
    engine.register_type_with_name::<super::jitter::JitterResult>("JitterResult");
    engine.register_get(
        "jitter_server",
        |result: &mut super::jitter::JitterResult| result.server.clone(),
    );
    engine.register_get("jitter_ms", |result: &mut super::jitter::JitterResult| {
        result.jitter_ms
    });
    engine.register_get(
        "jitter_min_latency_ms",
        |result: &mut super::jitter::JitterResult| result.min_latency_ms,
    );
    engine.register_get(
        "jitter_max_latency_ms",
        |result: &mut super::jitter::JitterResult| result.max_latency_ms,
    );

    // Register ThroughputResult type and its getters
    engine.register_type::<super::throughput::ThroughputResult>();
    engine.register_get(
        "throughput_server",
        |result: &mut super::throughput::ThroughputResult| result.server.clone(),
    );
    engine.register_get(
        "target_bandwidth_bps",
        |result: &mut super::throughput::ThroughputResult| result.target_bandwidth_bps as i64,
    );
    engine.register_get(
        "actual_bandwidth_bps",
        |result: &mut super::throughput::ThroughputResult| result.actual_bandwidth_bps,
    );
    engine.register_get(
        "throughput_packet_loss_percent",
        |result: &mut super::throughput::ThroughputResult| result.packet_loss_percent,
    );

    // Register network functions with wrapper functions
    engine.register_fn("measure_bandwidth", measure_bandwidth);
    engine.register_fn("measure_bandwidth_upload", measure_bandwidth_upload);
    engine.register_fn("measure_bandwidth_download", measure_bandwidth_download);
    engine.register_fn("measure_latency", measure_latency);
    engine.register_fn("run_jitter_test", run_jitter_test);
    engine.register_fn("test_udp_throughput", test_udp_throughput);

    // Register parameterized benchmark functions
    engine.register_fn(
        "benchmark_network_bandwidth",
        |server: &str, duration_sec: i64| -> super::bandwidth::BandwidthResult {
            super::benchmark_network_bandwidth(server, duration_sec).unwrap_or_else(|_| {
                log::error!("Network bandwidth benchmark failed");
                super::bandwidth::BandwidthResult {
                    upload_bps: 0.0,
                    download_bps: 0.0,
                    server: server.to_string(),
                    duration: std::time::Duration::from_secs(duration_sec as u64),
                }
            })
        },
    );

    engine.register_fn(
        "benchmark_network_latency",
        |host: &str, count: i64| -> super::latency::LatencyResult {
            super::benchmark_network_latency(host, count).unwrap_or_else(|_| {
                log::error!("Network latency benchmark failed");
                super::latency::LatencyResult {
                    host: host.to_string(),
                    min_ms: 0.0,
                    max_ms: 0.0,
                    avg_ms: 0.0,
                    stddev_ms: 0.0,
                    packet_loss_percent: 0.0,
                    samples: count as u32,
                }
            })
        },
    );

    engine.register_fn(
        "benchmark_network_jitter",
        |server: &str| -> super::jitter::JitterResult {
            super::benchmark_network_jitter(server).unwrap_or_else(|_| {
                log::error!("Network jitter benchmark failed");
                super::jitter::JitterResult {
                    server: server.to_string(),
                    jitter_ms: 0.0,
                    min_latency_ms: 0.0,
                    max_latency_ms: 0.0,
                }
            })
        },
    );

    engine.register_fn(
        "benchmark_network_udp_throughput",
        |server: &str, bandwidth_bps: i64| -> super::throughput::ThroughputResult {
            super::benchmark_network_udp_throughput(server, bandwidth_bps).unwrap_or_else(|_| {
                log::error!("Network UDP throughput benchmark failed");
                super::throughput::ThroughputResult {
                    server: server.to_string(),
                    target_bandwidth_bps: bandwidth_bps as u64,
                    actual_bandwidth_bps: 0.0,
                    packet_loss_percent: 0.0,
                }
            })
        },
    );

    Ok(())
}
