#!/usr/bin/env bash
# first-run-setup.sh — Sysadmin Chronicles one-time host setup
#
# This script creates the libvirt resources (networks, storage pool) and SSH
# keys required for the game. It is safe to re-run — all actions are idempotent.
#
# What this does:
#   1. Creates sc-internal libvirt network (private NAT, game-only)
#   2. Creates sc-images storage pool for qcow2 VM images
#   3. Generates the host→guest SSH key pair (sc_host_key)
#   4. Checks libvirtd is running and user has access
#
# What this does NOT do:
#   - Build VM images (that's seed-vms.sh)
#   - Modify /etc/libvirt or system-wide config beyond the named libvirt resources
#   - Require broad sudo during normal gameplay
#
# AGENT RULES: Never run provisioning scripts against VMs from here.
# This script only creates host infrastructure.

set -euo pipefail

OWNER_USER="${SUDO_USER:-$USER}"
OWNER_HOME="$(getent passwd "$OWNER_USER" | cut -d: -f6)"
OWNER_HOME="${OWNER_HOME:-$HOME}"
export LIBVIRT_DEFAULT_URI="${LIBVIRT_DEFAULT_URI:-qemu:///system}"

DRY_RUN=false
if [[ "${1:-}" == "--dry-run" ]]; then
    DRY_RUN=true
    echo "[DRY-RUN] No changes will be made."
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

run() {
    if [ "$DRY_RUN" = "true" ]; then
        echo "  [would run] $*"
    else
        "$@"
    fi
}

step() { echo ""; echo "── $* ───────────────────────"; }
ok()   { echo "  ✓ $*"; }
info() { echo "  → $*"; }

libvirt_reachable() {
    virsh -q list --all >/dev/null 2>&1
}

libvirt_socket_available() {
    systemctl is-active --quiet libvirtd.socket 2>/dev/null || \
    systemctl is-active --quiet virtqemud.socket 2>/dev/null
}

echo ""
echo "══════════════════════════════════════════════════"
echo "  Sysadmin Chronicles — First-Run Setup"
echo "══════════════════════════════════════════════════"

# Sanity: check libvirt access
step "Checking libvirt access"
if libvirt_reachable; then
    ok "libvirt responds to virsh"
elif libvirt_socket_available; then
    ok "libvirt socket activation is available"
else
    echo "  ERROR: libvirt is not reachable."
    echo "  Run: sudo systemctl enable --now libvirtd.socket"
    exit 1
fi

# ---------------------------------------------------------------------------
step "Creating sc-internal libvirt network"
# ---------------------------------------------------------------------------

NETWORK_XML="$SCRIPT_DIR/../vm/network-sc-internal.xml"

write_network_xml() {
    local target="$1"
    cat > "$target" << 'EOF'
<network>
  <name>sc-internal</name>
  <forward mode='nat'/>
  <bridge name='sc-br0' stp='on' delay='0'/>
  <ip address='10.42.0.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='10.42.0.10' end='10.42.0.50'/>
    </dhcp>
  </ip>
</network>
EOF
}

network_has_nat() {
    virsh net-dumpxml sc-internal 2>/dev/null | grep -q "<forward mode=['\"]nat['\"]"
}

define_network() {
    local label="$1"
    local tmpxml
    tmpxml=$(mktemp /tmp/sc-internal-XXXXXX.xml)
    if [ -f "$NETWORK_XML" ]; then
        cp "$NETWORK_XML" "$tmpxml"
    else
        write_network_xml "$tmpxml"
    fi
    run virsh net-define "$tmpxml"
    run virsh net-autostart sc-internal
    run virsh net-start sc-internal
    rm -f "$tmpxml"
    ok "$label"
}

