#!/usr/bin/env bash
# build-vm.sh — Modular VM builder. Sources a profile file that declares VM
# variables and a generate_user_data() function, then runs the common build
# pipeline against it.
#
# Usage:
#   ./build-vm.sh <profile> [--dry-run] [--force]
#
# Example:
#   ./build-vm.sh profiles/web-server.sh --force

set -euo pipefail

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

if [[ $# -lt 1 ]]; then
    echo "Usage: $0 <profile> [--dry-run] [--force]"
    exit 1
fi

PROFILE_ARG="$1"; shift

DRY_RUN=false
FORCE=false
while [[ $# -gt 0 ]]; do
    case "$1" in
        --dry-run) DRY_RUN=true; shift ;;
        --force)   FORCE=true;   shift ;;
        *) echo "Unknown argument: $1"; exit 1 ;;
    esac
done

source "$PROJECT_ROOT/tools/lib/config.sh"
config_read || true
if [ -n "${SC_IMAGES_DIR:-}" ]; then
    SC_IMAGE_ROOT="${SC_IMAGE_ROOT:-$SC_IMAGES_DIR}"
    export SC_IMAGE_ROOT
fi
if [ -n "${SC_LIBVIRT_URI:-}" ]; then
    LIBVIRT_DEFAULT_URI="${LIBVIRT_DEFAULT_URI:-$SC_LIBVIRT_URI}"
    export LIBVIRT_DEFAULT_URI
fi

source "$SCRIPT_DIR/lib/common.sh"

# Resolve profile path: bare name (e.g. "web-server") or explicit path.
if [[ -f "$PROFILE_ARG" ]]; then
    PROFILE="$PROFILE_ARG"
elif [[ -f "$SCRIPT_DIR/profiles/${PROFILE_ARG}.sh" ]]; then
    PROFILE="$SCRIPT_DIR/profiles/${PROFILE_ARG}.sh"
elif [[ -f "$SCRIPT_DIR/profiles/${PROFILE_ARG}" ]]; then
    PROFILE="$SCRIPT_DIR/profiles/${PROFILE_ARG}"
else
    echo "Profile not found: $PROFILE_ARG"
    echo "Available profiles:"
    ls "$SCRIPT_DIR/profiles/"
    exit 1
fi

source "$PROFILE"

# Validate required profile variables.
for var in DOMAIN HOSTNAME RAM_MB VCPUS DISK_SIZE GRAPHICS BASE_URL BASE_IMAGE; do
    [[ -n "${!var:-}" ]] || { echo "Profile must set $var"; exit 1; }
done
declare -f generate_user_data >/dev/null || { echo "Profile must define generate_user_data()"; exit 1; }

GAME_HOST_IP="${SC_GAME_HOST_IP:-10.42.0.1}"
POOL_DIR="$(pool_path)"
DISK_PATH="$POOL_DIR/${DOMAIN}.qcow2"
SEED_ISO="$SC_SEED_DIR/${DOMAIN}-seed.iso"
PUBKEY="$(<"${SC_SSH_KEY}.pub")"

export DOMAIN HOSTNAME RAM_MB VCPUS DISK_SIZE GRAPHICS BASE_URL BASE_IMAGE
export GAME_HOST_IP POOL_DIR DISK_PATH SEED_ISO PUBKEY

ensure_vm_tooling

echo ""
echo "══════════════════════════════════════════════════"
echo "  Building VM: $DOMAIN ($HOSTNAME)"
echo "  Profile: $(basename "$PROFILE")"
echo "  RAM: ${RAM_MB} MB  vCPUs: ${VCPUS}  Disk: ${DISK_SIZE}"
echo "══════════════════════════════════════════════════"

if domain_exists "$DOMAIN" && [ "$FORCE" = "false" ]; then
    ok "$DOMAIN already exists. Use --force to rebuild it."
    exit 0
fi

step "Preparing base image"
download_if_missing "$BASE_URL" "$BASE_IMAGE"

step "Preparing cloud-init seed"
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

generate_user_data > "$tmpdir/user-data"

cat > "$tmpdir/meta-data" <<EOF
instance-id: ${DOMAIN}
local-hostname: ${HOSTNAME}
EOF

create_seed_iso "$tmpdir/user-data" "$tmpdir/meta-data" "$SEED_ISO"

step "Building domain"
destroy_domain "$DOMAIN"
create_backing_disk "$BASE_IMAGE" "$DISK_PATH" "$DISK_SIZE"
build_import_domain "$DOMAIN" "$DISK_PATH" "$SEED_ISO" "$RAM_MB" "$VCPUS" "$GRAPHICS"

step "Waiting for guest networking"
guest_addr=""
if [ "$DRY_RUN" = "false" ]; then
    if guest_addr="$(wait_for_agent_ip "$DOMAIN" 300)"; then
        ok "$DOMAIN is reachable at $guest_addr"
    else
        info "Guest IP not available yet. First boot may still be running cloud-init."
    fi
fi

if [ "$DRY_RUN" = "false" ] && [ -n "${READY_COMMAND:-}" ]; then
    step "Waiting for guest readiness"
    if [ -n "$guest_addr" ]; then
        if [ -n "${READY_WATCH_TEMPLATE:-}" ]; then
            watch_command="${READY_WATCH_TEMPLATE//\{ADDR\}/$guest_addr}"
            info "Watch live progress in another terminal:"
            info "$watch_command"
        fi
    fi
    if wait_for_guest_command "$DOMAIN" "${READY_TIMEOUT:-600}" "$READY_COMMAND" "${READY_PROGRESS_COMMAND:-}" "${READY_PROGRESS_EVERY_SEC:-30}"; then
        ok "$DOMAIN passed readiness check"
        detach_seed_iso "$DOMAIN" "$SEED_ISO"
    else
        fail "$DOMAIN did not pass readiness check within ${READY_TIMEOUT:-600}s"
    fi
fi

ok "$DOMAIN build complete"
