#!/usr/bin/env bash
# libvirt wrappers for Sysadmin Chronicles.
# Source this file; do not execute directly.
# Expects LIBVIRT_DEFAULT_URI to be set by the caller.
#
# SC_VIRSH_SUDO=true  — prefix all virsh calls with sudo.
# Set this in install.sh when the current session doesn't yet have
# the libvirt group active (e.g., right after usermod -aG libvirt).

_virsh() {
    if [ "${SC_VIRSH_SUDO:-false}" = true ]; then
        sudo virsh "$@"
    else
        virsh "$@"
    fi
}

ensure_network() {
    local name="$1"
    local xml_path="$2"
    if _virsh net-list --all 2>/dev/null | grep -q "\\b${name}\\b"; then
        if ! _virsh net-info "$name" 2>/dev/null | grep -q "Active:.*yes"; then
            _virsh net-start "$name" >/dev/null 2>&1
        fi
        return 0
    fi
    _virsh net-define "$xml_path"    >/dev/null 2>&1
    _virsh net-autostart "$name"     >/dev/null 2>&1
    _virsh net-start "$name"         >/dev/null 2>&1
}

ensure_pool() {
    local name="$1"
    local path="$2"
    if _virsh pool-list --all 2>/dev/null | grep -q "\\b${name}\\b"; then
        if ! _virsh pool-info "$name" 2>/dev/null | grep -q "State:.*running"; then
            _virsh pool-start "$name" >/dev/null 2>&1
        fi
        return 0
    fi
    mkdir -p "$path"
    _virsh pool-define-as "$name" dir --target "$path"    >/dev/null 2>&1
    _virsh pool-autostart "$name"                         >/dev/null 2>&1
    _virsh pool-start "$name"                             >/dev/null 2>&1
}

pool_path() {
    local name="$1"
    _virsh pool-dumpxml "$name" 2>/dev/null \
        | sed -n 's:.*<path>\(.*\)</path>.*:\1:p' \
        | head -n1
}

domain_exists() {
    _virsh dominfo "$1" >/dev/null 2>&1
}

domain_state() {
    _virsh domstate "$1" 2>/dev/null | tr -d ' \n'
}

network_active() {
    _virsh net-info "$1" 2>/dev/null | grep -q "Active:.*yes"
}

ensure_network_active() {
    local name="$1"
    _virsh net-list --all 2>/dev/null | grep -q "\\b${name}\\b" || return 1
    network_active "$name" || _virsh net-start "$name" >/dev/null 2>&1
}

snapshot_exists() {
    _virsh snapshot-info "$1" "$2" >/dev/null 2>&1
}

snapshot_create() {
    local domain="$1"
    local name="$2"
    local desc="${3:-}"
    _virsh snapshot-delete "$domain" "$name" >/dev/null 2>&1 || true
    _virsh snapshot-create-as "$domain" "$name" --description "$desc" --atomic
}

snapshot_revert() {
    _virsh snapshot-revert "$1" "$2" --running
}

snapshot_delete() {
    _virsh snapshot-delete "$1" "$2"
}

snapshot_list_names() {
    _virsh snapshot-list "$1" --name 2>/dev/null || true
}

# Returns approximate qcow2 disk usage for a domain in human-readable form
domain_disk_usage() {
    local domain="$1"
    local total=0
    local disk
    for disk in $(_virsh domblklist "$domain" --details 2>/dev/null | awk '/disk/ && $4 != "-" {print $4}' || true); do
        [ -f "$disk" ] || continue
        local sz
        sz="$(du -sb "$disk" 2>/dev/null | awk '{print $1}' || echo 0)"
        total=$(( total + sz ))
    done
    if [ "$total" -gt 0 ]; then
        numfmt --to=iec-i --suffix=B "$total" 2>/dev/null || echo "${total}B"
    else
        echo "0B"
    fi
}
