#!/usr/bin/env bash
#
# NOVA AGENT INSTALLER
# Standalone script for curl-based installation
#
# Usage:
#   curl -fsSL https://get.novaaiops.com/install.sh | sudo bash -s -- --api URL --token TOKEN
#   OR
#   NOVA_API_KEY="your_key" curl -fsSL https://get.novaaiops.com/install.sh | sudo bash
#
# Command Line Arguments:
#   --api URL         - API endpoint URL (e.g., https://api.novaaiops.com)
#   --token TOKEN     - Your Nova AI agent install token
#   --name NAME       - Custom node name (default: hostname)
#
# Environment Variables:
#   NOVA_API_KEY      - Required: Your Nova AI agent API key
#   NOVA_ENDPOINT     - API endpoint (default: https://app.novaaiops.com/api)
#   NOVA_NODE_NAME    - Node name (default: hostname)
#   NOVA_DEBUG        - Set to 1 for verbose output
#

set -euo pipefail

# ─── Colours ────────────────────────────────────────────────────────────────
# Brand greens are 24-bit RGB sampled directly from the Nova AI logo robot
# (Nova-AI-Ops-Website-green-Design-best/nova-logo.png). Same three stops the
# `nova` CLI banner uses, so the install flow and the post-install CLI feel
# like one product.
#
#   #90F127  LIME    — logo top highlight   (top of art, left ◆, accents)
#   #58BA18  BRAND   — logo body fill       (mid art, WELCOME letters, success)
#   #105707  FOREST  — logo deep shadow     (bottom art, right ◆)
LIME="\033[38;2;144;241;39m"
BRAND="\033[38;2;88;186;24m"
FOREST="\033[38;2;16;87;7m"
DIM="\033[38;2;139;148;158m"
FG="\033[38;2;201;209;217m"

# Legacy palette tokens — kept so any echo lines elsewhere in this script
# that still reference PURPLE/PINK/ORANGE collapse onto the green ramp
# instead of producing the old purple/pink/orange.
PURPLE="$LIME"
PINK="$BRAND"
ORANGE="$FOREST"

BLUE="\033[38;5;39m"
GREEN="$BRAND"
GRAY="\033[38;5;245m"
RED="\033[38;5;196m"
YELLOW="\033[38;5;226m"
BOLD="\033[1m"
RESET="\033[0m"

# Parse command line arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --api)
      NOVA_ENDPOINT="$2/api"
      shift 2
      ;;
    --token)
      NOVA_API_KEY="$2"
      shift 2
      ;;
    --name)
      NOVA_NODE_NAME="$2"
      shift 2
      ;;
    --debug)
      NOVA_DEBUG=1
      shift
      ;;
    *)
      shift
      ;;
  esac
done

# Configuration (command line args override environment variables)
NOVA_API_KEY="${NOVA_API_KEY:-}"
NOVA_ENDPOINT="${NOVA_ENDPOINT:-https://app.novaaiops.com/api}"
NOVA_NODE_NAME="${NOVA_NODE_NAME:-$(hostname)}"
SERVICE_NAME="nova-ai-agent"
BINARY_PATH="/usr/local/bin/nova-ai-agent"
CONFIG_DIR="/etc/nova"
CONFIG_FILE="${CONFIG_DIR}/agent.yaml"
SYSTEMD_UNIT_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
DATA_DIR="/var/lib/nova"
LOG_DIR="/var/log/nova"

# Agent download URL - extract base URL from endpoint
ENDPOINT_BASE="${NOVA_ENDPOINT%/api}"
AGENT_DOWNLOAD_BASE="${NOVA_DOWNLOAD_URL:-${ENDPOINT_BASE}/downloads/agent}"

# Build a horizontal rule split into three coloured segments — lime →
# brand → forest — same tri-colour pattern the `nova` CLI banner draws
# above and below its ASCII art. $1 = total width in characters.
tri_rule() {
  local width="${1:-72}"
  local a=$((width / 3))
  local b=$((width / 3))
  local c=$((width - a - b))
  local out=""
  out+="${LIME}"; for ((i = 0; i < a; i++)); do out+="━"; done
  out+="${BRAND}"; for ((i = 0; i < b; i++)); do out+="━"; done
  out+="${FOREST}"; for ((i = 0; i < c; i++)); do out+="━"; done
  out+="${RESET}"
  printf "    %b\n" "$out"
}

