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

KEYDIR_BASE="/var/lib/cmkpush/.ssh/authorized_keys.d"
QUEUE_BASE="/var/lib/cmkpush/register-queue"
META_BASE="/var/lib/cmkpush/register-meta"

FQDN=""
PUBKEY=""
SITE=""
FOLDER=""
LABELS=()

usage() {
  cat >&2 <<'EOF'
cmk-push-agent-reg (forced command)
Reads registration payload from STDIN:

  FQDN=<fqdn>
  FOLDER=/Path
  SITE=<site>
  LABEL=k=v         (optional, repeatable)
  PUBKEY=ssh-ed25519 AAAA... comment

EOF
  exit 2
}

# ---- parse stdin payload ----
# Accept both LF and CRLF
while IFS= read -r line || [[ -n "$line" ]]; do
  line="${line%$'\r'}"
  [[ -n "$line" ]] || continue

  case "$line" in
    FQDN=*)   FQDN="${line#FQDN=}" ;;
    FOLDER=*) FOLDER="${line#FOLDER=}" ;;
    SITE=*)   SITE="${line#SITE=}" ;;
    LABEL=*)  LABELS+=("${line#LABEL=}") ;;
    PUBKEY=*) PUBKEY="${line#PUBKEY=}" ;;
    *)        echo "ERROR: invalid input line: $line" >&2; exit 3 ;;
  esac
done

[[ -n "$FQDN" && -n "$PUBKEY" && -n "$FOLDER" ]] || usage

# ---- validations ----
if ! [[ "$FQDN" =~ ^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$ ]]; then
  echo "ERROR: fqdn does not look valid: $FQDN" >&2
  exit 10
fi

if ! [[ "$PUBKEY" =~ ^ssh-(ed25519|rsa|ecdsa)[[:space:]]+[A-Za-z0-9+/=]+([[:space:]].*)?$ ]]; then
  echo "ERROR: pubkey does not look like a valid SSH public key" >&2
  exit 11
fi

if ! [[ "$FOLDER" =~ ^/([A-Za-z0-9][A-Za-z0-9._-]{0,63})(/[A-Za-z0-9][A-Za-z0-9._-]{0,63})*$ ]]; then
  echo "ERROR: folder path invalid: $FOLDER" >&2
  exit 12
fi

for kv in "${LABELS[@]}"; do
  if ! [[ "$kv" =~ ^[a-z0-9_]{1,32}=[A-Za-z0-9._-]{1,64}$ ]]; then
    echo "ERROR: invalid label (expected k=v): $kv" >&2
    exit 13
  fi
done

if [[ -z "$SITE" ]]; then
  SITE="$(omd sites -b 2>/dev/null | head -n1 || true)"
fi
[[ -n "$SITE" ]] || { echo "ERROR: could not determine default OMD site" >&2; exit 14; }

if ! [[ "$SITE" =~ ^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$ ]]; then
  echo "ERROR: invalid site value: $SITE" >&2
  exit 15
fi

if ! omd sites -b 2>/dev/null | grep -qx "$SITE"; then
  echo "ERROR: site does not exist: $SITE" >&2
  exit 16
fi

QUEUE_DIR="${QUEUE_BASE}/${SITE}"
META_DIR="${META_BASE}/${SITE}"

tmp_key=""; tmp_meta=""; tmp_q=""
cleanup() { rm -f "$tmp_key" "$tmp_meta" "$tmp_q"; }
trap cleanup EXIT

# =========================
# 1) Install push key entry
# =========================
KEYDIR="$KEYDIR_BASE"
KEYFILE="${KEYDIR}/${FQDN}"
OPTS='restrict,command="/usr/bin/cmk-push-receive"'

install -d -m 0750 -o cmkpush -g cmkpush "$KEYDIR"

tmp_key="$(mktemp -p "$KEYDIR" ".${FQDN}.XXXXXX.key.tmp")"
umask 077
printf '%s %s\n' "$OPTS" "$PUBKEY" > "$tmp_key"
install -m 0640 -o cmkpush -g cmkpush "$tmp_key" "$KEYFILE"
rm -f "$tmp_key"; tmp_key=""

# =========================
# 2) Build metadata JSON (server-internal)
# =========================
install -d -m 0750 -o cmkpush -g cmkpush "$QUEUE_DIR" "$META_DIR"

labels_json="{}"
if (( ${#LABELS[@]} > 0 )); then
  labels_json="{"
  first=true
  for kv in "${LABELS[@]}"; do
    k="${kv%%=*}"
    v="${kv#*=}"
    if $first; then first=false; else labels_json+=", "; fi
    labels_json+="\"$k\":\"$v\""
  done
  labels_json+="}"
fi

meta_json="{\"fqdn\":\"$FQDN\",\"site\":\"$SITE\",\"folder\":\"$FOLDER\",\"labels\":$labels_json}"

tmp_meta="$(mktemp -p "$META_DIR" ".${FQDN}.XXXXXX.meta.tmp")"
umask 077
printf '%s\n' "$meta_json" > "$tmp_meta"
install -m 0640 -o cmkpush -g cmkpush "$tmp_meta" "$META_DIR/${FQDN}.json"
rm -f "$tmp_meta"; tmp_meta=""

# =========================
# 3) Enqueue request
# =========================
TS="$(date -u +%Y%m%dT%H%M%SZ)"
RAND="$(od -An -N2 -tu2 /dev/urandom | tr -d ' ')"
tmp_q="$(mktemp -p "$QUEUE_DIR" ".${TS}.${RAND}.${FQDN}.XXXXXX.q.tmp")"
out_q="${QUEUE_DIR}/${TS}_${RAND}_${FQDN}.json"

umask 077
printf '%s\n' "$meta_json" > "$tmp_q"
install -m 0640 -o cmkpush -g cmkpush "$tmp_q" "$out_q"
rm -f "$tmp_q"; tmp_q=""

echo "OK: key installed + queued registration for $FQDN (site=$SITE folder=$FOLDER)"
