#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
source "$SCRIPT_DIR/vm-common.sh"

CMD_NAME="${VM_SETUP_CMD_NAME:-fireclaw setup}"

usage() {
  cat <<EOF
Usage: $CMD_NAME --instance <id> [options]

Options:
  --telegram-token <token>             (optional; omit for a local-only gateway with Telegram disabled)
  --telegram-users <csv>               (required with --telegram-token)
  --model <id>                         (default: openai/gpt-5.5)
  --skills <csv>                       (default: github,tmux,coding-agent,session-logs,skill-creator)
  --openclaw-image <image>
  --host-port <n>                      (default: first free port above BASE_PORT)
  --vm-vcpu <n>                        (default: 4)
  --vm-mem-mib <n>                     (default: 8192)
  --disk-size <size>                   (default: 40G)
  --api-sock <path>                    (default: <fc-instance-dir>/firecracker.socket)
  --base-kernel <path>
  --base-rootfs <path>
  --base-initrd <path>
  --anthropic-api-key <key>
  --openai-api-key <key>
  --minimax-api-key <key>
  --skip-browser-install
  -h|--help
EOF
}

require_option_value() {
  local opt="$1"
  local value="${2-}"
  [[ -n "$value" && "$value" != --* ]] || die "Missing value for $opt"
}

validate_no_newline() {
  local name="$1"
  local value="$2"
  [[ "$value" != *$'\n'* && "$value" != *$'\r'* ]] || die "$name must not contain newlines"
}

validate_positive_int() {
  local name="$1"
  local value="$2"
  [[ "$value" =~ ^[0-9]+$ ]] || die "$name must be numeric"
  (( 10#$value > 0 )) || die "$name must be greater than zero"
}

csv_values() {
  printf '%s' "$1" | tr ',' '\n' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//; /^$/d'
}

write_kv() {
  local file="$1"
  local key="$2"
  local value="$3"
  validate_no_newline "$key" "$value"
  printf "%s=%s\n" "$key" "$value" >> "$file"
}

INSTANCE=""
TELEGRAM_TOKEN=""
TELEGRAM_USERS=""
MODEL="${MODEL:-openai/gpt-5.5}"
SKILLS="${SKILLS:-github,tmux,coding-agent,session-logs,skill-creator}"
OPENCLAW_IMAGE="$OPENCLAW_IMAGE_DEFAULT"
VM_VCPU="${VM_VCPU:-4}"
VM_MEM_MIB="${VM_MEM_MIB:-8192}"
DISK_SIZE="${DISK_SIZE:-40G}"
API_SOCK="${API_SOCK:-}"
HOST_PORT_OVERRIDE=""
BASE_IMAGES_DIR="${BASE_IMAGES_DIR:-/srv/firecracker/base/images}"
BASE_KERNEL="${BASE_KERNEL:-$BASE_IMAGES_DIR/vmlinux}"
BASE_ROOTFS="${BASE_ROOTFS:-$BASE_IMAGES_DIR/rootfs.ext4}"
BASE_INITRD="${BASE_INITRD:-$BASE_IMAGES_DIR/initrd.img}"
SKIP_BROWSER_INSTALL="false"

ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}"
OPENAI_API_KEY="${OPENAI_API_KEY:-}"
MINIMAX_API_KEY="${MINIMAX_API_KEY:-}"
SETUP_COMPLETE="false"
CLEANUP_ARMED="false"

cleanup_failed_setup() {
  local rc="$1"
  [[ "$rc" -eq 0 || "$SETUP_COMPLETE" == "true" ]] && return 0
  [[ "$CLEANUP_ARMED" == "true" ]] || return 0
  set +e
  if [[ -n "${INSTANCE:-}" && "$INSTANCE" =~ ^[a-z0-9_-]+$ ]]; then
    warn "Setup failed; cleaning up partial instance: $INSTANCE"
    local vm_svc proxy_svc
    vm_svc="$(vm_service "$INSTANCE")"
    proxy_svc="$(proxy_service "$INSTANCE")"
    systemctl stop "$proxy_svc" 2>/dev/null || true
    systemctl stop "$vm_svc" 2>/dev/null || true
    systemctl disable "$proxy_svc" 2>/dev/null || true
    systemctl disable "$vm_svc" 2>/dev/null || true
    rm -f "/etc/systemd/system/$proxy_svc" "/etc/systemd/system/$vm_svc"
    systemctl daemon-reload 2>/dev/null || true
    systemctl reset-failed "$proxy_svc" "$vm_svc" 2>/dev/null || true
    if [[ -n "${VM_TAP:-}" ]]; then
      ip link set "$VM_TAP" down 2>/dev/null || true
      ip link del "$VM_TAP" 2>/dev/null || true
    fi
    if [[ -n "${API_SOCK:-}" ]]; then
      rm -f "$API_SOCK"
    fi
    if [[ -n "${inst_dir:-}" ]]; then
      rm -rf "$inst_dir"
    fi
    if [[ -n "${fc_dir:-}" ]]; then
      rm -rf "$fc_dir"
    fi
  fi
}

trap 'rc=$?; cleanup_failed_setup "$rc"; exit "$rc"' EXIT

while [[ $# -gt 0 ]]; do
  case "$1" in
    --instance) require_option_value "$1" "${2-}"; INSTANCE="$2"; shift 2 ;;
    --telegram-token) require_option_value "$1" "${2-}"; TELEGRAM_TOKEN="$2"; shift 2 ;;
    --telegram-users) require_option_value "$1" "${2-}"; TELEGRAM_USERS="$2"; shift 2 ;;
    --model) require_option_value "$1" "${2-}"; MODEL="$2"; shift 2 ;;
    --skills) require_option_value "$1" "${2-}"; SKILLS="$2"; shift 2 ;;
    --openclaw-image) require_option_value "$1" "${2-}"; OPENCLAW_IMAGE="$2"; shift 2 ;;
    --host-port) require_option_value "$1" "${2-}"; HOST_PORT_OVERRIDE="$2"; shift 2 ;;
    --vm-vcpu) require_option_value "$1" "${2-}"; VM_VCPU="$2"; shift 2 ;;
    --vm-mem-mib) require_option_value "$1" "${2-}"; VM_MEM_MIB="$2"; shift 2 ;;
    --disk-size) require_option_value "$1" "${2-}"; DISK_SIZE="$2"; shift 2 ;;
    --api-sock) require_option_value "$1" "${2-}"; API_SOCK="$2"; shift 2 ;;
    --base-kernel) require_option_value "$1" "${2-}"; BASE_KERNEL="$2"; shift 2 ;;
    --base-rootfs) require_option_value "$1" "${2-}"; BASE_ROOTFS="$2"; shift 2 ;;
    --base-initrd) require_option_value "$1" "${2-}"; BASE_INITRD="$2"; shift 2 ;;
    --anthropic-api-key) require_option_value "$1" "${2-}"; ANTHROPIC_API_KEY="$2"; shift 2 ;;
    --openai-api-key) require_option_value "$1" "${2-}"; OPENAI_API_KEY="$2"; shift 2 ;;
    --minimax-api-key) require_option_value "$1" "${2-}"; MINIMAX_API_KEY="$2"; shift 2 ;;
    --skip-browser-install) SKIP_BROWSER_INSTALL="true"; shift ;;
    -h|--help) usage; exit 0 ;;
    *) die "Unknown option: $1" ;;
  esac
