#!/bin/bash
# ================================================================
# Nexus Agent Install Script
# Usage: curl -fsSL https://YOUR_NEXUS_DOMAIN/agent/install.sh | bash -s -- --url https://YOUR_NEXUS_DOMAIN --key API_KEY --id SERVER_ID
#
# Network model:
#   - Heartbeat: child → central HTTPS (443 outbound), no inbound 8601 required
#   - Scripts / push: central → child SSH (22)
#   - Agent HTTP listens on 127.0.0.1 only (local); not exposed on public 8601
# ================================================================

set -e

CENTRAL_URL=""
WEB_URL=""
API_KEY=""
SERVER_ID=""
AGENT_PORT="8601"
INSTALL_DIR="/opt/nexus-agent"

# --- Python dependency versions (single source of truth) ---
FASTAPI_VER="0.115.6"
UVICORN_VER="0.34.0"
HTTPX_VER="0.28.1"
PSUTIL_VER=""          # latest
MULTIPART_VER="0.0.19"

# --- Privilege detection ---
if [ "$(id -u)" -eq 0 ]; then
    SUDO=""
else
    if command -v sudo >/dev/null 2>&1; then
        # Test passwordless sudo (-n = non-interactive)
        if sudo -n true 2>/dev/null; then
            SUDO="sudo"
            echo "  Non-root user detected — using sudo for privileged operations."
        else
            echo "ERROR: sudo requires a password. Configure passwordless sudo first:"
            echo "       echo \"$(whoami) ALL=(ALL) NOPASSWD:ALL\" | sudo tee /etc/sudoers.d/nexus-agent"
            exit 1
        fi
    else
        echo "ERROR: Running as non-root and sudo is not available."
        echo "       Either run as root or install sudo."
        exit 1
    fi
fi

while [[ $# -gt 0 ]]; do
    case $1 in
        --url)      CENTRAL_URL="$2"; shift 2 ;;
        --web-url)  WEB_URL="$2"; shift 2 ;;
        --key)      API_KEY="$2"; shift 2 ;;
        --id)       SERVER_ID="$2"; shift 2 ;;
        --port)     AGENT_PORT="$2"; shift 2 ;;
        *)          shift ;;
    esac
done

[ -z "$CENTRAL_URL" ] && echo "ERROR: --url is required" && exit 1
[ -z "$SERVER_ID" ] && echo "ERROR: --id is required (server ID from Nexus dashboard)" && exit 1
[ -z "$API_KEY" ] && echo "ERROR: --key is required (API key from Nexus settings)" && exit 1

echo ""
echo "=========================================="
echo "  Nexus Agent Install"
echo "=========================================="
echo "  Server:  $CENTRAL_URL"
echo "  ID:      $SERVER_ID"
echo "  Port:    ${AGENT_PORT} (localhost only)"
echo "=========================================="
echo ""

# 0. Stop existing service + kill stale processes on the port
echo "[0/7] Clean up old installation..."
$SUDO systemctl stop nexus-agent 2>/dev/null || true
# Kill any process occupying the agent port (stale process from manual start, etc.)
if command -v fuser >/dev/null 2>&1; then
    $SUDO fuser -k "${AGENT_PORT}"/tcp 2>/dev/null || true
elif command -v ss >/dev/null 2>&1; then
    PID=$(ss -tlnp 2>/dev/null | grep ":${AGENT_PORT}" | grep -oP 'pid=\K[0-9]+' | head -1)
    [ -n "$PID" ] && kill "$PID" 2>/dev/null || true
elif command -v netstat >/dev/null 2>&1; then
    PID=$(netstat -tlnp 2>/dev/null | grep ":${AGENT_PORT}" | awk '{print $7}' | cut -d'/' -f1 | head -1)
    [ -n "$PID" ] && kill "$PID" 2>/dev/null || true
fi
echo "  Old service stopped, port cleared"

