#!/bin/bash

###############################################################################
# Pinguzo Agent Installer
#
# Usage:
#   curl -fsSL https://files.pinguzo.com/install-agent.sh | \
#     sudo bash -s -- --agent-key=YOUR_64_CHAR_KEY
#
#   With a specific edge:
#   curl -fsSL https://files.pinguzo.com/install-agent.sh | \
#     sudo bash -s -- --agent-key=YOUR_64_CHAR_KEY --edge=us-ash.pinguzo.com
###############################################################################

set -e

echo "=================================================="
echo "  Pinguzo Agent Installer"
echo "=================================================="
echo ""

# ── Root check ────────────────────────────────────────────────────────────────
if [ "$EUID" -ne 0 ]; then
    echo "Please run as root (use sudo)"
    exit 1
fi

# ── Configuration ─────────────────────────────────────────────────────────────
AGENT_SCRIPT_URL="https://nuftp.com/pinguzo-agent.sh"
CENTRAL_URL="https://cp.pinguzo.com"

# Known edge servers — hostname only, URL is built internally
declare -A EDGE_SERVERS
EDGE_SERVERS["us-ash"]="us-ash.pinguzo.com"
EDGE_SERVERS["eu-fr"]="eu-fr.pinguzo.com"
EDGE_SERVERS["in-mum"]="in-mum.pinguzo.com"

# Installation paths
INSTALL_DIR="/usr/local/pinguzo"
AGENT_SCRIPT="$INSTALL_DIR/bin/pinguzo-agent.sh"
CONFIG_FILE="$INSTALL_DIR/config/agent.conf"
QUEUE_DIR="$INSTALL_DIR/queue"
LOG_DIR="/var/log/pinguzo"
LOG_FILE="$LOG_DIR/agent.log"

# ── Parse arguments (--key=value style) ───────────────────────────────────────
AGENT_KEY=""
EDGE_HOSTNAME_OVERRIDE=""

for arg in "$@"; do
    case "$arg" in
        --agent-key=*)
            AGENT_KEY="${arg#*=}"
            ;;
        --edge=*)
            EDGE_HOSTNAME_OVERRIDE="${arg#*=}"
            ;;
        --help)
            echo "Usage:"
            echo "  sudo bash install-agent.sh --agent-key=YOUR_64_CHAR_KEY"
            echo "  sudo bash install-agent.sh --agent-key=YOUR_64_CHAR_KEY --edge=us-ash.pinguzo.com"
            echo ""
            echo "Options:"
            echo "  --agent-key=KEY    64-character agent key from your Pinguzo dashboard (required)"
            echo "  --edge=HOSTNAME    Edge server hostname, e.g. us-ash.pinguzo.com (optional)"
            echo "                     Omit to auto-detect the lowest-latency edge server"
            echo ""
            echo "Available edge hostnames:"
            for id in "${!EDGE_SERVERS[@]}"; do
                echo "  ${EDGE_SERVERS[$id]}"
            done
            echo ""
            echo "One-liner install example:"
            echo "  curl -fsSL https://files.pinguzo.com/install-agent.sh | \\"
            echo "    sudo bash -s -- --agent-key=YOUR_64_CHAR_KEY"
            exit 0
            ;;
        *)
            echo "Unknown option: $arg"
            echo "Use --help for usage information"
            exit 1
            ;;
    esac
done

# ── Validate agent key ────────────────────────────────────────────────────────
if [ -z "$AGENT_KEY" ]; then
    echo "✗ Error: --agent-key is required"
    echo ""
    echo "Usage: sudo bash install-agent.sh --agent-key=YOUR_64_CHAR_KEY"
    echo "Use --help for more information"
    exit 1
fi

# Basic format check: must be 64 hex chars
if ! echo "$AGENT_KEY" | grep -qE '^[a-f0-9]{64}$'; then
    echo "✗ Error: agent key must be a 64-character hex string"
    echo "  Got: ${#AGENT_KEY} characters"
    exit 1
fi