done

[[ -n "$INSTANCE" ]] || die "Missing --instance"
if [[ -n "$TELEGRAM_TOKEN" ]]; then
  [[ -n "$TELEGRAM_USERS" ]] || die "Missing --telegram-users (required with --telegram-token)"
  [[ -n "$(csv_values "$TELEGRAM_USERS")" ]] || die "--telegram-users must include at least one allowed Telegram user ID"
elif [[ -n "$TELEGRAM_USERS" ]]; then
  die "--telegram-users requires --telegram-token"
fi
validate_instance_id "$INSTANCE"
validate_positive_int "VM_VCPU" "$VM_VCPU"
validate_positive_int "VM_MEM_MIB" "$VM_MEM_MIB"
validate_no_newline "TELEGRAM_TOKEN" "$TELEGRAM_TOKEN"
validate_no_newline "TELEGRAM_USERS" "$TELEGRAM_USERS"
validate_no_newline "MODEL" "$MODEL"
validate_no_newline "SKILLS" "$SKILLS"
validate_no_newline "OPENCLAW_IMAGE" "$OPENCLAW_IMAGE"
validate_no_newline "DISK_SIZE" "$DISK_SIZE"
validate_no_newline "API_SOCK" "$API_SOCK"
validate_no_newline "BASE_KERNEL" "$BASE_KERNEL"
validate_no_newline "BASE_ROOTFS" "$BASE_ROOTFS"
validate_no_newline "BASE_INITRD" "$BASE_INITRD"
validate_no_newline "ANTHROPIC_API_KEY" "$ANTHROPIC_API_KEY"
validate_no_newline "OPENAI_API_KEY" "$OPENAI_API_KEY"
validate_no_newline "MINIMAX_API_KEY" "$MINIMAX_API_KEY"
if [[ -n "$HOST_PORT_OVERRIDE" ]]; then
  validate_no_newline "HOST_PORT" "$HOST_PORT_OVERRIDE"