if virsh net-list --all | grep -q "sc-internal"; then
    if network_has_nat; then
        ok "sc-internal network already exists with NAT"
    else
        info "Recreating sc-internal with NAT egress for guest provisioning..."
        run virsh net-destroy sc-internal >/dev/null 2>&1 || true
        run virsh net-undefine sc-internal
        define_network "sc-internal network recreated and started"
    fi
else
    info "Creating sc-internal (private NAT, game-scoped network)..."
    define_network "sc-internal network created and started"
fi

# ---------------------------------------------------------------------------
step "Creating sc-images storage pool"
# ---------------------------------------------------------------------------

if [ "${LIBVIRT_DEFAULT_URI}" = "qemu:///system" ]; then
    IMAGES_DIR="/var/lib/libvirt/images/sysadmin-chronicles"
else
    IMAGES_DIR="$OWNER_HOME/.local/share/sysadmin-chronicles/images"
fi

if virsh pool-list --all | grep -q "sc-images"; then
    CURRENT_POOL_PATH="$(virsh pool-dumpxml sc-images 2>/dev/null | sed -n 's:.*<path>\(.*\)</path>.*:\1:p' | head -n1)"
    if [ "$CURRENT_POOL_PATH" = "$IMAGES_DIR" ]; then
        ok "sc-images pool already exists"
    else
        info "Recreating sc-images pool at $IMAGES_DIR (was $CURRENT_POOL_PATH)..."
        run mkdir -p "$IMAGES_DIR"
        run virsh pool-destroy sc-images >/dev/null 2>&1 || true
        run virsh pool-undefine sc-images
        run virsh pool-define-as sc-images dir --target "$IMAGES_DIR"
        run virsh pool-autostart sc-images
        run virsh pool-start sc-images
        ok "sc-images pool recreated"
    fi
else
    info "Creating sc-images pool at $IMAGES_DIR..."
    run mkdir -p "$IMAGES_DIR"
    run virsh pool-define-as sc-images dir --target "$IMAGES_DIR"
    run virsh pool-autostart sc-images
    run virsh pool-start sc-images
    ok "sc-images pool created"
fi

# ---------------------------------------------------------------------------
step "Generating SSH key pair"
# ---------------------------------------------------------------------------

KEY_PATH="$OWNER_HOME/.ssh/sc_host_key"
if [ -f "$KEY_PATH" ]; then
    run chown "$OWNER_USER:$OWNER_USER" "$KEY_PATH" "${KEY_PATH}.pub" >/dev/null 2>&1 || true
    run chmod 600 "$KEY_PATH" >/dev/null 2>&1 || true
    run chmod 644 "${KEY_PATH}.pub" >/dev/null 2>&1 || true
    ok "SSH key already exists: $KEY_PATH"
else
    info "Generating ed25519 key: $KEY_PATH"
    run mkdir -p "$(dirname "$KEY_PATH")"
    run ssh-keygen -t ed25519 -N "" -C "sysadmin-chronicles-host" -f "$KEY_PATH"
    run chmod 600 "$KEY_PATH"
    run chmod 644 "${KEY_PATH}.pub"
    run chown "$OWNER_USER:$OWNER_USER" "$KEY_PATH" "${KEY_PATH}.pub"
    ok "SSH key generated"
    info "Public key (add to VM authorized_keys during build):"
    if [ "$DRY_RUN" = "false" ]; then
        cat "${KEY_PATH}.pub"
    fi
fi

# ---------------------------------------------------------------------------
step "Verifying group membership"
# ---------------------------------------------------------------------------

if id -nG | grep -qw "libvirt"; then
    ok "User is in libvirt group"
else
    info "Consider adding yourself to the libvirt group for passwordless VM control:"
    info "  sudo usermod -aG libvirt \$USER && newgrp libvirt"
fi

# ---------------------------------------------------------------------------

echo ""
echo "══════════════════════════════════════════════════"
echo "  Setup complete."
echo "  Next step: bash tools/setup/seed-vms.sh"
echo "══════════════════════════════════════════════════"
echo ""
