#!/usr/bin/env bash
set -euo pipefail

# cmk-agent-register (agent-side wrapper)
# - writes local config for cmk-push-agent
# - ensures the agent SSH key exists (/root/.ssh/id_ed25519)
# - sends registration payload via STDIN to a server-side SSH forced-command
# - uses a registration-only SSH key (bootstrap key)
#
# Server expectation:
# - The bootstrap key in /var/lib/cmkpush/.ssh/authorized_keys (or similar) has:
#     restrict,command="/usr/bin/cmk-push-agent-reg" <pubkey>
# - cmk-push-agent-reg reads payload from STDIN:
#     FQDN=...
#     FOLDER=...
#     LABEL=k=v      (optional, repeatable)
#     PUBKEY=ssh-ed25519 AAAA... comment

usage() {
  cat >&2 <<'EOF'
Usage:
  cmk-agent-register \
    --server <host|ip> \
    --site <site id> \
    --folder </Path/In/Checkmk> \
    --reg-key </path/to/registration_key> \
    [--reg-user <ssh_user>] \
    [--port <ssh_port>] \
    [--label k=v ...] \
    [--strict-hostkey yes|accept-new|no] \
    <host-fqdn>

Defaults:
  --reg-user cmkpush
  --port 22

Notes:
  - Labels are transmitted via STDIN as repeated lines: LABEL=k=v
  - The agent public key is taken from /root/.ssh/id_ed25519.pub
EOF
}

die() { echo "ERROR: $*" >&2; exit 1; }

CMK_SERVER=""
CMK_PORT="22"
CMK_FOLDER=""
CMK_SITE="raw"
REG_USER="cmkpush"
REG_KEY=""
STRICT_HOSTKEY="accept-new"
LABELS=()

AGENT_KEY="/root/.ssh/id_ed25519"
KNOWN_HOSTS="/root/.ssh/known_hosts"

POSITIONAL=()
while [[ $# -gt 0 ]]; do
  case "$1" in
    --server)         CMK_SERVER="${2:-}"; shift 2 ;;
    --site)           CMK_SITE="${2:-}"; shift 2 ;;
    --port)           CMK_PORT="${2:-}"; shift 2 ;;
    --folder)         CMK_FOLDER="${2:-}"; shift 2 ;;
    --reg-user)       REG_USER="${2:-}"; shift 2 ;;
    --reg-key)        REG_KEY="${2:-}"; shift 2 ;;
    --label)          LABELS+=("${2:-}"); shift 2 ;;
    --strict-hostkey) STRICT_HOSTKEY="${2:-}"; shift 2 ;;
    -h|--help) usage; exit 0 ;;
    --) shift; break ;;
    -*) die "Unknown option: $1" ;;
    *) POSITIONAL+=("$1"); shift ;;
  esac
done

HOST_FQDN="${POSITIONAL[0]:-}"

[[ -n "$CMK_SERVER" ]] || die "Missing --server"
[[ -n "$CMK_SITE"   ]] || die "Missing --site"
[[ -n "$CMK_FOLDER" ]] || die "Missing --folder"
[[ -n "$REG_KEY"    ]] || die "Missing --reg-key"
[[ -n "$HOST_FQDN"  ]] || die "Missing <host-fqdn>"

# --- validate port ---
if ! [[ "$CMK_PORT" =~ ^[0-9]{1,5}$ ]] || (( CMK_PORT < 1 || CMK_PORT > 65535 )); then
  die "Invalid --port: $CMK_PORT"
fi

# --- validate folder ---
if ! [[ "$CMK_FOLDER" =~ ^/([A-Za-z0-9][A-Za-z0-9._-]{0,63})(/[A-Za-z0-9][A-Za-z0-9._-]{0,63})*$ ]]; then
  die "Invalid --folder: $CMK_FOLDER"
fi

