#!/bin/sh
# Nightly Postgres backup loop for Meezi.
#
# Runs inside a small postgres-image container (has pg_dump/gzip). Every day at
# ~02:00 Tehran it dumps the whole database, gzips it, and keeps the last
# RETAIN_DAYS files in /backups. Designed to be dead-simple and dependency-free:
# no cron daemon, just sleep-until-next-run so it survives container restarts.
#
# Env:
#   PGHOST, PGUSER, PGPASSWORD, PGDATABASE  — connection (from compose)
#   RETAIN_DAYS    — how many daily dumps to keep (default 14)
#   BACKUP_HOUR    — local hour to run (default 2 = 02:00)
set -eu

RETAIN_DAYS="${RETAIN_DAYS:-14}"
BACKUP_HOUR="${BACKUP_HOUR:-2}"
OUT_DIR=/backups
export TZ="${TZ:-Asia/Tehran}"

log() { echo "[pg-backup $(date '+%Y-%m-%d %H:%M:%S %Z')] $*"; }

run_backup() {
  ts=$(date '+%Y%m%d_%H%M%S')
  tmp="$OUT_DIR/.meezi_${ts}.sql.gz.partial"
  final="$OUT_DIR/meezi_${ts}.sql.gz"
  log "starting dump → $final"
  # pg_dump streams to gzip; .partial then atomic rename so a crash never
  # leaves a truncated file that looks like a good backup.
  if pg_dump --no-owner --no-privileges | gzip -9 > "$tmp"; then
    mv "$tmp" "$final"
    size=$(wc -c < "$final" 2>/dev/null || echo '?')
    log "done ($size bytes)"
  else
    rm -f "$tmp"
    log "ERROR: dump failed"
    return 1
  fi
  # Rotate: delete dumps older than RETAIN_DAYS days.
  find "$OUT_DIR" -maxdepth 1 -name 'meezi_*.sql.gz' -mtime "+${RETAIN_DAYS}" -print -delete | while read -r f; do
    log "rotated out $f"
  done
}

seconds_until_next_run() {
  now_h=$(date '+%-H'); now_m=$(date '+%-M'); now_s=$(date '+%-S')
  now=$(( now_h * 3600 + now_m * 60 + now_s ))
  target=$(( BACKUP_HOUR * 3600 ))
  if [ "$now" -lt "$target" ]; then
    echo $(( target - now ))
  else
    echo $(( 86400 - now + target ))
  fi
}

log "backup loop started (retain ${RETAIN_DAYS}d, daily at ${BACKUP_HOUR}:00 ${TZ})"
# Take one backup immediately on first boot so we never sit a full day with none.
run_backup || true
while true; do
  wait_s=$(seconds_until_next_run)
  log "next backup in ${wait_s}s"
  sleep "$wait_s"
  run_backup || true
done
