#!/bin/sh
# Datargo Agent — installer (Linux/macOS).
#
#   DATARGO_TOKEN=dgra_… sh -c "$(curl -fsSL https://agent.datargo.com/install.sh)"
#
# Detects OS/arch, downloads the matching binary, verifies its SHA-256 checksum,
# installs it to /usr/local/bin, registers the host (when DATARGO_TOKEN is set)
# and sets it up as a persistent service:
#   - Linux: hardened systemd unit, runs as a dedicated non-root user
#   - macOS: LaunchDaemon (com.datargo.agent), runs at boot, KeepAlive
# Outbound-only, no remote code execution.
#
# Env overrides (CI/tests): DATARGO_BASE_URL, INSTALL_DIR, DATARGO_SERVER,
# DATARGO_NO_ENROLL=1 (binary only), DATARGO_NO_SERVICE=1 (no service).
set -eu

BASE_URL="${DATARGO_BASE_URL:-https://agent.datargo.com}"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
BIN_NAME="datargo-agent"
SVC_USER="datargo-agent"            # dedicated service user (Linux)
STATE_DIR="/var/lib/datargo-agent"
PLIST="/Library/LaunchDaemons/com.datargo.agent.plist"
UNIT="/etc/systemd/system/datargo-agent.service"

info() { printf '\033[1;34m›\033[0m %s\n' "$1"; }
ok() { printf '\033[1;32m✓\033[0m %s\n' "$1"; }
die() { printf '\033[1;31m✗ %s\033[0m\n' "$1" >&2; exit 1; }

# ── OS/arch → asset ────────────────────────────────────────────────────────
os="$(uname -s)"
arch="$(uname -m)"
case "$os" in
  Linux)
    case "$arch" in
      x86_64 | amd64) asset="datargo-agent-linux-x86_64" ;;
      aarch64 | arm64) asset="datargo-agent-linux-aarch64" ;;
      *) die "unsupported architecture: $arch" ;;
    esac
    ;;
  Darwin) asset="datargo-agent-macos-universal" ;;
  *) die "unsupported OS: $os (Windows: coming soon via MSI)" ;;
esac

command -v curl >/dev/null 2>&1 || die "curl is required"

# sudo command if available (empty when root). Only required where root is truly
# needed (enroll + service) — not for a binary-only install into a writable
# INSTALL_DIR (e.g. CI/tests with INSTALL_DIR=/tmp/…).
SUDO_CMD=""
if [ "$(id -u)" -ne 0 ] && command -v sudo >/dev/null 2>&1; then
  SUDO_CMD="sudo"
fi

tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT INT TERM

# ── Download ───────────────────────────────────────────────────────────────
info "Downloading $asset from $BASE_URL …"
curl -fsSL -o "$tmp/$BIN_NAME" "$BASE_URL/$asset" || die "download failed"
curl -fsSL -o "$tmp/SHA256SUMS" "$BASE_URL/SHA256SUMS" || die "SHA256SUMS download failed"

# ── Verify checksum ────────────────────────────────────────────────────────
info "Verifying checksum …"
want="$(awk -v a="$asset" '$2 == a { print $1 }' "$tmp/SHA256SUMS")"
[ -n "$want" ] || die "no checksum for $asset in SHA256SUMS"
if command -v sha256sum >/dev/null 2>&1; then
  got="$(sha256sum "$tmp/$BIN_NAME" | awk '{print $1}')"
elif command -v shasum >/dev/null 2>&1; then
  got="$(shasum -a 256 "$tmp/$BIN_NAME" | awk '{print $1}')"
else
  die "neither sha256sum nor shasum available"
fi
[ "$want" = "$got" ] || die "checksum mismatch (expected $want, got $got)"
chmod +x "$tmp/$BIN_NAME"
ok "checksum ok"

# ── Install ────────────────────────────────────────────────────────────────
# sudo only if INSTALL_DIR (or its parent) is not writable.
INSTALL_SUDO=""
if [ -d "$INSTALL_DIR" ]; then
  [ -w "$INSTALL_DIR" ] || INSTALL_SUDO="$SUDO_CMD"
else
  [ -w "$(dirname "$INSTALL_DIR")" ] || INSTALL_SUDO="$SUDO_CMD"
fi
info "Installing to $INSTALL_DIR/$BIN_NAME …"
$INSTALL_SUDO mkdir -p "$INSTALL_DIR"
$INSTALL_SUDO mv "$tmp/$BIN_NAME" "$INSTALL_DIR/$BIN_NAME"
BIN="$INSTALL_DIR/$BIN_NAME"
ok "$("$BIN" --version 2>/dev/null || echo "$BIN_NAME installed")"