# 1. Resolve Python 3.10+ (prefer system 3.12 on BT panels; skip 3.7 pyenv)
echo "[1/7] Resolve Python 3.10+..."
PYTHON=""
for candidate in python3.12 python3.11 python3.10 /usr/bin/python3.12 /usr/bin/python3.11 /usr/bin/python3.10 python3; do
    if command -v "$candidate" >/dev/null 2>&1; then
        ver=$("$candidate" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || true)
        major=${ver%%.*}
        minor=${ver#*.}
        if [ -n "$major" ] && [ "$major" -eq 3 ] && [ "${minor:-0}" -ge 10 ] 2>/dev/null; then
            PYTHON="$candidate"
            break
        fi
    fi
done
if [ -z "$PYTHON" ]; then
    echo "ERROR: Python 3.10+ required (found only older pyenv/BT Python?). Install system python3.12."
    exit 1
fi
echo "  Using: $PYTHON ($($PYTHON --version 2>&1))"

# 2. Ensure rsync (required for push/sync)
echo "[2/7] Check rsync..."
if ! command -v rsync >/dev/null 2>&1; then
    echo "  rsync not found — installing..."
    if command -v apt-get >/dev/null 2>&1; then
        $SUDO apt-get update -qq && $SUDO apt-get install -y -qq rsync
    elif command -v yum >/dev/null 2>&1; then
        $SUDO yum install -y -q rsync
    elif command -v dnf >/dev/null 2>&1; then
        $SUDO dnf install -y -q rsync
    elif command -v apk >/dev/null 2>&1; then
        $SUDO apk add --quiet rsync
    else
        echo "ERROR: Cannot detect package manager. Please install rsync manually."
        exit 1
    fi
    echo "  rsync installed OK"
else
    echo "  rsync already available"
fi

# 3. Create dir + venv
echo "[3/7] Create venv..."
VENV_DIR="${INSTALL_DIR}/.venv"
$SUDO mkdir -p "$INSTALL_DIR"
# If using sudo, give ownership to current user so venv/pip work without sudo
if [ -n "$SUDO" ]; then
    $SUDO chown -R "$(id -u):$(id -g)" "$INSTALL_DIR"
fi
if [ ! -f "$VENV_DIR/bin/activate" ]; then
    # Allow venv creation to fail (set -e won't abort) so we can install python3-venv
    "$PYTHON" -m venv "$VENV_DIR" 2>/dev/null || true
    # venv creation fails when python3-venv is missing — check if activate exists
    if [ ! -f "$VENV_DIR/bin/activate" ]; then
        echo "  venv incomplete — installing python3-venv..."
        $SUDO apt-get update -qq && $SUDO apt-get install -y -qq "python$( "$PYTHON" -c 'import sys;print(f"{sys.version_info.major}.{sys.version_info.minor}")' )-venv" 2>/dev/null \
            || $SUDO apt-get install -y -qq python3-venv 2>/dev/null \
            || { echo "ERROR: Cannot install python3-venv. Run: $SUDO apt install python3-venv"; exit 1; }
        rm -rf "$VENV_DIR"
        "$PYTHON" -m venv "$VENV_DIR"
        if [ ! -f "$VENV_DIR/bin/activate" ]; then
            echo "ERROR: venv creation failed even after installing python3-venv"
            exit 1
        fi
    fi
fi
# shellcheck disable=SC1091
source "$VENV_DIR/bin/activate"
pip install -q --upgrade pip
PIP_DEPS="fastapi==${FASTAPI_VER} uvicorn==${UVICORN_VER} httpx==${HTTPX_VER} python-multipart==${MULTIPART_VER}"
[ -n "$PSUTIL_VER" ] && PIP_DEPS="${PIP_DEPS} psutil==${PSUTIL_VER}" || PIP_DEPS="${PIP_DEPS} psutil"
pip install -q $PIP_DEPS

# 4. Download agent.py
echo "[4/7] Download agent.py..."
[ -z "$WEB_URL" ] && WEB_URL="${CENTRAL_URL}"
curl -fsSL "${WEB_URL}/agent/agent.py" -o "$INSTALL_DIR/agent.py" || {
    echo "ERROR: Cannot download from $WEB_URL/agent/agent.py"
    exit 1
}

# 5. Config
echo "[5/7] Write config..."
CENTRAL_HOST=$(echo "${CENTRAL_URL}" | sed 's~https\?://~~' | cut -d'/' -f1 | cut -d':' -f1)

cat > "$INSTALL_DIR/config.json" << EOF
{
  "server_id": ${SERVER_ID},
  "central": { "url": "${CENTRAL_URL}", "api_key": "${API_KEY}" },
  "api_key": "${API_KEY}",
  "heartbeat_interval": 60,
  "allowed_ips": ["${CENTRAL_HOST}"],
  "log_file": "/var/log/nexus-agent.log",
  "log_level": "INFO",
  "server": { "host": "127.0.0.1", "port": ${AGENT_PORT} }
}
EOF
echo "  IP allowlist (Agent HTTP): ${CENTRAL_HOST}"
echo "  Note: inbound TCP ${AGENT_PORT} is NOT required (heartbeat uses HTTPS outbound)."

# 6. systemd + start (bind localhost only)
echo "[6/7] Setup systemd + start..."

$SUDO tee /etc/systemd/system/nexus-agent.service > /dev/null << EOF
[Unit]
Description=Nexus Agent
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=${INSTALL_DIR}
Environment=PATH=${VENV_DIR}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ExecStart=${VENV_DIR}/bin/python -m uvicorn agent:app --host 127.0.0.1 --port ${AGENT_PORT} --log-level info
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

$SUDO systemctl daemon-reload
$SUDO systemctl enable nexus-agent
$SUDO systemctl start nexus-agent
sleep 2

STATUS="running"
$SUDO systemctl is-active --quiet nexus-agent || STATUS="FAILED"

# 7. Verify
echo "[7/7] Verify..."
HOSTNAME=$(hostname 2>/dev/null || echo "unknown")
IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo "unknown")

echo ""
echo "=========================================="
echo "  Done! Status: ${STATUS}"
echo "=========================================="
echo ""
echo "  Heartbeat:  ${CENTRAL_URL}/api/agent/heartbeat (HTTPS outbound)"
echo "  Agent HTTP: 127.0.0.1:${AGENT_PORT} (local only, no public firewall rule needed)"
echo "  Scripts:    via SSH port 22 from Nexus center"
echo "  Server ID:  ${SERVER_ID}"
echo ""
echo "  Commands:"
echo "    systemctl status nexus-agent"
echo "    journalctl -u nexus-agent -f"
echo "    systemctl restart nexus-agent"
echo ""