print_logo() {
  echo ""
  tri_rule 84
  echo ""
  # ASCII art rows cycle through the same three logo stops as the CLI banner.
  # Single-line "NOVA AGENT" wordmark — 84-col content + 4-col indent = 88.
  echo -e "    ${LIME}███╗   ██╗ ██████╗ ██╗   ██╗ █████╗      █████╗  ██████╗ ███████╗███╗   ██╗████████╗${RESET}"
  echo -e "    ${BRAND}████╗  ██║██╔═══██╗██║   ██║██╔══██╗    ██╔══██╗██╔════╝ ██╔════╝████╗  ██║╚══██╔══╝${RESET}"
  echo -e "    ${FOREST}██╔██╗ ██║██║   ██║██║   ██║███████║    ███████║██║  ███╗█████╗  ██╔██╗ ██║   ██║   ${RESET}"
  echo -e "    ${LIME}██║╚██╗██║██║   ██║╚██╗ ██╔╝██╔══██║    ██╔══██║██║   ██║██╔══╝  ██║╚██╗██║   ██║   ${RESET}"
  echo -e "    ${BRAND}██║ ╚████║╚██████╔╝ ╚████╔╝ ██║  ██║    ██║  ██║╚██████╔╝███████╗██║ ╚████║   ██║   ${RESET}"
  echo -e "    ${FOREST}╚═╝  ╚═══╝ ╚═════╝   ╚═══╝  ╚═╝  ╚═╝    ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═══╝   ╚═╝   ${RESET}"
  echo ""
  # WELCOME caption — bracketed by lime/forest diamonds, brand-green text.
  # Indent chosen so the caption sits roughly centred under the 84-col rule.
  echo -e "                       ${BOLD}${LIME}◆  ${BRAND}Welcome to NOVA AGENT${FOREST}  ◆${RESET}"
  echo ""
  echo -e "        ${DIM}Multi-distro agent  ·  metrics, logs, runbooks  ·  AI remediation${RESET}"
  echo ""
  tri_rule 84
  echo ""
}

step() { echo -e "${BLUE}${BOLD}▸ $*${RESET}"; }
substep() { echo -e "${GRAY}  • $*${RESET}"; }
success() { echo -e "${GREEN}✔ $*${RESET}"; }
error() { echo -e "${RED}✗ $*${RESET}" >&2; }
warn() { echo -e "${YELLOW}⚠ $*${RESET}"; }
info() { echo -e "${GRAY}$*${RESET}"; }

detect_arch() {
  case "$(uname -m)" in
    x86_64)  echo "amd64" ;;
    aarch64) echo "arm64" ;;
    armv7l)  echo "armv7" ;;
    *)
      error "Unsupported architecture: $(uname -m)"
      exit 1
      ;;
  esac
}

check_root() {
  if [[ $EUID -ne 0 ]]; then
    error "This installer must be run as root or with sudo"
    info "Run: sudo bash -c \"\$(curl -fsSL https://get.novaaiops.com/install.sh)\""
    exit 1
  fi
}

check_prerequisites() {
  step "Checking prerequisites"

  # Check for systemd
  if ! command -v systemctl &> /dev/null; then
    error "systemd is required but not found"
    exit 1
  fi

  # Check for curl
  if ! command -v curl &> /dev/null; then
    error "curl is required but not found"
    info "Install with: apt-get install curl  or  yum install curl"
    exit 1
  fi

  success "Prerequisites satisfied"
}

check_api_key() {
  if [[ -z "$NOVA_API_KEY" ]]; then
    echo ""
    error "Install token is required"
    echo ""
    info "To get your install token:"
    info "  1. Go to https://app.novaaiops.com/instances"
    info "  2. Click 'Quick Install' then 'Generate Install Token'"
    info "  3. Copy the install command"
    echo ""
    info "Example usage:"
    echo -e "${BLUE}  curl -fsSL https://get.novaaiops.com/install.sh | sudo bash -s -- --api \"https://api.novaaiops.com\" --token \"your_token\"${RESET}"
    echo ""
    info "Or use environment variable:"
    echo -e "${BLUE}  NOVA_API_KEY=\"your_token\" curl -fsSL https://get.novaaiops.com/install.sh | sudo bash${RESET}"
    echo ""
    exit 1
  fi

  success "Install token provided"
}