# ── Resolve API URL ───────────────────────────────────────────────────────────
# Always build the full metrics URL from a hostname — never accept a raw URL.
build_metrics_url() {
    echo "https://${1}/api/v1/metrics.php"
}

if [ -n "$EDGE_HOSTNAME_OVERRIDE" ]; then
    # Strip any accidental https:// or path the user may have typed
    EDGE_HOSTNAME_OVERRIDE=$(echo "$EDGE_HOSTNAME_OVERRIDE" \
        | sed 's|^https\?://||' | cut -d'/' -f1)

    echo "→ Verifying specified edge: $EDGE_HOSTNAME_OVERRIDE"

    PROBE_TMP=$(mktemp)
    probe_info=$(curl -s -o "$PROBE_TMP" -w '%{http_code}:%{time_total}' \
        --max-time 5 "https://${EDGE_HOSTNAME_OVERRIDE}/healthz.php" 2>/dev/null) \
        || probe_info="0:9999"

    http_code="${probe_info%%:*}"
    response_time="${probe_info##*:}"
    body=$(cat "$PROBE_TMP" 2>/dev/null || true)
    rm -f "$PROBE_TMP"

    if [ "$http_code" != "200" ] || [ "$body" != "OK" ]; then
        echo "✗ Edge server is not reachable or unhealthy (HTTP ${http_code:-0})"
        echo "  Check the hostname and try again, or omit --edge to auto-detect."
        exit 1
    fi

    echo "  Response time: ${response_time}s ✓ healthy"
    EDGE_BASE_URL="https://$EDGE_HOSTNAME_OVERRIDE"
    API_URL=$(build_metrics_url "$EDGE_HOSTNAME_OVERRIDE")
    echo "  Endpoint: $API_URL"
else
    echo "→ Auto-detecting closest edge server..."

    FASTEST_HOST=""
    FASTEST_TIME=9999
    PROBE_TMP=$(mktemp)

    for id in "${!EDGE_SERVERS[@]}"; do
        host="${EDGE_SERVERS[$id]}"
        healthz_url="https://${host}/healthz.php"
        echo "  Testing $id ($host)..."

        # Capture HTTP code + response time together; body goes to temp file
        probe_info=$(curl -s -o "$PROBE_TMP" -w '%{http_code}:%{time_total}' \
            --max-time 5 "$healthz_url" 2>/dev/null) || probe_info="0:9999"

        http_code="${probe_info%%:*}"
        response_time="${probe_info##*:}"
        body=$(cat "$PROBE_TMP" 2>/dev/null || true)

        # Only accept the edge if it returns HTTP 200 and body is exactly "OK"
        if [ "$http_code" = "200" ] && [ "$body" = "OK" ]; then
            echo "    Response time: ${response_time}s ✓ healthy"
            if (( $(echo "$response_time < $FASTEST_TIME" | bc -l 2>/dev/null || echo 0) )); then
                FASTEST_TIME=$response_time
                FASTEST_HOST=$host
                FASTEST_ID=$id
            fi
        else
            echo "    Skipped — not reachable or unhealthy (HTTP ${http_code:-0})"
        fi
    done

    rm -f "$PROBE_TMP"

    if [ -z "$FASTEST_HOST" ]; then
        echo "✗ No healthy edge servers found"
        echo "  All edge servers are offline, or specify one manually:"
        echo "  sudo bash install-agent.sh --agent-key=YOUR_KEY --edge=in-mum.pinguzo.com"
        exit 1
    fi

    EDGE_BASE_URL="https://$FASTEST_HOST"
    API_URL=$(build_metrics_url "$FASTEST_HOST")
    echo "✓ Selected: $FASTEST_ID ($FASTEST_HOST) — ${FASTEST_TIME}s"
fi