# --- validate labels ---
for kv in "${LABELS[@]}"; do
  if ! [[ "$kv" =~ ^[a-z0-9_]{1,32}=[A-Za-z0-9._-]{1,64}$ ]]; then
    die "Invalid --label (expected k=v): $kv"
  fi
done

# --- strict hostkey mode ---
case "$STRICT_HOSTKEY" in
  yes|accept-new|no) ;;
  *) die "Invalid --strict-hostkey (use yes|accept-new|no)" ;;
esac

# --- ensure ssh tooling ---
command -v ssh >/dev/null 2>&1 || die "ssh not found"
command -v ssh-keygen >/dev/null 2>&1 || die "ssh-keygen not found"
command -v ssh-keyscan >/dev/null 2>&1 || die "ssh-keyscan not found"

# --- ensure agent SSH key exists ---
install -d -m 0700 /root/.ssh

if [[ ! -f "$AGENT_KEY" || ! -f "${AGENT_KEY}.pub" ]]; then
  ssh-keygen -t ed25519 -f "$AGENT_KEY" -N "" -q
  chmod 0600 "$AGENT_KEY"
  chmod 0644 "${AGENT_KEY}.pub"
fi

PUBKEY="$(cat "${AGENT_KEY}.pub")"

# --- known_hosts handling ---
touch "$KNOWN_HOSTS"
chmod 0644 "$KNOWN_HOSTS"

if ! ssh-keygen -F "[$CMK_SERVER]:$CMK_PORT" -f "$KNOWN_HOSTS" >/dev/null 2>&1; then
  ssh-keyscan -p "$CMK_PORT" -H "$CMK_SERVER" >> "$KNOWN_HOSTS" 2>/dev/null || true
fi

# --- SSH options ---
SSH_OPTS=(
  -T
  -o BatchMode=yes
  -o ConnectTimeout=10
  -o PasswordAuthentication=no
  -o PreferredAuthentications=publickey
  -o StrictHostKeyChecking="$STRICT_HOSTKEY"
  -o UserKnownHostsFile="$KNOWN_HOSTS"
  -p "$CMK_PORT"
  -i "$REG_KEY"
)

# --- Build STDIN payload for forced-command receiver ---
# IMPORTANT: do NOT pass a remote command. Forced-command will run on server.
payload() {
  printf 'FQDN=%s\n' "$HOST_FQDN"
  printf 'FOLDER=%s\n' "$CMK_FOLDER"
  printf 'SITE=%s\n' "$CMK_SITE"
  for kv in "${LABELS[@]}"; do
    printf 'LABEL=%s\n' "$kv"
  done
  printf 'PUBKEY=%s\n' "$PUBKEY"
}

payload | ssh "${SSH_OPTS[@]}" "${REG_USER}@${CMK_SERVER}"

# --- write local agent config ---
install -d -m 0755 /etc/cmk-push-agent

cat > /etc/cmk-push-agent/cmk-push-agent.conf <<EOF
CMK_SERVER="${CMK_SERVER}"
CMK_PORT="${CMK_PORT}"
CMK_SITE="${CMK_SITE}"
HOSTNAME="${HOST_FQDN}"
EOF

# Optional: store payload summary locally (debug)
{
  echo "FQDN=$HOST_FQDN"
  echo "FOLDER=$CMK_FOLDER"
  echo "CMK_SITE=${CMK_SITE}"
  for kv in "${LABELS[@]}"; do
    echo "LABEL=$kv"
  done
} > /etc/cmk-push-agent/registration.meta
chmod 0644 /etc/cmk-push-agent/registration.meta

# --- enable agent services (best effort) ---
if command -v cmk-agent-update >/dev/null 2>&1; then
  cmk-agent-update || true
fi

if command -v systemctl >/dev/null 2>&1; then
  systemctl enable --now cmk-push-agent.service >/dev/null 2>&1 || true
  systemctl enable --now cmk-push-agent.timer   >/dev/null 2>&1 || true
fi

echo "OK: registration payload sent (stdin), local config written, agent key ensured."
