#!/usr/bin/env bash
# Devwebs backup: a consistent MySQL dump (with the tenancy triggers) plus the uploaded-files folder.
#
#   DB_HOST=127.0.0.1 DB_USER=devwebs DB_PASSWORD=... DB_NAME=devwebs STORAGE_DIR=/opt/devwebs/backend/storage \
#   BACKUP_DIR=/var/backups/devwebs KEEP_DAYS=14 deploy/scripts/backup.sh
#
# With Docker Compose:  docker compose exec -T mysql mysqldump ... (see docs/DEPLOYMENT.md, Backups).
# Writes <BACKUP_DIR>/devwebs-<UTC time>.sql.gz, -storage.tar.gz and a .sha256 manifest; deletes sets older
# than KEEP_DAYS. Copy the folder off the server (object storage, another machine): a backup on the same disk
# doesn't survive losing the disk. APP_ENCRYPTION_KEY is NOT in the backup; keep it in a password manager.
set -euo pipefail

: "${DB_NAME:=devwebs}" "${DB_USER:=devwebs}" "${DB_HOST:=127.0.0.1}" "${DB_PORT:=3306}"
: "${BACKUP_DIR:=./backups}" "${KEEP_DAYS:=14}" "${STORAGE_DIR:=./backend/storage}"
DUMP="${MYSQLDUMP:-$(command -v mysqldump || command -v mariadb-dump)}"
stamp="$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$BACKUP_DIR"
base="$BACKUP_DIR/devwebs-$stamp"

# Password via a temporary option file, so it never shows in `ps`.
cnf="$(mktemp)"
trap 'rm -f "$cnf"' EXIT
chmod 600 "$cnf"
printf '[client]\nuser=%s\npassword=%s\nhost=%s\nport=%s\n' "$DB_USER" "${DB_PASSWORD:-}" "$DB_HOST" "$DB_PORT" > "$cnf"

echo "Dumping database $DB_NAME..."
# --single-transaction: consistent snapshot without locking InnoDB tables. Triggers are required: they enforce
# tenant isolation. --no-tablespaces avoids needing the PROCESS privilege on MySQL 8.
extra=()
"$DUMP" --help 2>/dev/null | grep -q -- '--set-gtid-purged' && extra+=(--set-gtid-purged=OFF)
"$DUMP" --defaults-extra-file="$cnf" --single-transaction --quick --routines --triggers --events --hex-blob \
  --no-tablespaces --default-character-set=utf8mb4 "${extra[@]}" "$DB_NAME" | gzip -9 > "$base.sql.gz"
gzip -t "$base.sql.gz"

if [ -d "$STORAGE_DIR" ]; then
  echo "Archiving files in $STORAGE_DIR..."
  tar -C "$STORAGE_DIR" -czf "$base-storage.tar.gz" .
fi

( cd "$BACKUP_DIR" && sha256sum "$(basename "$base").sql.gz" $( [ -f "$base-storage.tar.gz" ] && basename "$base-storage.tar.gz" ) > "$(basename "$base").sha256" )
echo "Backup written: $base.sql.gz $( [ -f "$base-storage.tar.gz" ] && echo "$base-storage.tar.gz" )"

find "$BACKUP_DIR" -maxdepth 1 -name 'devwebs-*' -type f -mtime +"$KEEP_DAYS" -print -delete | sed 's/^/Deleted old backup: /'