# No token: binary only, no enroll/service.
if [ -z "${DATARGO_TOKEN:-}" ] || [ -n "${DATARGO_NO_ENROLL:-}" ]; then
  printf '\n'
  info "Binary installed. Register + set up the service with your token:"
  printf '    DATARGO_TOKEN=dgra_… %s\n' "sh -c \"\$(curl -fsSL $BASE_URL/install.sh)\""
  exit 0
fi

# From here on root is required (enroll writes to /var/lib, service setup).
if [ "$(id -u)" -ne 0 ] && [ -z "$SUDO_CMD" ]; then
  die "root/sudo required for registration + service setup."
fi

# ── Service user (Linux: dedicated, non-root) ────────────────────────────────
if [ "$os" = "Linux" ] && [ "${DATARGO_NO_SERVICE:-}" != "1" ]; then
  if ! id "$SVC_USER" >/dev/null 2>&1; then
    info "Creating service user $SVC_USER (system, non-login) …"
    $SUDO_CMD useradd --system --no-create-home --shell /usr/sbin/nologin "$SVC_USER" 2>/dev/null \
      || $SUDO_CMD adduser --system --no-create-home --shell /usr/sbin/nologin "$SVC_USER" 2>/dev/null \
      || true
  fi
fi

# ── Register (enroll) ────────────────────────────────────────────────────────
info "Registering host …"
set -- enroll
[ -n "${DATARGO_SERVER:-}" ] && set -- "$@" --server "$DATARGO_SERVER"
$SUDO_CMD env DATARGO_TOKEN="$DATARGO_TOKEN" "$BIN" "$@" \
  || die "registration failed — is the token valid / not expired?"
ok "Host registered."
# Hand the state over to the service user (Linux) — enroll ran as root.
if [ "$os" = "Linux" ] && id "$SVC_USER" >/dev/null 2>&1; then
  $SUDO_CMD chown -R "$SVC_USER":"$SVC_USER" "$STATE_DIR" 2>/dev/null \
    || $SUDO_CMD chown -R "$SVC_USER" "$STATE_DIR" 2>/dev/null || true
  $SUDO_CMD chmod 750 "$STATE_DIR" 2>/dev/null || true
fi

# ── Service setup ────────────────────────────────────────────────────────────
if [ "${DATARGO_NO_SERVICE:-}" = "1" ]; then
  printf '\n'
  info "Service setup skipped (DATARGO_NO_SERVICE=1). Run manually: $BIN_NAME run"
  exit 0
fi

if [ "$os" = "Linux" ]; then
  command -v systemctl >/dev/null 2>&1 || {
    info "no systemd found — start manually: $BIN_NAME run"
    exit 0
  }
  info "Installing systemd unit (hardened, User=$SVC_USER) …"
  $SUDO_CMD sh -c "cat > '$UNIT'" <<UNITEOF
[Unit]
Description=Datargo Agent (host monitoring)
Documentation=https://agent.datargo.com
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=$SVC_USER
ExecStart=$BIN run
Restart=on-failure
RestartSec=5
# Hardening: the agent is outbound-only and read-only.
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictSUIDSGID=yes
RestrictNamespaces=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
StateDirectory=datargo-agent
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK
SystemCallFilter=@system-service

[Install]
WantedBy=multi-user.target
UNITEOF
  $SUDO_CMD systemctl daemon-reload
  $SUDO_CMD systemctl enable --now datargo-agent
  ok "Service running: $(systemctl is-active datargo-agent 2>/dev/null || echo unknown)  (logs: journalctl -u datargo-agent -f)"

elif [ "$os" = "Darwin" ]; then
  info "Installing LaunchDaemon (com.datargo.agent) …"
  $SUDO_CMD mkdir -p /var/log
  $SUDO_CMD sh -c "cat > '$PLIST'" <<PLISTEOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>com.datargo.agent</string>
  <key>ProgramArguments</key>
  <array>
    <string>$BIN</string>
    <string>run</string>
  </array>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
  <key>ProcessType</key><string>Background</string>
  <key>StandardOutPath</key><string>/var/log/datargo-agent.log</string>
  <key>StandardErrorPath</key><string>/var/log/datargo-agent.log</string>
</dict>
</plist>
PLISTEOF
  $SUDO_CMD chmod 644 "$PLIST"
  # Reload cleanly if already present (idempotent).
  $SUDO_CMD launchctl bootout system/com.datargo.agent 2>/dev/null || true
  $SUDO_CMD launchctl bootstrap system "$PLIST" 2>/dev/null \
    || $SUDO_CMD launchctl load -w "$PLIST" 2>/dev/null \
    || die "launchctl could not load the service"
  $SUDO_CMD launchctl enable system/com.datargo.agent 2>/dev/null || true
  $SUDO_CMD launchctl kickstart -k system/com.datargo.agent 2>/dev/null || true
  ok "Service running (logs: tail -f /var/log/datargo-agent.log)"
fi

printf '\n'
ok "Done — the Datargo Agent is running and reporting to the cockpit."
