#!/usr/bin/env bash
# Backs up the ASP.NET Data Protection keyring. Without this keyring, PHI
# encrypted by Phase 32 cannot be decrypted — a database backup alone is not
# sufficient to restore the system. See docs/ops/phi-encryption-runbook.md.
#
# Volume name matches docker-compose.prod.yml `name: vigilcare` → vigilcare_dp_keys.
# Do not derive the name from the host directory; /opt/vigilcare would otherwise
# produce a different volume than a checkout named VigilCareClinical.
#
# Usage (on the production host):
#   ./scripts/backup-dp-keys.sh
#   BACKUP_DIR=/mnt/offsite/vigilcare/dp-keys ./scripts/backup-dp-keys.sh
#
# Cron example (daily 02:15 UTC):
#   15 2 * * * /opt/vigilcare/scripts/backup-dp-keys.sh >> /var/log/vigilcare-dp-backup.log 2>&1
set -euo pipefail

VOLUME_NAME="${VOLUME_NAME:-vigilcare_dp_keys}"
BACKUP_DIR="${BACKUP_DIR:-/var/backups/vigilcare/dp-keys}"
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
ARCHIVE="${BACKUP_DIR}/dp-keys-${STAMP}.tar.gz"

if ! docker volume inspect "${VOLUME_NAME}" >/dev/null 2>&1; then
  echo "ERROR: Docker volume '${VOLUME_NAME}' not found." >&2
  echo "Confirm docker-compose.prod.yml uses 'name: vigilcare' and the API has started once." >&2
  exit 1
fi

mkdir -p "${BACKUP_DIR}"
chmod 700 "${BACKUP_DIR}"

echo "Backing up volume ${VOLUME_NAME} → ${ARCHIVE}"
docker run --rm \
  -v "${VOLUME_NAME}:/keys:ro" \
  -v "${BACKUP_DIR}:/backup" \
  alpine tar czf "/backup/dp-keys-${STAMP}.tar.gz" -C /keys .

chmod 600 "${ARCHIVE}"

# Refuse empty archives (volume had no key XML yet).
if ! tar tzf "${ARCHIVE}" | grep -q '\.xml$'; then
  echo "ERROR: archive contains no *.xml key files — refusing to keep empty backup." >&2
  rm -f "${ARCHIVE}"
  exit 1
fi

echo "Keyring backed up to ${ARCHIVE}"

# Retain 30 days.
find "${BACKUP_DIR}" -name 'dp-keys-*.tar.gz' -mtime +30 -delete
echo "Retention: removed archives older than 30 days under ${BACKUP_DIR}"
