#!/usr/bin/env bash
# tools/cmd/railiance-backup-s1 — S1 OS & Provisioning backup
# Backs up: key OS config files applied by Ansible (sshd, ufw, fail2ban, hosts)
# Encryption: age (reuses SOPS key pair from .sops.yaml)
# Output: /opt/backup/railiance/infra/
# No network required. Requires root to read /etc/.
set -euo pipefail

# ── Configuration ──────────────────────────────────────────────────────────────
AGE_PUBLIC_KEY="age1aq8twfd78wvpra0had8cezcnj96tj4q0068edrz5jez8d6xwmflqdepsh4"
BACKUP_DIR="/opt/backup/railiance/infra"
KEEP=7
TS="$(date -u +%Y%m%dT%H%M%SZ)"

# Colour helpers (no external dependency)
ok()   { printf "  ✅ %-12s  %s\n" "$1" "$2"; }
warn() { printf "  ⚠️  %-12s  %s\n" "$1" "$2"; }
bad()  { printf "  ❌ %-12s  %s\n" "$1" "$2"; }

mkdir -p "${BACKUP_DIR}"
printf "\nrailiance-infra (S1) backup — %s\n" "${TS}"
printf "%0.s-" $(seq 1 44); echo

# ── Root check ─────────────────────────────────────────────────────────────────
if [[ $EUID -ne 0 ]]; then
  bad "root" "this script requires root — run via: sudo make backup"
  exit 1
fi

# ── OS config snapshot ─────────────────────────────────────────────────────────
# Captures the live state of files that Ansible manages.
# These may drift from the playbooks if manual changes were made.
ok "os-config" "snapshotting /etc config…"

OS_FILES=(
  /etc/ssh/sshd_config
  /etc/ssh/sshd_config.d/
  /etc/ufw/ufw.conf
  /etc/ufw/user.rules
  /etc/ufw/user6.rules
  /etc/fail2ban/jail.local
  /etc/fail2ban/jail.d/
  /etc/hosts
  /etc/hostname
  /etc/apt/sources.list.d/
)

TMP_OS="$(mktemp -d)"
for item in "${OS_FILES[@]}"; do
  [[ -e "${item}" ]] || continue
  dest="${TMP_OS}$(dirname "${item}")"
  mkdir -p "${dest}"
  cp -a "${item}" "${dest}/" 2>/dev/null || true
done

tar -czf - -C "${TMP_OS}" . \
  | age -r "${AGE_PUBLIC_KEY}" -o "${BACKUP_DIR}/os-config-${TS}.tar.gz.age"
rm -rf "${TMP_OS}"
ok "os-config" "encrypted → os-config-${TS}.tar.gz.age"

# ── Installed packages list ────────────────────────────────────────────────────
if command -v dpkg &>/dev/null; then
  dpkg --get-selections \
    | age -r "${AGE_PUBLIC_KEY}" -o "${BACKUP_DIR}/packages-${TS}.txt.age"
  ok "packages" "encrypted → packages-${TS}.txt.age"
fi

# ── Prune local cache ──────────────────────────────────────────────────────────
for pattern in "os-config-*.tar.gz.age" "packages-*.txt.age"; do
  find "${BACKUP_DIR}" -name "${pattern}" | sort -r | tail -n +$((KEEP + 1)) | xargs -r rm -f
done
ok "prune" "kept last ${KEEP} of each type"

# ── Stamp ──────────────────────────────────────────────────────────────────────
echo "${TS}" > "${BACKUP_DIR}/.last-backup"

echo
ok "done" "backup complete — ${TS}"
echo "         Location: ${BACKUP_DIR}"
echo "         Decrypt with: age -d -i ~/.config/sops/age/keys.txt <file>"