# ── Register edge assignment on central ───────────────────────────────────────
# Tells central which edge this server belongs to so it can push the server
# record to the edge BEFORE the first metrics run (avoids relay path on run 1).
SELECTED_EDGE_HOST="${EDGE_BASE_URL#https://}"
echo "→ Registering edge assignment with central..."
reg_response=$(curl -s -w "\n%{http_code}" -X POST \
    "${CENTRAL_URL}/api/v1/agent-edge-init.php" \
    -H "Content-Type: application/json" \
    -H "X-Agent-Key: $AGENT_KEY" \
    -d "{\"edge_hostname\":\"${SELECTED_EDGE_HOST}\"}" \
    --max-time 15 --connect-timeout 5 2>/dev/null)
reg_code=$(echo "$reg_response" | tail -1)
if [ "$reg_code" = "200" ]; then
    echo "✓ Edge assignment registered — sync will complete within 30 seconds"
else
    echo "⚠ Edge pre-registration skipped (HTTP ${reg_code:-0}) — will register automatically on first metrics send"
fi

# ── Create directories ────────────────────────────────────────────────────────
echo "→ Creating directories..."
mkdir -p "$INSTALL_DIR/bin" "$INSTALL_DIR/config" "$QUEUE_DIR" "$LOG_DIR"

# ── Download agent script ─────────────────────────────────────────────────────
echo "→ Downloading Pinguzo agent..."
if curl -fsSL "$AGENT_SCRIPT_URL" -o "$AGENT_SCRIPT"; then
    chmod +x "$AGENT_SCRIPT"
    echo "✓ Agent downloaded"
else
    echo "✗ Failed to download agent from $AGENT_SCRIPT_URL"
    exit 1
fi

# ── Write config file ─────────────────────────────────────────────────────────
echo "→ Writing configuration..."
cat > "$CONFIG_FILE" << EOF
# Pinguzo Agent Configuration
# Generated by install-agent.sh on $(date -u '+%Y-%m-%d %H:%M UTC')
PINGUZO_API_URL="$EDGE_BASE_URL"
PINGUZO_AGENT_KEY="$AGENT_KEY"
PINGUZO_QUEUE_DIR="$QUEUE_DIR"
PINGUZO_LOG_FILE="$LOG_FILE"
EOF

chmod 600 "$CONFIG_FILE"
echo "✓ Config written to $CONFIG_FILE"

# ── Set up cron ───────────────────────────────────────────────────────────────
echo "→ Setting up cron jobs..."

# Randomise daily update time to spread load across agents
RANDOM_HOUR=$(( RANDOM % 24 ))
RANDOM_MIN=$(( RANDOM % 60 ))

cat > /etc/cron.d/pinguzo << EOF
# Pinguzo monitoring agent — runs every minute
* * * * * root $AGENT_SCRIPT >> $LOG_FILE 2>&1

# Pinguzo update check — once per day at a randomised time
$RANDOM_MIN $RANDOM_HOUR * * * root $AGENT_SCRIPT --updates >> $LOG_FILE 2>&1
EOF
chmod 644 /etc/cron.d/pinguzo
echo "✓ Cron installed"

# ── Test run ──────────────────────────────────────────────────────────────────
echo "→ Running agent test..."
if "$AGENT_SCRIPT"; then
    echo "✓ Agent test successful"
else
    echo "⚠ Agent test failed — check logs: $LOG_FILE"
    echo "  The cron job will retry automatically every minute"
fi

# ── Summary ───────────────────────────────────────────────────────────────────
echo ""
echo "=================================================="
echo "  Installation Complete!"
echo "=================================================="
echo ""
echo "  Edge endpoint:  $API_URL"
echo "  Agent key:      ${AGENT_KEY:0:8}...${AGENT_KEY: -8}"
echo "  Install dir:    $INSTALL_DIR"
echo "  Log file:       $LOG_FILE"
echo "  Metrics cron:   every minute"
echo "  Update cron:    daily at ${RANDOM_HOUR}:$(printf '%02d' $RANDOM_MIN) (randomised)"
echo ""
echo "Useful commands:"
echo "  Test agent:   $AGENT_SCRIPT"
echo "  View logs:    tail -f $LOG_FILE"
echo "  Check cron:   cat /etc/cron.d/pinguzo"
echo "  Uninstall:    sudo $AGENT_SCRIPT --uninstall"
echo ""
