#!/usr/bin/env bash
#
# tools/db-backup.sh — backup lógico do banco do V7 (ADR-042), reutilizável no dev e no deploy.
#
# Uso: tools/db-backup.sh [--dry-run] [--keep N] [--dir DIR]
#
# Falhas de dump/validação ABORTAM (exit 1). Ausência de postgres/banco (primeiro deploy) é
# **pulada** com exit 0 — não há o que copiar. Nunca imprime segredos.
set -Eeuo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

DRY_RUN=0
KEEP=""
DIR=""

while [ $# -gt 0 ]; do
    case "$1" in
        --dry-run) DRY_RUN=1 ;;
        --keep) shift; KEEP="${1:-}" ;;
        --dir) shift; DIR="${1:-}" ;;
        -h | --help)
            sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//'
            exit 0
            ;;
        *) echo "db-backup: flag desconhecida: $1" >&2; exit 2 ;;
    esac
    shift
done

env_value() {
    [ -f .env ] || return 0
    grep -E "^$1=" .env | head -1 | cut -d= -f2- | sed -E 's/^"(.*)"$/\1/; s/^'"'"'(.*)'"'"'$/\1/' || true
}

PROJECT="$(bash "$ROOT/tools/project-name.sh")"
# shellcheck source=tools/runtime.sh
. "$ROOT/tools/runtime.sh"
COMPOSE=("${ENGINE[@]}" compose -p "$PROJECT" --env-file .env "${COMPOSE_FILES[@]}")

DB_NAME="$(env_value DB_DATABASE)"; DB_NAME="${DB_NAME:-concordia}"
DB_USER="$(env_value DB_USERNAME)"; DB_USER="${DB_USER:-concordia}"
DB_PASS="$(env_value DB_PASSWORD)"

STORAGE_PATH="$(env_value STORAGE_PATH)"; STORAGE_PATH="${STORAGE_PATH:-./storage}"
BACKUP_DIR="${DIR:-${STORAGE_PATH%/}/backups}"

KEEP="${KEEP:-$(env_value BACKUP_KEEP)}"; KEEP="${KEEP:-7}"
case "$KEEP" in ''|*[!0-9]*) KEEP=7 ;; esac
[ "$KEEP" -ge 1 ] || KEEP=1

command -v "${ENGINE[0]}" >/dev/null 2>&1 || { echo "db-backup: ${ENGINE[0]} indisponível." >&2; exit 1; }

if [ -z "$("${COMPOSE[@]}" ps -q postgres 2>/dev/null)" ]; then
    echo "db-backup: postgres não está em execução — backup pulado."
    exit 0
fi

exists="$("${COMPOSE[@]}" exec -T postgres env PGPASSWORD="$DB_PASS" \
    psql -U "$DB_USER" -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'" 2>/dev/null \
    | tr -d '[:space:]' || true)"
if [ "$exists" != "1" ]; then
    echo "db-backup: banco '${DB_NAME}' ainda não existe — backup pulado."
    exit 0
fi

ts="$(date -u +%Y%m%dT%H%M%SZ)"
file="${BACKUP_DIR}/db-${ts}.dump"
tmp="${file}.partial"

if [ "$DRY_RUN" = 1 ]; then
    echo "db-backup: (dry-run) pg_dump -Fc → ${file}"
    exit 0
fi

mkdir -p "$BACKUP_DIR"

if ! "${COMPOSE[@]}" exec -T postgres env PGPASSWORD="$DB_PASS" \
    pg_dump -Fc --no-owner --no-acl -U "$DB_USER" -d "$DB_NAME" > "$tmp"; then
    rm -f "$tmp"
    echo "db-backup: pg_dump falhou." >&2
    exit 1
fi

if [ ! -s "$tmp" ]; then
    rm -f "$tmp"
    echo "db-backup: dump vazio." >&2
    exit 1
fi

if ! "${COMPOSE[@]}" exec -T postgres pg_restore --list < "$tmp" > /dev/null; then
    rm -f "$tmp"
    echo "db-backup: dump ilegível (pg_restore --list falhou)." >&2
    exit 1
fi

mv -f "$tmp" "$file"
bytes="$(wc -c < "$file" | tr -d ' ')"
echo "db-backup: ${file} (${bytes} bytes)"

# Retenção determinística por nome (timestamp UTC).
ls -1 "$BACKUP_DIR"/db-*.dump 2>/dev/null | sort -r | tail -n +"$((KEEP + 1))" | while read -r old; do
    rm -f "$old" && echo "db-backup: antigo removido: $(basename "$old")"
done
