#!/usr/bin/env bash
# Hermes Agent Cloud — Deploy the Hermes Agent to AWS, GCP, or Azure
# Usage: hermes-agent-cloud [command] [options]
set -euo pipefail

HERMES_DEPLOY_VERSION="1.5.1"

# enums.sh uses associative arrays, which require Bash 4+.
if (( BASH_VERSINFO[0] < 4 )); then
  for bash_candidate in /opt/homebrew/bin/bash /usr/local/bin/bash; do
    if [[ -x "$bash_candidate" ]]; then
      exec "$bash_candidate" "$0" "$@"
    fi
  done

  echo "hermes-agent-cloud requires Bash 4+." >&2
  echo "Install it with: brew install bash" >&2
  exit 1
fi

resolve_script_dir() {
  local source_path="${BASH_SOURCE[0]}"
  while [[ -L "$source_path" ]]; do
    local source_dir
    source_dir="$(cd "$(dirname "$source_path")" && pwd)"
    source_path="$(readlink "$source_path")"
    [[ "$source_path" != /* ]] && source_path="$source_dir/$source_path"
  done

  cd "$(dirname "$source_path")" && pwd
}

HERMES_DEPLOY_DIR="$(resolve_script_dir)"
HERMES_DEPLOY_HOME="${HOME}/.hermes-agent-cloud"

# ─── Source libraries ───────────────────────────────────────────────────────
# shellcheck source=lib/enums.sh
# Must be sourced first; other libs depend on enum arrays.
source "${HERMES_DEPLOY_DIR}/lib/enums.sh"
# shellcheck source=lib/ui.sh
source "${HERMES_DEPLOY_DIR}/lib/ui.sh"
# shellcheck source=lib/preflight.sh
source "${HERMES_DEPLOY_DIR}/lib/preflight.sh"
# shellcheck source=lib/config.sh
source "${HERMES_DEPLOY_DIR}/lib/config.sh"
# shellcheck source=lib/ssh.sh
source "${HERMES_DEPLOY_DIR}/lib/ssh.sh"
# shellcheck source=lib/aws.sh
source "${HERMES_DEPLOY_DIR}/lib/aws.sh"
# shellcheck source=lib/azure.sh
source "${HERMES_DEPLOY_DIR}/lib/azure.sh"
# shellcheck source=lib/gcp_catalog.sh
source "${HERMES_DEPLOY_DIR}/lib/gcp_catalog.sh"
# shellcheck source=lib/gcp.sh
source "${HERMES_DEPLOY_DIR}/lib/gcp.sh"
# shellcheck source=lib/billing.sh
source "${HERMES_DEPLOY_DIR}/lib/billing.sh"
# shellcheck source=lib/ebs.sh
source "${HERMES_DEPLOY_DIR}/lib/ebs.sh"
# shellcheck source=lib/profile.sh
source "${HERMES_DEPLOY_DIR}/lib/profile.sh"
# shellcheck source=lib/secrets_bws.sh
source "${HERMES_DEPLOY_DIR}/lib/secrets_bws.sh"
# shellcheck source=lib/backup.sh
source "${HERMES_DEPLOY_DIR}/lib/backup.sh"
# shellcheck source=lib/redundancy.sh
source "${HERMES_DEPLOY_DIR}/lib/redundancy.sh"
# shellcheck source=lib/ci_setup.sh
source "${HERMES_DEPLOY_DIR}/lib/ci_setup.sh"

# ─── Globals ────────────────────────────────────────────────────────────────
CLOUD=""
REDUNDANT_CLOUD=""
export REGION=""
export DRY_RUN=false
export NO_COLOR=false
export GCP_PRESET=""
export GCP_PACKS=""
export CONFIG_INPUT_FILE=""
export EXPLAIN_ONLY=false
SUBCOMMAND=""
REMAINING_ARGS=()

# ─── Flag parser ────────────────────────────────────────────────────────────
parse_flags() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --cloud)    CLOUD="$(echo "$2" | tr '[:upper:]' '[:lower:]')"; validate_cloud "$CLOUD"; shift 2 ;;
      --region)      REGION="$2"; shift 2 ;;
      --preset)      GCP_PRESET="$(echo "$2" | tr '[:upper:]' '[:lower:]')"; shift 2 ;;
      --packs)       GCP_PACKS="$(echo "$2" | tr '[:upper:]' '[:lower:]')"; shift 2 ;;
      --config)      CONFIG_INPUT_FILE="$2"; shift 2 ;;
      --dry-run)  DRY_RUN=true; shift   ;;
      --explain)  EXPLAIN_ONLY=true; shift ;;
      --no-color) NO_COLOR=true; shift  ;;
      --redundant) REDUNDANT_CLOUD="$(echo "$2" | tr '[:upper:]' '[:lower:]')"; shift 2 ;;
      --help|-h)  cmd_help; exit 0      ;;
      -*)  error "Unknown flag: $1"; exit 1 ;;
      *)
        if [[ -z "$SUBCOMMAND" ]]; then
          SUBCOMMAND="$1"
        else
          REMAINING_ARGS+=("$1")
        fi
        shift
        ;;
    esac
  done
}

# ─── Help ───────────────────────────────────────────────────────────────────
cmd_help() {
  hermes_banner
  echo ""
  gum style --foreground 212 --bold "USAGE"
  echo "  hermes-agent-cloud [command] [options]"
  echo ""
  gum style --foreground 212 --bold "COMMANDS"
  printf "  %-12s %s\n" "update"  "Upgrade hermes-agent on the VM to the latest version"
  printf "  %-12s %s\n" "doctor"  "Run on-instance health checks (service, disk, memory, env)"
  printf "  %-12s %s\n" "deploy"  "Deploy Hermes Agent to a cloud provider (default)"
  printf "  %-12s %s\n" "status"  "Show live resource status"
  printf "  %-12s %s\n" "open"    "Open Hermes WebUI in your browser (via SSH tunnel)"
  printf "  %-12s %s\n" "tunnel"  "Open SSH tunnel to WebUI (port forward only, no browser)"
  printf "  %-12s %s\n" "update-ip" "Re-detect your public IP and update cloud firewall rules"
  printf "  %-12s %s\n" "ssh"     "Open a shell on the Hermes instance"
  printf "  %-12s %s\n" "logs"    "Stream live Hermes gateway logs"
  printf "  %-12s %s\n" "secrets" "Update API keys in the cloud vault"
  printf "  %-12s %s\n" "ebs"     "Manage persistent data volume (attach/detach/migrate)  [AWS]"
  printf "  %-12s %s\n" "billing" "Show cloud cost summary and budget alerts"
  printf "  %-12s %s\n" "backup"  "Snapshot skills/memory/config to local + cloud storage"
  printf "  %-12s %s\n" "doctor"  "Run post-deploy diagnostics (GCP support is richest)"
  printf "  %-12s %s\n" "ci-setup"  "Generate GitHub Actions workflow for deploy automation"
  printf "  %-12s %s\n" "destroy" "Tear down all deployed resources"
  printf "  %-12s %s\n" "profile" "Manage named profiles (multi-instance)"
  printf "  %-12s %s\n" "redundancy" "Manage multi-cloud failover (status, failover)"
  printf "  %-12s %s\n" "version" "Print version"
  echo ""
  gum style --foreground 212 --bold "OPTIONS"
  printf "  %-20s %s\n" "--cloud aws|gcp|azure" "Target cloud provider"
  printf "  %-20s %s\n" "--region REGION"        "Cloud region (e.g. ap-east-1)"
  printf "  %-20s %s\n" "--preset PRESET"        "GCP preset (minimal|dev-agent|data-agent|ai-agent|full-ops)"
  printf "  %-20s %s\n" "--packs pack1,pack2"    "Extra GCP capability packs"
  printf "  %-20s %s\n" "--config FILE"          "Load repeatable deploy inputs from a profile file"
  printf "  %-20s %s\n" "--dry-run"              "Show plan only, no resources created"
  printf "  %-20s %s\n" "--explain"              "Show resolved GCP plan and exit"
  printf "  %-20s %s\n" "--no-color"             "Disable color output"
  printf "  %-20s %s\n" "--help"                 "Show this help"
  echo ""
  gum style --foreground 212 --bold "EXAMPLES"
  echo "  hermes-agent-cloud                               # launch the wizard"
  echo "  hermes-agent-cloud deploy --cloud aws            # deploy to AWS"
  echo "  hermes-agent-cloud deploy --cloud gcp --dry-run  # preview GCP plan"
  echo "  hermes-agent-cloud deploy --cloud gcp --preset ai-agent --packs pubsub"
  echo "  hermes-agent-cloud deploy --cloud gcp --config ./gcp-profile.env --explain"
  echo "  hermes-agent-cloud ssh                           # SSH into the instance"
  echo "  hermes-agent-cloud doctor                        # run diagnostics for the saved deploy"
  echo "  hermes-agent-cloud secrets                       # rotate API keys"
  echo "  hermes-agent-cloud billing                            # view cloud cost summary"
  echo "  hermes-agent-cloud billing --cloud aws               # AWS costs only"
  echo "  hermes-agent-cloud ebs status                           # show volume info"
  echo "  hermes-agent-cloud ebs detach                          # detach for instance upgrade"
  echo "  hermes-agent-cloud ebs attach i-0abc123def456         # reattach to new instance"
  echo "  hermes-agent-cloud ebs migrate                        # full instance migration wizard"
  echo ""
}

# ─── Version ────────────────────────────────────────────────────────────────
cmd_version() {
  echo "hermes-agent-cloud v${HERMES_DEPLOY_VERSION}"
}

# ─── Deploy ─────────────────────────────────────────────────────────────────
cmd_deploy() {
  hermes_banner
  preflight_check

  config_load

  if [[ -n "$CLOUD" ]]; then
    CLOUD="$(echo "$CLOUD" | tr '[:upper:]' '[:lower:]')"
  else
    local cloud_choice
    cloud_choice=$(choose_one "Choose your cloud provider" "AWS" "GCP" "Azure")
    CLOUD="$(echo "$cloud_choice" | tr '[:upper:]' '[:lower:]')"
  fi

  case "$CLOUD" in
    aws)   aws_wizard   ;;
    azure) azure_wizard ;;
    gcp)   gcp_wizard   ;;
    *)     error "Unknown cloud provider: ${CLOUD}"; exit 1 ;;
  esac

  if [[ -n "$REDUNDANT_CLOUD" ]]; then
    redundancy_deploy "$CLOUD" "$REDUNDANT_CLOUD"
  fi
}

# ─── Status ─────────────────────────────────────────────────────────────────
cmd_status() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-agent-cloud deploy"; exit 1; }

  hermes_banner
  case "$CLOUD" in
    aws)   aws_status   ;;
    azure) azure_status ;;
    gcp)   gcp_status   ;;
  esac
}

# ─── SSH ────────────────────────────────────────────────────────────────────
cmd_ssh() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-agent-cloud deploy"; exit 1; }

  case "$CLOUD" in
    aws)   aws_ssh   ;;
    azure) azure_ssh ;;
    gcp)   gcp_ssh   ;;
  esac
}

# ─── Logs ───────────────────────────────────────────────────────────────────
cmd_logs() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-agent-cloud deploy"; exit 1; }

  case "$CLOUD" in
    aws)   aws_logs   ;;
    azure) azure_logs ;;
    gcp)   gcp_logs   ;;
  esac
}

# ─── Secrets ────────────────────────────────────────────────────────────────
cmd_secrets() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-agent-cloud deploy"; exit 1; }

  hermes_banner

  local method
  method=$(choose_one "How would you like to manage secrets?" \
    "Manual entry" \
    "Bitwarden Secrets Manager")

  case "$method" in
    "Bitwarden Secrets Manager")
      cmd_secrets_bws
      ;;
    *)
      case "$CLOUD" in
        aws)   aws_secrets   ;;
        azure) azure_secrets ;;
        gcp)   gcp_secrets   ;;
      esac
      ;;
  esac
}

# ─── Open / Tunnel ──────────────────────────────────────────────────────────
# Fetch the live public IP from the cloud provider (handles elastic IP changes after restart)
_get_live_ip() {
  local cloud="$1"
  local ip=""
  case "$cloud" in
    aws)
      local tf_dir region instance_id
      tf_dir=$(config_get "tf_dir" 2>/dev/null || echo "")
      region=$(config_get "region" 2>/dev/null || echo "")
      instance_id=$(config_get "instance_id" 2>/dev/null || echo "")
      # Try Terraform state first (authoritative)
      if [[ -n "$tf_dir" && -d "$tf_dir" ]]; then
        ip=$(terraform -chdir="$tf_dir" output -raw public_ip 2>/dev/null || echo "")
      fi
      # Fall back to live AWS API (catches IP change after VM reboot)
      if [[ -z "$ip" && -n "$instance_id" && -n "$region" ]]; then
        ip=$(aws ec2 describe-instances \
          --instance-ids "$instance_id" \
          --region "$region" \
          --query "Reservations[0].Instances[0].PublicIpAddress" \
          --output text 2>/dev/null | grep -v None || echo "")
      fi
      ;;
    gcp)
      local tf_dir zone
      tf_dir=$(config_get "tf_dir" 2>/dev/null || echo "")
      zone=$(config_get "region" 2>/dev/null || echo "")  # region stores zone for GCP
      if [[ -n "$tf_dir" && -d "$tf_dir" ]]; then
        ip=$(terraform -chdir="$tf_dir" output -raw public_ip 2>/dev/null || echo "")
      fi
      if [[ -z "$ip" && -n "$zone" ]]; then
        ip=$(gcloud compute instances describe hermes-instance \
          --zone "$zone" \
          --format "value(networkInterfaces[0].accessConfigs[0].natIP)" 2>/dev/null || echo "")
      fi
      ;;
    azure)
      local tf_dir
      tf_dir=$(config_get "tf_dir" 2>/dev/null || echo "")
      if [[ -n "$tf_dir" && -d "$tf_dir" ]]; then
        ip=$(terraform -chdir="$tf_dir" output -raw public_ip 2>/dev/null || echo "")
      fi
      if [[ -z "$ip" ]]; then
        ip=$(az vm list-ip-addresses \
          --resource-group hermes-rg \
          --name hermes-instance \
          --query "[0].virtualMachine.network.publicIpAddresses[0].ipAddress" \
          --output tsv 2>/dev/null || echo "")
      fi
      ;;
  esac
  # Last resort: cached value in config
  [[ -z "$ip" ]] && ip=$(config_get "public_ip" 2>/dev/null || echo "")
  echo "$ip"
}

_webui_ssh_tunnel() {
  local mode="$1"   # "open" or "tunnel"
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-agent-cloud deploy"; exit 1; }

  local ip ssh_key local_port remote_port
  info "Fetching current IP for ${CLOUD}..."
  ip=$(_get_live_ip "$CLOUD")
  [[ -z "$ip" ]] && { error "Cannot determine VM IP. Check: hermes-agent-cloud status"; exit 1; }

  # Update cached IP in case it changed (e.g. after VM restart)
  config_set "public_ip" "$ip"

  ssh_key=$(config_get "ssh_key_path")
  ssh_key="${ssh_key/#\~/$HOME}"
  local_port=$(config_get "webui_port" 2>/dev/null || echo "8787")
  remote_port="$local_port"

  info "Opening SSH tunnel → http://127.0.0.1:${local_port}"
  info "  Remote: ${ip}:${remote_port}"

  # SSH keepalive flags — prevent idle disconnect
  local keepalive_opts=(
    -o "ServerAliveInterval=30"
    -o "ServerAliveCountMax=6"
    -o "TCPKeepAlive=yes"
    -o "StrictHostKeyChecking=accept-new"
    -o "ExitOnForwardFailure=yes"
  )

  if [[ "$mode" == "open" ]]; then
    # Background tunnel, then open browser
    ssh -f -N \
        -L "${local_port}:127.0.0.1:${remote_port}" \
        -i "$ssh_key" \
        "${keepalive_opts[@]}" \
        "ubuntu@${ip}"
    sleep 1
    local url="http://127.0.0.1:${local_port}"
    if command -v open &>/dev/null; then
      open "$url"
    elif command -v xdg-open &>/dev/null; then
      xdg-open "$url"
    else
      success "Tunnel ready — open in browser: $url"
    fi
    success "Tunnel running in background. Close with: pkill -f 'L ${local_port}:127.0.0.1'"
  else
    # Foreground tunnel — blocks until Ctrl-C, auto-reconnect on drop
    info "Press Ctrl-C to close. Tunnel will auto-reconnect on disconnect."
    while true; do
      ssh -N \
          -L "${local_port}:127.0.0.1:${remote_port}" \
          -i "$ssh_key" \
          "${keepalive_opts[@]}" \
          "ubuntu@${ip}" || true
      warn "Tunnel dropped — reconnecting in 5s... (Ctrl-C to stop)"
      sleep 5
      # Re-fetch IP in case VM was restarted with a new IP
      local new_ip
      new_ip=$(_get_live_ip "$CLOUD")
      [[ -n "$new_ip" ]] && ip="$new_ip"
    done
  fi
}

cmd_open() {
  _webui_ssh_tunnel "open"
}

cmd_tunnel() {
  _webui_ssh_tunnel "tunnel"
}

# ─── Update IP ──────────────────────────────────────────────────────────────
# Re-fetches your current public IP and updates the cloud firewall rules.
# Run this whenever your local IP changes (ISP reassignment, VPN, travel, etc.)
cmd_update_ip() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-agent-cloud deploy"; exit 1; }

  hermes_banner

  # Detect current public IP
  local new_ip
  new_ip=$(curl -sf --max-time 5 "https://api.ipify.org" \
             || curl -sf --max-time 5 "https://ifconfig.me" \
             || echo "")
  [[ -z "$new_ip" ]] && { error "Could not detect your public IP. Check your internet connection."; exit 1; }

  local new_cidr="${new_ip}/32"
  local old_ip
  old_ip=$(config_get "allowed_ip" 2>/dev/null || echo "unknown")

  if [[ "$new_ip" == "$old_ip" ]]; then
    success "Your IP is unchanged: ${new_ip} — no update needed."
    return 0
  fi

  warn "IP changed: ${old_ip} → ${new_ip}"
  gum confirm "Update cloud firewall rules to allow ${new_ip}?" || { warn "Aborted."; exit 0; }

  local tf_dir
  tf_dir=$(config_get "tf_dir")
  [[ -z "$tf_dir" || ! -d "$tf_dir" ]] && { error "Terraform directory not found: ${tf_dir}"; exit 1; }

  # Patch tfvars in-place (macOS and Linux compatible)
  if grep -q "allowed_ssh_cidr" "${tf_dir}/terraform.tfvars"; then
    if [[ "$OSTYPE" == "darwin"* ]]; then
      sed -i '' "s|allowed_ssh_cidr.*=.*|allowed_ssh_cidr = \"${new_cidr}\"|" "${tf_dir}/terraform.tfvars"
    else
      sed -i "s|allowed_ssh_cidr.*=.*|allowed_ssh_cidr = \"${new_cidr}\"|" "${tf_dir}/terraform.tfvars"
    fi
  else
    echo "allowed_ssh_cidr = \"${new_cidr}\"" >> "${tf_dir}/terraform.tfvars"
  fi

  info "Running terraform apply to update firewall rules..."
  terraform -chdir="$tf_dir" apply -auto-approve \
    -target="$(case "$CLOUD" in
      aws)   echo "aws_security_group.hermes_sg" ;;
      gcp)   echo "google_compute_firewall.hermes_ssh" ;;
      azure) echo "azurerm_network_security_group.hermes_nsg" ;;
    esac)" 2>&1 | tail -20

  # Persist new IP
  config_set "allowed_ip" "$new_ip"
  config_set "public_ip"  "$(_get_live_ip "$CLOUD")"

  success "Firewall updated. Your new allowed IP: ${new_ip}"
  info "If tunnel was running, restart it: hermes-agent-cloud tunnel"
}

# ─── Doctor ─────────────────────────────────────────────────────────────────
cmd_doctor() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-deploy deploy"; exit 1; }

  hermes_banner
  local ip ssh_key
  ip=$(_get_live_ip "$CLOUD")
  [[ -z "$ip" ]] && { error "Cannot determine VM IP. Check: hermes-deploy status"; exit 1; }
  ssh_key=$(config_get "ssh_key_path")
  ssh_key="${ssh_key/#\~/$HOME}"

  info "Running on-instance health check on ${ip}..."
  echo ""
  ssh_run_cmd "$ip" "ubuntu" "$ssh_key" '
    set +e
    pass() { printf "\033[32m  ✓\033[0m  %s\n" "$1"; }
    fail() { printf "\033[31m  ✗\033[0m  %s\n" "$1"; FAILED=1; }
    warn() { printf "\033[33m  ⚠\033[0m  %s\n" "$1"; }
    FAILED=0

    echo ""
    printf "\033[1;37m  ─── Hermes Agent Doctor ────────────────────────────\033[0m\n"
    echo ""

    # 1. hermes-gateway service
    if systemctl is-active --quiet hermes-gateway 2>/dev/null; then
      pass "hermes-gateway service is running"
    else
      fail "hermes-gateway service is NOT running  (sudo systemctl start hermes-gateway)"
    fi

    # 2. Gateway HTTP response
    if curl -sf --max-time 5 http://127.0.0.1:8080/health &>/dev/null; then
      pass "Gateway health endpoint /health responded OK"
    else
      warn "Gateway /health did not respond (may still be starting)"
    fi

    # 3. hermes-agent installed + version
    HERMES_BIN=$(command -v hermes 2>/dev/null || echo "")
    if [[ -n "$HERMES_BIN" ]]; then
      VER=$(hermes version 2>/dev/null | head -1 || echo "unknown")
      pass "hermes-agent installed: $VER"
    else
      fail "hermes binary not found in PATH"
    fi

    # 4. ~/.hermes/.env exists
    if [[ -f "$HOME/.hermes/.env" && -s "$HOME/.hermes/.env" ]]; then
      pass "~/.hermes/.env present and non-empty"
    else
      fail "~/.hermes/.env missing or empty  (run: hermes-deploy secrets)"
    fi

    # 5. Docker running
    if systemctl is-active --quiet docker 2>/dev/null; then
      pass "Docker daemon is running"
    else
      warn "Docker daemon is not running"
    fi

    # 6. Disk usage
    DISK=$(df -h / | awk "NR==2{print \$5}" | tr -d %)
    if (( DISK < 85 )); then
      pass "Disk usage: ${DISK}%"
    elif (( DISK < 95 )); then
      warn "Disk usage: ${DISK}% — getting full"
    else
      fail "Disk usage: ${DISK}% — critically full"
    fi

    # 7. Memory
    MEM_FREE=$(free -m | awk "/^Mem:/{print \$7}")
    if (( MEM_FREE > 512 )); then
      pass "Available memory: ${MEM_FREE} MB"
    else
      warn "Available memory: ${MEM_FREE} MB — low"
    fi

    echo ""
    if [[ "$FAILED" == "0" ]]; then
      printf "  \033[32m✓ All checks passed\033[0m\n"
    else
      printf "  \033[31m✗ Some checks failed — see above\033[0m\n"
    fi
    echo ""
    exit "$FAILED"
  '
}

# ─── Update ─────────────────────────────────────────────────────────────────
cmd_update() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-deploy deploy"; exit 1; }

  hermes_banner
  local ip ssh_key
  ip=$(_get_live_ip "$CLOUD")
  [[ -z "$ip" ]] && { error "Cannot determine VM IP. Check: hermes-deploy status"; exit 1; }
  ssh_key=$(config_get "ssh_key_path")
  ssh_key="${ssh_key/#\~/$HOME}"

  info "Upgrading hermes-agent on ${ip}..."
  echo ""
  ssh_run_cmd "$ip" "ubuntu" "$ssh_key" '
    set -e
    echo ""
    printf "\033[1;37m  ─── Upgrading Hermes Agent ─────────────────────────\033[0m\n"
    echo ""

    # Get current version before upgrade
    OLD_VER=$(hermes version 2>/dev/null | head -1 || echo "unknown")
    printf "  Current version: \033[33m%s\033[0m\n" "$OLD_VER"

    # Upgrade via pip if venv exists, else via curl installer
    VENV=$(ls -d ~/.hermes/venv ~/.local/share/hermes/venv 2>/dev/null | head -1 || echo "")
    if [[ -n "$VENV" && -f "$VENV/bin/pip" ]]; then
      printf "  Upgrading via pip...\n"
      "$VENV/bin/pip" install --upgrade hermes-agent
    else
      printf "  Upgrading via install script...\n"
      curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
    fi

    NEW_VER=$(hermes version 2>/dev/null | head -1 || echo "unknown")
    printf "\n  Upgraded: \033[33m%s\033[0m → \033[32m%s\033[0m\n" "$OLD_VER" "$NEW_VER"

    # Log version to systemd journal
    logger -t hermes-agent "hermes-agent upgraded: $OLD_VER -> $NEW_VER"

    # Restart gateway to pick up new version
    sudo systemctl restart hermes-gateway
    printf "  \033[32m✓ hermes-gateway restarted with new version\033[0m\n\n"
  '
}

# ─── Destroy ─────────────────────────────────────────────────────────────────
cmd_destroy() {
  config_load
  [[ -z "$CLOUD" ]] && CLOUD="$(config_get "cloud")"
  [[ -z "$CLOUD" ]] && { error "No deployment found. Run: hermes-agent-cloud deploy"; exit 1; }

  hermes_banner
  confirm_destructive "This will PERMANENTLY destroy your Hermes instance and all data."

  case "$CLOUD" in
    aws)   aws_destroy   ;;
    azure) azure_destroy ;;
    gcp)   gcp_destroy   ;;
  esac
}

# ─── Main ───────────────────────────────────────────────────────────────────
main() {
  mkdir -p "${HERMES_DEPLOY_HOME}"
  parse_flags "$@"

  local cmd="${SUBCOMMAND:-deploy}"

  case "$cmd" in
    update)  cmd_update  ;;
    doctor)  cmd_doctor  ;;
    deploy)  cmd_deploy  ;;
    status)  cmd_status  ;;
    open)      cmd_open      ;;
    tunnel)    cmd_tunnel    ;;
    update-ip) cmd_update_ip ;;
    ssh)       cmd_ssh       ;;
    logs)    cmd_logs    ;;
    secrets) cmd_secrets ;;
    ebs)     config_load; ebs_cmd "${REMAINING_ARGS[@]:-}" ;;
    billing) billing_cmd ;;
    backup)  backup_cmd  ;;
    destroy) cmd_destroy ;;
    profile) cmd_profile "${REMAINING_ARGS[@]:-}" ;;
    redundancy) cmd_redundancy "${REMAINING_ARGS[@]:-}" ;;
    ci-setup) ci_setup_cmd ;;
    version) cmd_version ;;
    help)    cmd_help    ;;
    *)
      error "Unknown command: ${cmd}"
      echo ""
      cmd_help
      exit 1
      ;;
  esac
}

main "$@"
