#!/bin/bash
# Makenotwork Database Backup Script
# Runs daily via cron, keeps 30 days of backups.
#
# Usage: backup-db.sh [db_name]
#   db_name defaults to "makenotwork". Pass "multithreaded" (or any other
#   DB) to back up that one instead. The script runs as the corresponding
#   OS user (peer auth), so call from that user's crontab.
#
# Setup (per DB user):
#   1. Deploy script to /opt/mnw/backup-db.sh (chmod 755)
#   2. Ensure /var/lib/mnw/backups exists and is writable by the DB user
#   3. Add cron job as that user:
#      sudo crontab -u <db_user> -e
#      # Daily at 03:00 UTC:
#      0 3 * * * /opt/mnw/backup-db.sh <db_name> >> /var/lib/mnw/backups/<db_name>/backup.log 2>&1

set -euo pipefail

DB_NAME="${1:-makenotwork}"
DB_USER="$DB_NAME"  # peer auth: OS user matches DB user
BACKUP_DIR="/var/lib/mnw/backups/${DB_NAME}"
RETENTION_DAYS=30

TIMESTAMP=$(date +%Y%m%d-%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}-${TIMESTAMP}.sql.gz"

echo "[$(date -Iseconds)] Starting backup of ${DB_NAME}..."

mkdir -p "$BACKUP_DIR"
# Move into the backup dir so later `find ... -delete` doesn't fail when invoked
# from a CWD the DB user can't traverse (e.g. /root under `sudo -u`).
cd "$BACKUP_DIR"

pg_dump -U "$DB_USER" "$DB_NAME" | gzip > "$BACKUP_FILE"

FILESIZE=$(stat -c%s "$BACKUP_FILE" 2>/dev/null || stat -f%z "$BACKUP_FILE" 2>/dev/null)
if [ "$FILESIZE" -lt 100 ]; then
    echo "[$(date -Iseconds)] ERROR: Backup file suspiciously small (${FILESIZE} bytes)"
    exit 1
fi

echo "[$(date -Iseconds)] Backup complete: $BACKUP_FILE ($(du -h "$BACKUP_FILE" | cut -f1))"

# Stable per-DB latest filename for downstream pullers (sando's backup-puller
# user rsyncs `latest-<db>.sql.gz`). Hard link rather than symlink because rrsync
# blocks `-L`; atomic via temp-then-rename so the link is never briefly missing.
LATEST="${BACKUP_DIR}/latest.sql.gz"
ln -f "$BACKUP_FILE" "${LATEST}.new"
mv -Tf "${LATEST}.new" "$LATEST"

DELETED=$(find "$BACKUP_DIR" -name "${DB_NAME}-*.sql.gz" -mtime +${RETENTION_DAYS} -delete -print | wc -l)
if [ "$DELETED" -gt 0 ]; then
    echo "[$(date -Iseconds)] Pruned $DELETED ${DB_NAME} backup(s) older than ${RETENTION_DAYS} days"
fi

TOTAL=$(find "$BACKUP_DIR" -name "${DB_NAME}-*.sql.gz" | wc -l)
echo "[$(date -Iseconds)] Total ${DB_NAME} backups on disk: $TOTAL"

# Sync to offsite host (best-effort — failure here does not fail the backup).
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OFFSITE_SCRIPT="${SCRIPT_DIR}/sync-backup-offsite.sh"
if [ -x "$OFFSITE_SCRIPT" ]; then
    "$OFFSITE_SCRIPT" "$DB_NAME" "$BACKUP_FILE" || true
fi