download_agent() {
  step "Installing Nova AI agent"

  substep "Platform: linux_$(detect_arch)"

  # Create the agent binary — a comprehensive shell-based metrics collector
  # that requires zero external dependencies (no Node.js, no Python).
  # Collects: CPU, memory, disk, network, load, uptime, process count, Docker containers
  cat > "$BINARY_PATH" << 'AGENT_EOF'
#!/bin/bash
# NOVA AI Agent v2.0.0 — Production metrics collector
# Collects system metrics and sends to Nova AI backend every 15 seconds
# Zero dependencies — uses standard Linux tools (free, df, /proc)

VERSION="2.0.0"
CONFIG_FILE="${1#--config=}"
echo "[Nova Agent v${VERSION}] Starting..."
echo "[Nova Agent] Config: $CONFIG_FILE"

# Read config from YAML
if [[ -f "$CONFIG_FILE" ]]; then
  AGENT_SECRET=$(grep "agent_secret:" "$CONFIG_FILE" 2>/dev/null | awk '{print $2}')
  AGENT_ID=$(grep "agent_id:" "$CONFIG_FILE" 2>/dev/null | awk '{print $2}')
  API_KEY=$(grep "api_key:" "$CONFIG_FILE" 2>/dev/null | awk '{print $2}')
  ENDPOINT=$(grep "endpoint_url:" "$CONFIG_FILE" 2>/dev/null | awk '{print $2}')
  NODE_NAME=$(grep "node_name:" "$CONFIG_FILE" 2>/dev/null | awk '{print $2}')
  ORG_ID=$(grep "org_id:" "$CONFIG_FILE" 2>/dev/null | awk '{print $2}')
  AUTH_KEY="${AGENT_SECRET:-$API_KEY}"
fi

SEND_INTERVAL=15
HEARTBEAT_INTERVAL=30
HEARTBEAT_COUNTER=0

collect_metrics() {
  local timestamp=$(date +%s)000
  local host="${NODE_NAME:-$(hostname)}"
  local agent="${AGENT_ID:-nova-agent-$(hostname)}"

  # CPU usage (from /proc/stat for accuracy)
  local cpu_line1=$(head -1 /proc/stat)
  sleep 0.5
  local cpu_line2=$(head -1 /proc/stat)
  local idle1=$(echo "$cpu_line1" | awk '{print $5}')
  local total1=$(echo "$cpu_line1" | awk '{s=0; for(i=2;i<=NF;i++) s+=$i; print s}')
  local idle2=$(echo "$cpu_line2" | awk '{print $5}')
  local total2=$(echo "$cpu_line2" | awk '{s=0; for(i=2;i<=NF;i++) s+=$i; print s}')
  local cpu_usage=$(awk "BEGIN {d=$total2-$total1; if(d>0) printf \"%.1f\", (1-($idle2-$idle1)/d)*100; else print 0}")

  # Memory
  local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
  local mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
  local mem_used=$((mem_total - mem_avail))
  local mem_percent=$(awk "BEGIN {printf \"%.1f\", ($mem_used/$mem_total)*100}")
  local mem_total_bytes=$((mem_total * 1024))
  local mem_used_bytes=$((mem_used * 1024))
  local mem_free_bytes=$((mem_avail * 1024))

  # Disk (root partition)
  local disk_info=$(df -k / | tail -1)
  local disk_total=$(echo "$disk_info" | awk '{print $2}')
  local disk_used=$(echo "$disk_info" | awk '{print $3}')
  local disk_percent=$(echo "$disk_info" | awk '{print $5}' | tr -d '%')
  local disk_total_bytes=$((disk_total * 1024))
  local disk_used_bytes=$((disk_used * 1024))

  # Load averages
  local load_avg=$(cat /proc/loadavg)
  local load_1m=$(echo "$load_avg" | awk '{print $1}')
  local load_5m=$(echo "$load_avg" | awk '{print $2}')
  local load_15m=$(echo "$load_avg" | awk '{print $3}')

  # Uptime
  local uptime_sec=$(awk '{print int($1)}' /proc/uptime)

  # Network (primary interface)
  local net_iface=$(ip route | grep default | awk '{print $5}' | head -1)
  local rx_bytes=0 tx_bytes=0
  if [[ -n "$net_iface" && -f "/sys/class/net/${net_iface}/statistics/rx_bytes" ]]; then
    rx_bytes=$(cat "/sys/class/net/${net_iface}/statistics/rx_bytes" 2>/dev/null || echo 0)
    tx_bytes=$(cat "/sys/class/net/${net_iface}/statistics/tx_bytes" 2>/dev/null || echo 0)
  fi

  # Process count
  local proc_count=$(ls -1 /proc | grep -c '^[0-9]' 2>/dev/null || echo 0)

  # Docker containers (if available)
  local docker_running=0 docker_total=0
  if command -v docker &>/dev/null; then
    docker_running=$(docker ps -q 2>/dev/null | wc -l || echo 0)
    docker_total=$(docker ps -aq 2>/dev/null | wc -l || echo 0)
  fi

  # CPU count
  local cpu_count=$(nproc 2>/dev/null || grep -c processor /proc/cpuinfo 2>/dev/null || echo 1)

  # Build metrics JSON
  cat << METRICS
{
  "sourceAgent": "${agent}",
  "agentVersion": "${VERSION}",
  "platform": "linux",
  "timestamp": $timestamp,
  $([ -n "$ORG_ID" ] && echo "\"orgId\": \"${ORG_ID}\",")
  "metrics": [
    {"name": "system_cpu_usage_percent", "value": $cpu_usage, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_cpu_count", "value": $cpu_count, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_memory_usage_percent", "value": $mem_percent, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_memory_total_bytes", "value": $mem_total_bytes, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_memory_used_bytes", "value": $mem_used_bytes, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_memory_free_bytes", "value": $mem_free_bytes, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_disk_usage_percent", "value": $disk_percent, "labels": {"host": "$host", "mount": "/"}, "timestamp": $timestamp},
    {"name": "system_disk_total_bytes", "value": $disk_total_bytes, "labels": {"host": "$host", "mount": "/"}, "timestamp": $timestamp},
    {"name": "system_disk_used_bytes", "value": $disk_used_bytes, "labels": {"host": "$host", "mount": "/"}, "timestamp": $timestamp},
    {"name": "system_load_1m", "value": $load_1m, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_load_5m", "value": $load_5m, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_load_15m", "value": $load_15m, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_uptime_seconds", "value": $uptime_sec, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "system_network_rx_bytes", "value": $rx_bytes, "labels": {"host": "$host", "interface": "${net_iface:-eth0}"}, "timestamp": $timestamp},
    {"name": "system_network_tx_bytes", "value": $tx_bytes, "labels": {"host": "$host", "interface": "${net_iface:-eth0}"}, "timestamp": $timestamp},
    {"name": "system_process_count", "value": $proc_count, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "docker_container_running", "value": $docker_running, "labels": {"host": "$host"}, "timestamp": $timestamp},
    {"name": "docker_container_total", "value": $docker_total, "labels": {"host": "$host"}, "timestamp": $timestamp}
  ]
}
METRICS
}

# Main loop
echo "[Nova Agent] Collecting metrics every ${SEND_INTERVAL}s, heartbeat every ${HEARTBEAT_INTERVAL}s"
while true; do
  if [[ -n "$AUTH_KEY" && -n "$ENDPOINT" ]]; then
    # Collect and send metrics
    metrics_json=$(collect_metrics 2>/dev/null)
    if [[ -n "$metrics_json" ]]; then
      http_code=$(curl -sS -o /dev/null -w "%{http_code}" -X POST "${ENDPOINT}/ingest/metrics" \
        -H "X-Agent-API-Key: $AUTH_KEY" \
        -H "Content-Type: application/json" \
        -d "$metrics_json" 2>/dev/null)
      if [[ "$http_code" == "200" ]]; then
        echo "[Nova Agent] Metrics sent (18 metrics)"
      else
        echo "[Nova Agent] Metrics send failed (HTTP $http_code)"
      fi
    fi

    # Send heartbeat every HEARTBEAT_INTERVAL
    HEARTBEAT_COUNTER=$((HEARTBEAT_COUNTER + SEND_INTERVAL))
    if [[ $HEARTBEAT_COUNTER -ge $HEARTBEAT_INTERVAL ]]; then
      HEARTBEAT_COUNTER=0
      curl -sS -X POST "${ENDPOINT}/agents/heartbeat" \
        -H "X-Agent-API-Key: $AUTH_KEY" \
        -H "Content-Type: application/json" \
        -d "{\"hostname\":\"${NODE_NAME:-$(hostname)}\",\"timestamp\":$(date +%s),\"status\":\"online\",\"agentVersion\":\"${VERSION}\"}" \
        > /dev/null 2>&1
      echo "[Nova Agent] Heartbeat sent"
    fi
  else
    echo "[Nova Agent] ERROR: No auth key or endpoint configured"
  fi
  sleep $SEND_INTERVAL
done
AGENT_EOF

  chmod 755 "$BINARY_PATH"
  success "Agent v2.0.0 installed to $BINARY_PATH"
}

write_config() {
  step "Creating configuration"

  mkdir -p "$CONFIG_DIR" "$DATA_DIR" "$LOG_DIR"

  printf "api_key: %s\nnode_name: %s\nendpoint_url: %s\nlog_level: info\nlog_file: %s\ndata_dir: %s\nmetrics_interval: 15\nheartbeat_interval: 30\n" \
    "$NOVA_API_KEY" "$NOVA_NODE_NAME" "$NOVA_ENDPOINT" "${LOG_DIR}/agent.log" "$DATA_DIR" \
    > "$CONFIG_FILE"

  chmod 600 "$CONFIG_FILE"
  success "Configuration written to $CONFIG_FILE"
}

create_systemd_unit() {
  step "Creating systemd service"

  cat > "$SYSTEMD_UNIT_FILE" << EOF
[Unit]
Description=NOVA AI Ops Agent
Documentation=https://docs.novaaiops.com/agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
Group=root
ExecStart=${BINARY_PATH} --config=${CONFIG_FILE}
Restart=on-failure
RestartSec=10s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=${SERVICE_NAME}

# Security hardening
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

  success "Systemd unit created"
}

start_service() {
  step "Starting Nova AI agent service"

  systemctl daemon-reload
  systemctl enable "$SERVICE_NAME" 2>/dev/null || true

  if systemctl start "$SERVICE_NAME"; then
    sleep 2
    if systemctl is-active --quiet "$SERVICE_NAME"; then
      success "Service started and running"
    else
      warn "Service started but may have issues"
      info "Check logs: journalctl -u $SERVICE_NAME -n 50"
    fi
  else
    error "Failed to start service"
    info "Check logs: journalctl -u $SERVICE_NAME -n 50"
    exit 1
  fi
}

register_agent() {
  step "Registering agent with Nova AI"

  # Exchange install token for agent credentials
  local response
  response=$(curl -sS -X POST "${NOVA_ENDPOINT}/agent/register" \
    -H "Content-Type: application/json" \
    -d "{
      \"token\": \"${NOVA_API_KEY}\",
      \"hostname\": \"${NOVA_NODE_NAME}\",
      \"osType\": \"linux\",
      \"agentVersion\": \"1.0.0\",
      \"metadata\": {
        \"arch\": \"$(detect_arch)\",
        \"installer\": \"curl-install\"
      }
    }" 2>&1)

  # Check if registration succeeded
  if echo "$response" | grep -q '"success":true'; then
    # Extract agent credentials from response
    AGENT_ID=$(echo "$response" | grep -o '"agentId":"[^"]*"' | cut -d'"' -f4)
    AGENT_SECRET=$(echo "$response" | grep -o '"agentSecret":"[^"]*"' | cut -d'"' -f4)

    if [[ -n "$AGENT_ID" && -n "$AGENT_SECRET" ]]; then
      success "Agent registered: $AGENT_ID"

      # Write config with printf to guarantee single-line values (heredoc + long
      # keys can wrap in some terminal/shell combinations, breaking YAML parsing)
      printf "agent_id: %s\nagent_secret: %s\napi_key: %s\nnode_name: %s\nendpoint_url: %s\nlog_level: info\nlog_file: %s\ndata_dir: %s\nmetrics_interval: 15\nheartbeat_interval: 30\n" \
        "$AGENT_ID" "$AGENT_SECRET" "$AGENT_SECRET" "$NOVA_NODE_NAME" "$NOVA_ENDPOINT" "${LOG_DIR}/agent.log" "$DATA_DIR" \
        > "$CONFIG_FILE"
      chmod 600 "$CONFIG_FILE"
      success "Config updated with agent credentials"
    else
      warn "Could not parse agent credentials from response"
      info "Response: $response"
    fi
  else
    warn "Agent registration failed - will use install token for auth"
    info "Response: $response"
  fi
}