fi
VM_VCPU=$((10#$VM_VCPU))
VM_MEM_MIB=$((10#$VM_MEM_MIB))
require_model_provider_key "$MODEL"

require_root
for c in firecracker systemctl ip bridge iptables openssl jq cloud-localds ssh scp socat curl qemu-img install flock; do
  require_cmd "$c"
done
FIRECRACKER_BIN="$(command -v firecracker)"
[[ "$FIRECRACKER_BIN" = /* ]] || die "firecracker must resolve to an absolute executable path"
[[ -e /dev/kvm && -r /dev/kvm && -w /dev/kvm ]] || die "/dev/kvm is not available (KVM is required to run Firecracker VMs)"

mem_avail_mib="$(awk '/^MemAvailable:/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)"
if (( mem_avail_mib > 0 && VM_MEM_MIB > mem_avail_mib )); then
  warn "Requested VM memory (${VM_MEM_MIB} MiB) exceeds host MemAvailable (${mem_avail_mib} MiB); the VM may OOM the host"
fi

[[ -f "$BASE_KERNEL" ]] || die "Kernel not found: $BASE_KERNEL"
[[ -f "$BASE_ROOTFS" ]] || die "Rootfs not found: $BASE_ROOTFS"

ensure_root_dirs

if [[ ! -f "$SSH_KEY_PATH" ]]; then
  log "Generating SSH key: $SSH_KEY_PATH"
  mkdir -p "$(dirname "$SSH_KEY_PATH")"
  ssh-keygen -t ed25519 -N "" -f "$SSH_KEY_PATH" >/dev/null
fi

inst_dir="$(instance_dir "$INSTANCE")"
fc_dir="$(fc_instance_dir "$INSTANCE")"
if [[ -z "$API_SOCK" ]]; then
  API_SOCK="$fc_dir/firecracker.socket"
fi
VM_SVC="$(vm_service "$INSTANCE")"
PROXY_SVC="$(proxy_service "$INSTANCE")"
[[ "$API_SOCK" = /* ]] || die "--api-sock must be an absolute path"
[[ ! -e "$inst_dir" ]] || die "Instance already exists: $inst_dir"
[[ ! -e "$fc_dir" ]] || die "Firecracker assets already exist: $fc_dir"
[[ ! -e "$API_SOCK" ]] || die "Firecracker API socket already exists: $API_SOCK"
[[ ! -e "/etc/systemd/system/$VM_SVC" ]] || die "VM unit already exists: /etc/systemd/system/$VM_SVC"
[[ ! -e "/etc/systemd/system/$PROXY_SVC" ]] || die "Proxy unit already exists: /etc/systemd/system/$PROXY_SVC"
CLEANUP_ARMED="true"

# Hold the allocation lock until the reservation is visible in the .env file,
# so concurrent setups cannot pick the same port/IP.
exec {ALLOC_LOCK_FD}>"$STATE_ROOT/.alloc.lock"
flock "$ALLOC_LOCK_FD"

if [[ -n "$HOST_PORT_OVERRIDE" ]]; then
  ensure_host_port_available "$HOST_PORT_OVERRIDE"
  HOST_PORT="$((10#$HOST_PORT_OVERRIDE))"
else
  HOST_PORT="$(next_port)"
fi
VM_IP="$(next_ip)"
SUBNET_MASK_BITS="$(subnet_mask_bits)"
BRIDGE_GATEWAY_IP="$(bridge_gateway_ip)"
VM_OCTET="${VM_IP##*.}"
SHORT_ID="$(echo "$INSTANCE" | tr -cd 'a-z0-9' | cut -c1-6)"
[[ -n "$SHORT_ID" ]] || SHORT_ID="vm"
VM_TAP="t${SHORT_ID}${VM_OCTET}"
VM_MAC="$(printf '06:fc:00:10:00:%02x' "$VM_OCTET")"
GATEWAY_TOKEN="$(openssl rand -hex 32)"

if ip link show "$VM_TAP" >/dev/null 2>&1; then
  die "TAP device already exists: $VM_TAP (leftover from a previous instance? remove it with: sudo ip link del $VM_TAP)"
fi

mkdir -p "$inst_dir/config" "$inst_dir/workspace"
chmod 700 "$inst_dir" "$inst_dir/config" "$inst_dir/workspace"
mkdir -p "$fc_dir/images" "$fc_dir/config" "$fc_dir/logs"
chmod 700 "$fc_dir" "$fc_dir/images" "$fc_dir/config" "$fc_dir/logs"
mkdir -p "$(dirname "$API_SOCK")"

ENV_FILE="$(instance_env "$INSTANCE")"
install -m 600 /dev/null "$ENV_FILE"
write_kv "$ENV_FILE" FIRECLAW_STATE_FORMAT "plain-v1"
write_kv "$ENV_FILE" INSTANCE_ID "$INSTANCE"
write_kv "$ENV_FILE" HOST_PORT "$HOST_PORT"
write_kv "$ENV_FILE" VM_IP "$VM_IP"
write_kv "$ENV_FILE" VM_TAP "$VM_TAP"
write_kv "$ENV_FILE" VM_MAC "$VM_MAC"
write_kv "$ENV_FILE" GATEWAY_TOKEN "$GATEWAY_TOKEN"
write_kv "$ENV_FILE" MODEL "$MODEL"
write_kv "$ENV_FILE" SKILLS "$SKILLS"
write_kv "$ENV_FILE" TELEGRAM_USERS "$TELEGRAM_USERS"
write_kv "$ENV_FILE" OPENCLAW_IMAGE "$OPENCLAW_IMAGE"
write_kv "$ENV_FILE" VM_VCPU "$VM_VCPU"
write_kv "$ENV_FILE" VM_MEM_MIB "$VM_MEM_MIB"
write_kv "$ENV_FILE" DISK_SIZE "$DISK_SIZE"
write_kv "$ENV_FILE" API_SOCK "$API_SOCK"
write_kv "$ENV_FILE" SSH_KEY_PATH "$SSH_KEY_PATH"
write_kv "$ENV_FILE" SKIP_BROWSER_INSTALL "$SKIP_BROWSER_INSTALL"
write_kv "$ENV_FILE" ANTHROPIC_API_KEY "$ANTHROPIC_API_KEY"
write_kv "$ENV_FILE" OPENAI_API_KEY "$OPENAI_API_KEY"
write_kv "$ENV_FILE" MINIMAX_API_KEY "$MINIMAX_API_KEY"

exec {ALLOC_LOCK_FD}>&-

install -m 600 /dev/null "$inst_dir/.token"
printf '%s\n' "$GATEWAY_TOKEN" > "$inst_dir/.token"

log "Preparing VM disk and assets"
cp --reflink=auto "$BASE_ROOTFS" "$fc_dir/images/rootfs.ext4" 2>/dev/null || cp "$BASE_ROOTFS" "$fc_dir/images/rootfs.ext4"
chmod 600 "$fc_dir/images/rootfs.ext4"
if [[ -n "$DISK_SIZE" ]]; then
  log "Resizing rootfs to $DISK_SIZE"
  qemu-img resize -f raw "$fc_dir/images/rootfs.ext4" "$DISK_SIZE" >/dev/null
fi
cp "$BASE_KERNEL" "$fc_dir/images/vmlinux"

INITRD_PATH=""
if [[ -f "$BASE_INITRD" ]]; then
  cp "$BASE_INITRD" "$fc_dir/images/initrd.img"
  INITRD_PATH="$fc_dir/images/initrd.img"
fi

SSH_PUB_KEY="$(cat "${SSH_KEY_PATH}.pub")"

cat > "$fc_dir/config/user-data" <<EOF
#cloud-config
users:
  - name: ubuntu
    groups: [sudo, docker]
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: true
    ssh_authorized_keys:
      - $SSH_PUB_KEY
package_update: true
packages:
  - jq
  - curl
EOF

cat > "$fc_dir/config/meta-data" <<EOF
instance-id: $INSTANCE
local-hostname: $INSTANCE
EOF

cat > "$fc_dir/config/network-config" <<EOF
version: 2
ethernets:
  eth0:
    match:
      macaddress: "$VM_MAC"
    set-name: eth0
    dhcp4: false
    addresses:
      - $VM_IP/$SUBNET_MASK_BITS
    routes:
      - to: 0.0.0.0/0
        via: $BRIDGE_GATEWAY_IP
    nameservers:
      addresses: [1.1.1.1,8.8.8.8]
EOF

cloud-localds --network-config="$fc_dir/config/network-config" "$fc_dir/images/seed.img" "$fc_dir/config/user-data" "$fc_dir/config/meta-data"

jq -n \
  --arg kernel "$fc_dir/images/vmlinux" \
  --arg initrd "$INITRD_PATH" \
  --arg rootfs "$fc_dir/images/rootfs.ext4" \
  --arg seed "$fc_dir/images/seed.img" \
  --arg tap "$VM_TAP" \
  --arg mac "$VM_MAC" \
  --arg log "$fc_dir/logs/firecracker.log" \
  --argjson vcpu "$VM_VCPU" \
  --argjson mem "$VM_MEM_MIB" '
{
  "boot-source": (
    { "kernel_image_path": $kernel, "boot_args": "console=ttyS0 reboot=k panic=1 pci=off" } +
    (if $initrd != "" then { "initrd_path": $initrd } else {} end)
  ),
  "drives": [
    { "drive_id": "rootfs", "path_on_host": $rootfs, "is_root_device": true, "is_read_only": false },
    { "drive_id": "seed", "path_on_host": $seed, "is_root_device": false, "is_read_only": true }
  ],
  "network-interfaces": [
    { "iface_id": "eth0", "host_dev_name": $tap, "guest_mac": $mac }
  ],
  "machine-config": { "vcpu_count": $vcpu, "mem_size_mib": $mem, "smt": false },
  "logger": { "log_path": $log, "level": "Info", "show_level": true, "show_log_origin": false }
}
' > "$fc_dir/config/vm-config.json"

cat > "$fc_dir/start-vm.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail

BRIDGE_NAME="$BRIDGE_NAME"
BRIDGE_ADDR="$BRIDGE_ADDR"
SUBNET_CIDR="$SUBNET_CIDR"
VM_TAP="$VM_TAP"
API_SOCK="$API_SOCK"
CONFIG_JSON="$fc_dir/config/vm-config.json"
FIRECRACKER_BIN="$FIRECRACKER_BIN"

if ! ip link show "\$BRIDGE_NAME" >/dev/null 2>&1; then
  ip link add "\$BRIDGE_NAME" type bridge
fi
ip -4 addr show dev "\$BRIDGE_NAME" | grep -Fq " \$BRIDGE_ADDR " || ip addr add "\$BRIDGE_ADDR" dev "\$BRIDGE_NAME"
ip link set "\$BRIDGE_NAME" up
sysctl -w net.ipv4.ip_forward=1 >/dev/null
iptables -t nat -C POSTROUTING -s "\$SUBNET_CIDR" ! -o "\$BRIDGE_NAME" -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -s "\$SUBNET_CIDR" ! -o "\$BRIDGE_NAME" -j MASQUERADE
# Defense-in-depth only: matches solely where br_netfilter is enabled.
iptables -C FORWARD -i "\$BRIDGE_NAME" -o "\$BRIDGE_NAME" -j DROP 2>/dev/null || iptables -I FORWARD 1 -i "\$BRIDGE_NAME" -o "\$BRIDGE_NAME" -j DROP

if ! ip link show "\$VM_TAP" >/dev/null 2>&1; then
  ip tuntap add dev "\$VM_TAP" mode tap user root
fi
ip link set "\$VM_TAP" master "\$BRIDGE_NAME"
# Isolated bridge ports cannot exchange frames (IP or ARP) with each other,
# only with the bridge/host itself — this is the actual VM-to-VM isolation.
bridge link set dev "\$VM_TAP" isolated on
ip link set "\$VM_TAP" up

rm -f "\$API_SOCK"
exec "\$FIRECRACKER_BIN" --api-sock "\$API_SOCK" --config-file "\$CONFIG_JSON"
EOF
chmod +x "$fc_dir/start-vm.sh"

cat > "$fc_dir/stop-vm.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail
VM_TAP="$VM_TAP"
API_SOCK="$API_SOCK"

# Ask the guest to shut down cleanly (systemd maps Ctrl-Alt-Del to a clean
# reboot, which exits Firecracker) before systemd kills the VMM, so the
# rootfs ext4 is not torn down mid-write.
if [[ -S "\$API_SOCK" ]]; then
  if curl -fsS --max-time 2 --unix-socket "\$API_SOCK" -X PUT http://localhost/actions \\
      -H 'Content-Type: application/json' -d '{"action_type": "SendCtrlAltDel"}' >/dev/null 2>&1; then
    for _ in \$(seq 1 20); do
      curl -fsS --max-time 1 --unix-socket "\$API_SOCK" http://localhost/ >/dev/null 2>&1 || break
      sleep 1
    done
  fi
fi

ip link set "\$VM_TAP" down 2>/dev/null || true
ip link del "\$VM_TAP" 2>/dev/null || true
rm -f "\$API_SOCK"
EOF
chmod +x "$fc_dir/stop-vm.sh"

cat > "/etc/systemd/system/$VM_SVC" <<EOF
[Unit]
Description=Firecracker VM ($INSTANCE)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=$fc_dir/start-vm.sh
ExecStop=$fc_dir/stop-vm.sh
TimeoutStopSec=45
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target
EOF

cat > "/etc/systemd/system/$PROXY_SVC" <<EOF
[Unit]
Description=Localhost proxy for VM ($INSTANCE)
After=$VM_SVC
Requires=$VM_SVC
PartOf=$VM_SVC

[Service]
Type=simple
DynamicUser=yes
ExecStart=/usr/bin/socat TCP-LISTEN:$HOST_PORT,bind=127.0.0.1,reuseaddr,fork TCP:$VM_IP:18789
SuccessExitStatus=143
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target $VM_SVC
EOF

systemctl daemon-reload
systemctl enable --now "$VM_SVC"

log "Waiting for SSH on $VM_IP"
if ! wait_for_ssh "$VM_IP" "$SSH_KEY_PATH" 180 "$INSTANCE"; then
  die "VM booted but SSH was not reachable"
fi

PROVISION_VARS="$inst_dir/provision.vars"
install -m 600 /dev/null "$PROVISION_VARS"
kv() { write_kv "$PROVISION_VARS" "$1" "$2"; }

kv FIRECLAW_STATE_FORMAT "plain-v1"
kv INSTANCE_ID "$INSTANCE"
kv TELEGRAM_TOKEN "$TELEGRAM_TOKEN"
kv TELEGRAM_USERS "$TELEGRAM_USERS"
kv MODEL "$MODEL"
kv SKILLS "$SKILLS"
kv GATEWAY_TOKEN "$GATEWAY_TOKEN"
kv OPENCLAW_IMAGE "$OPENCLAW_IMAGE"
kv SKIP_BROWSER_INSTALL "$SKIP_BROWSER_INSTALL"
kv DISK_SIZE "$DISK_SIZE"
kv ANTHROPIC_API_KEY "$ANTHROPIC_API_KEY"
kv OPENAI_API_KEY "$OPENAI_API_KEY"
kv MINIMAX_API_KEY "$MINIMAX_API_KEY"

[[ -f "$REPO_ROOT/scripts/provision-guest.sh" ]] || die "Missing: $REPO_ROOT/scripts/provision-guest.sh"

scp -i "$SSH_KEY_PATH" -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile="$(ssh_known_hosts_file "$INSTANCE")" \
  "$REPO_ROOT/scripts/provision-guest.sh" "ubuntu@$VM_IP:/tmp/provision-guest.sh"
scp -i "$SSH_KEY_PATH" -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile="$(ssh_known_hosts_file "$INSTANCE")" \
  "$PROVISION_VARS" "ubuntu@$VM_IP:/tmp/provision.vars"

ssh -i "$SSH_KEY_PATH" -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile="$(ssh_known_hosts_file "$INSTANCE")" \
  "ubuntu@$VM_IP" "sudo bash /tmp/provision-guest.sh /tmp/provision.vars"

# Guest provisioning succeeded: from here on a failure must not destroy the
# instance — it is recoverable with `fireclaw provision` / `fireclaw start`.
CLEANUP_ARMED="false"

systemctl enable --now "$PROXY_SVC"

if ! wait_for_instance_health "$INSTANCE" "$VM_IP" "$HOST_PORT" "$SSH_KEY_PATH" 30; then
  warn "The instance was kept for inspection: sudo fireclaw status $INSTANCE"
  die "Health checks did not pass for $INSTANCE after provisioning (retry with: sudo fireclaw provision $INSTANCE)"
fi
SETUP_COMPLETE="true"

echo "✓ VM instance configured"
echo "  Instance: $INSTANCE"
echo "  VM IP:    $VM_IP"
echo "  Port:     $HOST_PORT"
echo "  Token:    (print with: sudo fireclaw token $INSTANCE)"
echo "  Health:   up (guest + proxy)"
echo "  Status:   $(systemctl is-active "$VM_SVC") / $(systemctl is-active "$PROXY_SVC")"
