#!/usr/bin/env bash
# pre-backup-dump.sh — take consistent database dumps before restic runs.
# Tested on Debian 12 / bash 5.2, restic 0.18.0, sqlite 3.40.1.
# Usage: pre-backup-dump.sh <appdata-root> <dump-root>
set -euo pipefail

APPDATA="${1:?usage: pre-backup-dump.sh <appdata-root> <dump-root>}"
DUMPROOT="${2:?usage: pre-backup-dump.sh <appdata-root> <dump-root>}"
mkdir -p "$DUMPROOT"

fail=0

# --- SQLite apps: Vaultwarden, Mealie, Paperless (older installs), Home Assistant (if not using the recorder DB) ---
# .backup uses SQLite's online backup API: safe while the app is writing.
for db in \
  "$APPDATA/vaultwarden/data/db.sqlite3" \
  "$APPDATA/mealie/data/mealie.sqlite" ; do
  [ -f "$db" ] || continue
  app="$(basename "$(dirname "$(dirname "$db")")")"
  out="$DUMPROOT/$app/$(basename "$db")"
  mkdir -p "$(dirname "$out")"
  echo "==> sqlite dump: $db -> $out"
  # .timeout sets SQLite's busy handler; without it .backup fails instantly
  # with "database is locked" as soon as the app holds a write transaction.
  ok=0
  for attempt in 1 2 3; do
    if sqlite3 -cmd ".timeout 8000" "$db" ".backup '$out'"; then ok=1; break; fi
    echo "    attempt $attempt failed, retrying in 2s"
    sleep 2
  done
  [ "$ok" = 1 ] || { echo "    FAIL: could not dump $db"; fail=1; continue; }
  result="$(sqlite3 "$out" 'PRAGMA integrity_check;')"
  echo "    integrity_check: $result"
  [ "$result" = "ok" ] || { echo "    FAIL: dump is not a valid database"; fail=1; }
done

# --- PostgreSQL apps: Immich, Paperless-ngx (default compose), Nextcloud (if pgsql) ---
# pg_dump -Fc is a single-file custom-format dump; restore with pg_restore --clean --if-exists.
if [ -n "${PG_DSN:-}" ]; then
  out="$DUMPROOT/immich/immich.dump"
  mkdir -p "$(dirname "$out")"
  echo "==> pg_dump: $PG_DSN -> $out"
  pg_dump -Fc --no-owner --no-privileges -d "$PG_DSN" -f "$out"
  # 300 bytes is roughly "empty database"; anything smaller means the dump failed quietly.
  size="$(stat -c%s "$out")"
  echo "    dump size: $size bytes"
  [ "$size" -gt 4096 ] || { echo "    FAIL: dump looks empty"; fail=1; }
fi

exit "$fail"
