//! NVIDIA GPU detection via NVML (runtime-loaded).

use crate::types::{GpuDevice, GpuVendor};
use nvml_wrapper::Nvml;

/// Attempt to detect NVIDIA GPUs via NVML.
/// Returns empty Vec if NVML is not available (no NVIDIA driver).
pub fn detect_nvidia() -> Vec<GpuDevice> {
    let nvml = match Nvml::init() {
        Ok(n) => n,
        Err(_) => return Vec::new(),
    };

    let count = match nvml.device_count() {
        Ok(c) => c,
        Err(_) => return Vec::new(),
    };

    let mut devices = Vec::new();
    for i in 0..count {
        let device = match nvml.device_by_index(i) {
            Ok(d) => d,
            Err(_) => continue,
        };

        let name = device.name().unwrap_or_else(|_| format!("NVIDIA GPU {i}"));
        let mem_info = device.memory_info().ok();
        let vram_total_mb = mem_info.as_ref().map_or(0, |m| m.total / (1024 * 1024));
        let vram_free_mb = mem_info.as_ref().map_or(0, |m| m.free / (1024 * 1024));

        let cc = device
            .cuda_compute_capability()
            .ok()
            .map(|cc| format!("{}.{}", cc.major, cc.minor));

        let driver = nvml.sys_driver_version().ok();

        let pci = device
            .pci_info()
            .ok()
            .map(|p| p.bus_id);

        devices.push(GpuDevice {
            name,
            vendor: GpuVendor::Nvidia,
            vram_total_mb,
            vram_free_mb,
            compute_capability: cc,
            driver_version: driver,
            pci_bus_id: pci,
        });
    }

    devices
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_detect_nvidia_returns_vec() {
        // This test works regardless of whether NVIDIA hardware is present.
        // On machines without NVIDIA GPUs, it returns empty vec.
        // On machines with NVIDIA GPUs, it returns populated vec.
        let devices = detect_nvidia();
        // Just verify it doesn't panic and returns a Vec
        let _ = devices.len();
    }
}