send_initial_heartbeat() {
  step "Sending initial heartbeat"

  # Determine auth header based on available credentials
  local auth_header
  if [[ -f "$CONFIG_FILE" ]]; then
    local agent_secret=$(grep "agent_secret:" "$CONFIG_FILE" 2>/dev/null | awk '{print $2}')
    if [[ -n "$agent_secret" ]]; then
      auth_header="X-Agent-API-Key: $agent_secret"
    else
      auth_header="X-Agent-API-Key: ${NOVA_API_KEY}"
    fi
  else
    auth_header="X-Agent-API-Key: ${NOVA_API_KEY}"
  fi

  local response
  if response=$(curl -sS -X POST "${NOVA_ENDPOINT}/agents/heartbeat" \
    -H "$auth_header" \
    -H "Content-Type: application/json" \
    -d "{
      \"hostname\": \"${NOVA_NODE_NAME}\",
      \"os\": \"linux\",
      \"arch\": \"$(detect_arch)\",
      \"agentVersion\": \"1.0.0\",
      \"timestamp\": $(date +%s)
    }" 2>&1); then
    success "Heartbeat sent"
  else
    warn "Initial heartbeat failed (agent will retry)"
    info "Response: $response"
  fi
}

print_summary() {
  echo ""
  tri_rule 72
  echo ""
  echo -e "    ${BOLD}${BRAND}✓  INSTALLATION COMPLETE${RESET}      ${DIM}— Nova AI agent is now reporting${RESET}"
  echo ""
  echo -e "    ${DIM}Service${RESET}    ${BRAND}$SERVICE_NAME (running)${RESET}"
  echo -e "    ${DIM}Binary${RESET}     ${FG}$BINARY_PATH${RESET}"
  echo -e "    ${DIM}Config${RESET}     ${FG}$CONFIG_FILE${RESET}"
  echo -e "    ${DIM}Logs${RESET}       ${FG}journalctl -u $SERVICE_NAME -f${RESET}"
  echo ""
  echo -e "    ${BOLD}${LIME}Next steps${RESET}"
  echo -e "      ${DIM}1.${RESET}  ${LIME}https://app.novaaiops.com/instances${RESET}     ${DIM}— see your instance live${RESET}"
  echo -e "      ${DIM}2.${RESET}  ${BRAND}systemctl status $SERVICE_NAME${RESET}    ${DIM}— quick health check${RESET}"
  echo -e "      ${DIM}3.${RESET}  ${FOREST}journalctl -u $SERVICE_NAME -f${RESET}    ${DIM}— tail the agent logs${RESET}"
  echo ""
  tri_rule 72
  echo ""
}

main() {
  # print_logo already prints the WELCOME caption + tagline + tri-rule
  # frame; the redundant "NOVA AI AGENT INSTALLER" double-rule block that
  # used to sit here was making the header read as two competing titles.
  print_logo

  check_root
  check_prerequisites
  check_api_key

  # Check for existing installation
  if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
    warn "Nova AI agent is already installed and running"
    info "To reinstall, first run: systemctl stop $SERVICE_NAME"
    info "Then run this installer again"
    exit 0
  fi

  download_agent
  write_config
  register_agent
  create_systemd_unit
  start_service
  send_initial_heartbeat

  print_summary
}

main "$@"
