#!/usr/bin/env bash
#
# Turista database backup script
#
# Run ON THE SERVER, from the Laravel app root (the folder containing `artisan`):
#
#   bash backup-db              # dump the DB now
#
# For a daily backup, install this cron entry (crontab -e), e.g. 03:10 every night:
#
#   10 3 * * * cd /path/to/turista && bash backup-db >> storage/logs/backup.log 2>&1
#
# Safe to re-run. Credentials are read from .env — nothing is hardcoded here.
#
set -euo pipefail

# Keep this many days of backups (override: BACKUP_KEEP_DAYS=60 bash backup-db)
KEEP_DAYS="${BACKUP_KEEP_DAYS:-30}"
BACKUP_DIR="${BACKUP_DIR:-storage/app/backups}"

log()  { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"; }
fail() { printf '\nBACKUP FAILED: %s\n' "$*" >&2; exit 1; }

# ---------------------------------------------------------------------------
# Pre-flight checks
# ---------------------------------------------------------------------------
[ -f ".env" ]            || fail "Run this from the Laravel app root (no '.env' file here)."
command -v mysqldump >/dev/null || fail "mysqldump is not installed (apt install mysql-client / default-mysql-client)."

# Read DB_* values from .env (last definition wins, quotes stripped).
env_value() {
  grep -E "^$1=" .env | tail -n1 | cut -d= -f2- | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//"
}

DB_CONNECTION="$(env_value DB_CONNECTION)"
DB_HOST="$(env_value DB_HOST)"
DB_PORT="$(env_value DB_PORT)"
DB_DATABASE="$(env_value DB_DATABASE)"
DB_USERNAME="$(env_value DB_USERNAME)"
DB_PASSWORD="$(env_value DB_PASSWORD)"

[ "$DB_CONNECTION" = "mysql" ] || fail "DB_CONNECTION is '${DB_CONNECTION}', this script only handles mysql."
[ -n "$DB_DATABASE" ]         || fail "DB_DATABASE is not set in .env."

mkdir -p "$BACKUP_DIR"

STAMP="$(date '+%Y%m%d-%H%M%S')"
FILE="${BACKUP_DIR}/${DB_DATABASE}-${STAMP}.sql.gz"

log "Dumping ${DB_DATABASE}@${DB_HOST}:${DB_PORT:-3306} -> ${FILE}"

# ---------------------------------------------------------------------------
# Dump
# ---------------------------------------------------------------------------
mysqldump \
  --host="${DB_HOST:-127.0.0.1}" \
  --port="${DB_PORT:-3306}" \
  --user="${DB_USERNAME}" \
  --password="${DB_PASSWORD}" \
  --single-transaction \
  --quick \
  --routines \
  --triggers \
  "$DB_DATABASE" | gzip > "$FILE" \
  || fail "mysqldump failed — check DB_* credentials in .env and that mysqldump can reach the DB."

# gzip gets no exit status from the pipe, so verify the dump is non-trivial.
MIN_BYTES=2048
ACTUAL_BYTES="$(wc -c < "$FILE")"
[ "$ACTUAL_BYTES" -ge "$MIN_BYTES" ] \
  || fail "Dump file is only ${ACTUAL_BYTES} bytes — treating that as a failed backup, keeping the file for inspection."

log "Dump complete ($(du -h "$FILE" | cut -f1))."

# ---------------------------------------------------------------------------
# Rotate old backups
# ---------------------------------------------------------------------------
log "Removing backups older than ${KEEP_DAYS} days from ${BACKUP_DIR}"
find "$BACKUP_DIR" -name '*.sql.gz' -type f -mtime "+${KEEP_DAYS}" -print -delete

log "Done. Current backups:"
ls -lh "$BACKUP_DIR"/*.sql.gz