# VM Host Preparation System
#
# Prepares hosts for VM management by installing necessary hypervisors.
# Supports three modes: explicit, automatic, and auto-detect.

# Selective imports (ADR-025 Phase 3 Layer 2).
use lib_provisioning/vm/detector.nu [check-vm-capability]

export def "prepare-host-for-vms" [
    host: string                   # Host identifier ("local" or remote hostname)
    --auto-install                 # Auto-install missing hypervisors
    --check-only                   # Only check, don't modify
]: record {
    """
    Prepare a host for virtual machine management.

    Detects available hypervisors and optionally installs missing ones.

    Examples:
        # Check local host capability
        prepare-host-for-vms "local" --check-only

        # Prepare local host with auto-install
        prepare-host-for-vms "local" --auto-install

        # Check remote host
        prepare-host-for-vms "upcloud-server-01" --check-only
    """

    let capabilities = (check-vm-capability $host)

    if $check_only {
        return $capabilities
    }

    if not $auto_install {
        return $capabilities
    }

    # Auto-install hypervisors
    prepare-host-install $host $capabilities
}

def prepare-host-install [host: string, capabilities: record]: record {
    """Install hypervisors on host"""

    let needs_installation = (
        ($capabilities.primary_backend == "none")
    )

    if not $needs_installation {
        return {
            host: $host
            status: "ready"
            message: $"Host has ($capabilities.primary_backend) hypervisor available"
        }
    }

    print $"Preparing host ($host) for VM support..."

    # Determine what to install
    let to_install = [
        "kvm",
        "libvirt",
        "qemu",
    ]

    # Install each hypervisor
    let results = (
        $to_install
        | each {|taskserv|
            install-hypervisor-taskserv $host $taskserv
        }
    )

    # Check results
    let failures = ($results | where success == false)

    if ($failures | length) > 0 {
        return {
            host: $host
            status: "partial"
            message: $"Installed successfully but ($failures | length) failed"
            failed_taskservs: ($failures | each {|x| $x.taskserv})
        }
    }

    {
        host: $host
        status: "success"
        message: "Host prepared successfully for VM management"
        installed_taskservs: $to_install
    }
}

def install-hypervisor-taskserv [host: string, taskserv: string]: record {
    """Install a hypervisor taskserv on host"""

    print $"  Installing ($taskserv)..."

    let cmd = (
        if $host == "local" {
            $"provisioning taskserv create ($taskserv)"
        } else {
            $"provisioning taskserv create ($taskserv) --on-host ($host)"
        }
    )

    # Execute command (no try-catch)
    let exec_result = (do { shell-exec-safe $cmd } | complete)
    let result = (
        if $exec_result.exit_code == 0 {
            $exec_result.stdout
        } else {
            {
                taskserv: $taskserv
                success: false
                error: $exec_result.stderr
            }
        }
    )

    if ($result | type) == "record" and ("success" in $result) {
        return $result
    }

    {
        taskserv: $taskserv
        success: true
        message: $"Installed successfully"
    }
}

def shell-exec-safe [cmd: string]: record {
    """Execute shell command safely"""

    # Execute command (no try-catch)
    let result = (do { bash -c $cmd } | complete)

    if $result.exit_code != 0 {
        return {success: false, error: $result.stderr}
    }

    {success: true, stdout: $result.stdout}
}

export def "get-host-hypervisor-status" [host: string]: table {
    """Get detailed hypervisor status for a host"""

    let capabilities = (check-vm-capability $host)

    $capabilities.available_hypervisors
    | map {|h|
        {
            host: $host
            hypervisor: $h.name
            status: $h.available
            description: $h.description
            ready: ($h.available == "ready")
        }
    }
}

export def "list-vm-capable-hosts" []: table {
    """List all hosts that can run VMs"""

    # Get local host capability
    let local_status = (check-vm-capability "local")

    [
        {
            name: "local"
            can_run_vms: $local_status.can_run_vms
            primary_hypervisor: $local_status.primary_backend
        }
    ]
    # In future, could add remote hosts from infrastructure config
}

export def "ensure-vm-support" [host: string]: record {
    """
    Ensure host has VM support, installing if necessary.

    Returns success only when VM support is confirmed ready.
    """

    let status1 = (check-vm-capability $host)

    if $status1.primary_backend != "none" {
        return {
            host: $host
            status: "ready"
            message: $"Host already has VM support via ($status1.primary_backend)"
        }
    }

    # Need to install
    print $"Host ($host) needs VM hypervisor installation"
    let install_result = (prepare-host-install $host $status1)

    if $install_result.status != "success" {
        return $install_result
    }

    # Verify installation
    let status2 = (check-vm-capability $host)

    {
        host: $host
        status: "ready"
        message: $"VM support installed and verified"
        primary_hypervisor: $status2.primary_backend
    }
}
