# VM Hypervisor Detection System
#
# Detects available hypervisor capabilities on host system.
# Follows Rule 1 (single purpose) and Rule 2 (explicit types).
# Error handling: do/complete pattern (no try-catch)

export def "detect-hypervisors" []: table {
    """Detect all available hypervisors on the system"""

    let kvm_available = (detect-kvm)
    let libvirt_available = (detect-libvirt)
    let qemu_available = (detect-qemu)
    let docker_available = (detect-docker)

    [
        $kvm_available,
        $libvirt_available,
        $qemu_available,
        $docker_available,
    ] | compact
}

def detect-kvm []: record {
    """Detect KVM kernel module and CPU support"""

    # Check CPU support (vmx=Intel, svm=AMD)
    let cpu_support = (
        open /proc/cpuinfo
        | grep -E "vmx|svm"
        | length
    ) > 0

    if not $cpu_support {
        return null
    }

    # Check if module is loaded
    let module_loaded = (
        lsmod
        | grep "^kvm "
        | length
    ) > 0

    # Check /dev/kvm device
    let device_present = ("/dev/kvm" | path exists)

    {
        name: "kvm"
        available: (if ($module_loaded and $device_present) { "ready" } else { "available" })
        cpu_support: $cpu_support
        module_loaded: $module_loaded
        device_present: $device_present
        description: "Kernel-based Virtual Machine"
    }
}

def detect-libvirt []: record {
    """Detect libvirt daemon"""

    # Check if package is installed (no try-catch)
    let installed = (
        let result = (do { virsh --version -q } | complete)
        $result.exit_code == 0 and (($result.stdout | length) > 0)
    )

    if not $installed {
        return null
    }

    # Check if service is running (no try-catch)
    let running = (
        let result = (do { systemctl is-active --quiet libvirtd } | complete)
        $result.exit_code == 0
    )

    # Check libvirt socket
    let socket_present = ("/var/run/libvirt/libvirt-sock" | path exists)

    {
        name: "libvirt"
        available: (if $running { "ready" } else { "available" })
        installed: $installed
        running: $running
        socket_present: $socket_present
        description: "libvirt virtualization management"
    }
}

def detect-qemu []: record {
    """Detect QEMU emulator"""

    # Check if QEMU is installed (no try-catch)
    let installed = (
        let result = (do { qemu-system-x86_64 --version } | complete)
        $result.exit_code == 0 and (($result.stdout | length) > 0)
    )

    if not $installed {
        return null
    }

    # Get supported architectures
    let archs = [
        "x86_64",
        "i386",
        "aarch64",
        "arm",
    ]

    {
        name: "qemu"
        available: "available"
        installed: $installed
        architectures: $archs
        description: "QEMU machine emulator"
    }
}

def detect-docker []: record {
    """Detect Docker Desktop VM support (macOS/Windows)"""

    # Check if Docker is installed (no try-catch)
    let docker_installed = (
        let result = (do { docker --version } | complete)
        $result.exit_code == 0 and (($result.stdout | length) > 0)
    )

    if not $docker_installed {
        return null
    }

    # Check Docker Desktop (via context) (no try-catch)
    let is_desktop = (
        let result = (do { docker context ls } | complete)
        $result.exit_code == 0 and (($result.stdout | grep "desktop" | length) > 0)
    )

    {
        name: "docker-vm"
        available: (if $is_desktop { "ready" } else { "available" })
        docker_installed: $docker_installed
        is_desktop: $is_desktop
        description: "Docker Desktop VM support"
    }
}

export def "get-primary-hypervisor" []: string {
    """Get the best available hypervisor for VM creation"""

    let hypervisors = (detect-hypervisors)

    # Preference order: libvirt (ready) > kvm (ready) > qemu > docker
    let ready_libvirt = (
        $hypervisors
        | where name == "libvirt" and available == "ready"
        | length
    ) > 0

    let ready_kvm = (
        $hypervisors
        | where name == "kvm" and available == "ready"
        | length
    ) > 0

    let available_qemu = (
        $hypervisors
        | where name == "qemu"
        | length
    ) > 0

    let available_docker = (
        $hypervisors
        | where name == "docker-vm"
        | length
    ) > 0

    if $ready_libvirt {
        "libvirt"
    } else if $ready_kvm {
        "kvm"
    } else if $available_qemu {
        "qemu"
    } else if $available_docker {
        "docker-vm"
    } else {
        error make {msg: "No hypervisors detected on system"}
    }
}

export def "check-vm-capability" [host: string]: record {
    """Check if host can run virtual machines"""

    let hypervisors = (detect-hypervisors)

    {
        host: $host
        can_run_vms: (($hypervisors | length) > 0)
        available_hypervisors: $hypervisors
        primary_backend: (
            # Guard: Ensure at least one hypervisor detected before calling get-primary-hypervisor
            if ($hypervisors | length) > 0 {
                get-primary-hypervisor
            } else {
                "none"
            }
        )
    }
}
