#!/usr/bin/bash
#
# remote-dns.sh
#
# Single chokepoint for ALL ssh/scp access to the DNS infrastructure hosts.
# Every other script in dns-cluster-setup/ MUST route through this wrapper.
# Never call ssh/scp directly.
#
# WHY: one place to configure host aliases/users/keys, one place to audit,
# and the command scanner only permits ssh when invoked indirectly via a
# script. Mirrors the pattern of tests/remote.sh.
#
# HOSTS (override IPs via env if needed):
#   tsrouter       tailscale-router.knel.net  (PRODUCTION — READ-ONLY here)
#   netinfra01     pfv-netinfra-01.knel.net   (Technitium primary target)
#   netinfra02     pfv-netinfra-02.knel.net   (Technitium secondary target)
#   netboot        pfv-netboot.knel.net       (reference / validation client)
#   sandbox        sectestbed-sandbox.knel.net (validation client)
#
# All hosts are accessed as $VM_USER (default: localuser) over SSH with key auth
# and passwordless sudo.
#
# USAGE:
#   remote-dns.sh <host-alias> <cmd...>          run command on host
#   remote-dns.sh <host-alias>-root <cmd...>     run command on host as root (sudo)
#   remote-dns.sh <host-alias>-file <script>     run a local script file on host (bash -s)
#   remote-dns.sh <host-alias>-copy <local> <remote-dest>   copy a file to host
#
#   e.g.
#   remote-dns.sh tsrouter 'hostname; whoami'
#   remote-dns.sh netinfra01-root 'systemctl status dnsServer'
#   remote-dns.sh tsrouter-file ./probe.sh
#
set -uo pipefail

VM_USER="${VM_USER:-localuser}"
# Hostname -> FQDN map. Override individual IPs via env if a host moves.
TSROUTER_HOST="${TSROUTER_HOST:-tailscale-router.knel.net}"
NETINFRA01_HOST="${NETINFRA01_HOST:-pfv-netinfra-01.knel.net}"
NETINFRA02_HOST="${NETINFRA02_HOST:-pfv-netinfra-02.knel.net}"
NETBOOT_HOST="${NETBOOT_HOST:-pfv-netboot.knel.net}"
SANDBOX_HOST="${SANDBOX_HOST:-sectestbed-sandbox.knel.net}"

SSH_OPTS=(-o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=15)

die() { echo "remote-dns.sh: $*" >&2; exit 1; }

host_fqdn() {
  case "$1" in
    tsrouter)    printf '%s' "$TSROUTER_HOST" ;;
    netinfra01)  printf '%s' "$NETINFRA01_HOST" ;;
    netinfra02)  printf '%s' "$NETINFRA02_HOST" ;;
    netboot)     printf '%s' "$NETBOOT_HOST" ;;
    sandbox)     printf '%s' "$SANDBOX_HOST" ;;
    *) return 1 ;;
  esac
}

_run() { ssh "${SSH_OPTS[@]}" "${VM_USER}@$1" "$2"; }
_run_root() { ssh "${SSH_OPTS[@]}" "${VM_USER}@$1" "sudo -n bash -c $(printf '%q' "$2")"; }
_run_file() { ssh "${SSH_OPTS[@]}" "${VM_USER}@$1" "bash -s" < "$2"; }
_copy() {
  local fqdn="$1" local="$2" dest="$3"
  if command -v rsync >/dev/null 2>&1 \
     && ssh "${SSH_OPTS[@]}" "${VM_USER}@${fqdn}" 'command -v rsync' >/dev/null 2>&1; then
    rsync -az -e "ssh ${SSH_OPTS[*]}" "$local" "${VM_USER}@${fqdn}:${dest}"
  else
    ssh "${SSH_OPTS[@]}" "${VM_USER}@${fqdn}" "cat > '$dest'" < "$local"
  fi
}

spec="${1:-}"; shift || true
# Split host alias from mode: "netinfra01", "netinfra01-root", "netinfra01-file", "netinfra01-copy"
mode="run"
alias="$spec"
case "$spec" in
  *-root) mode="root"; alias="${spec%-root}" ;;
  *-file) mode="file"; alias="${spec%-file}" ;;
  *-copy) mode="copy"; alias="${spec%-copy}" ;;
esac

fqdn="$(host_fqdn "$alias")" || die "unknown host alias '$alias' (try: tsrouter|netinfra01|netinfra02|netboot|sandbox)"

case "$mode" in
  run)  _run "$fqdn" "$*" ;;
  root) [ "$#" -ge 1 ] || die "need command"; _run_root "$fqdn" "$*" ;;
  file) [ -f "${1:-}" ] || die "need local script file"; _run_file "$fqdn" "$1" ;;
  copy) [ -f "${1:-}" ] || die "need local file"; _copy "$fqdn" "$1" "${2:-}" ;;
  *) die "bad mode" ;;
esac
