#!/bin/bash
# Sync database backups to offsite host (astra) via Tailscale.
# Called by backup-db.sh after each successful backup.
#
# Usage: sync-backup-offsite.sh <db_name> <backup_file>
#   db_name      — database name (used for subdir and prune glob)
#   backup_file  — absolute path to the timestamped .sql.gz produced by this run
#
# On astra, backups land in /opt/backups/mnw/<db_name>/, with a per-DB
# latest.sql.gz hard link maintained for downstream pullers (sando).
#
# Setup on astra (one-time):
#   mkdir -p /opt/backups/mnw
#   chown max:max /opt/backups/mnw
#
# Setup on Hetzner: tailnet ACL grants tag:prod -> max@tag:testing SSH (no
# pubkey wrangling — Tailscale SSH bypasses authorized_keys via tailnet cert).

set -euo pipefail

DB_NAME="${1:?usage: sync-backup-offsite.sh <db_name> <backup_file>}"
BACKUP_FILE="${2:?usage: sync-backup-offsite.sh <db_name> <backup_file>}"

OFFSITE_HOST="100.106.221.39"  # astra (Tailscale IP)
OFFSITE_USER="max"
OFFSITE_DIR="/opt/backups/mnw/${DB_NAME}"
OFFSITE_RETENTION_DAYS=30
WAM_URL="${WAM_URL:-http://127.0.0.1:7890}"

wam_alert() {
    local title="$1"
    local body="${2:-}"
    curl -sf -X POST "$WAM_URL/tickets" \
        -H "Content-Type: application/json" \
        -d "{\"title\": \"$title\", \"body\": \"$body\", \"priority\": \"high\", \"source\": \"backup-offsite\"}" \
        >/dev/null 2>&1 || true
}

if [ ! -f "$BACKUP_FILE" ]; then
    echo "[$(date -Iseconds)] OFFSITE(${DB_NAME}): backup file missing: $BACKUP_FILE"
    exit 0
fi

BASENAME=$(basename "$BACKUP_FILE")
SSH_OPTS="-o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new"

echo "[$(date -Iseconds)] OFFSITE(${DB_NAME}): Syncing ${BASENAME} to ${OFFSITE_HOST}:${OFFSITE_DIR}"

# Ensure the per-DB offsite dir exists.
ssh ${SSH_OPTS} "${OFFSITE_USER}@${OFFSITE_HOST}" "mkdir -p '${OFFSITE_DIR}'"

if rsync -e "ssh ${SSH_OPTS}" --timeout=120 \
    "$BACKUP_FILE" \
    "${OFFSITE_USER}@${OFFSITE_HOST}:${OFFSITE_DIR}/"; then
    echo "[$(date -Iseconds)] OFFSITE(${DB_NAME}): Transfer complete"
else
    echo "[$(date -Iseconds)] OFFSITE(${DB_NAME}): Transfer FAILED (astra unreachable or SSH error)"
    wam_alert "Offsite backup sync failed (${DB_NAME})" "rsync to ${OFFSITE_HOST}:${OFFSITE_DIR} failed for ${BASENAME}. Check Tailscale connectivity and SSH auth."
    exit 0
fi

# Refresh the per-DB latest.sql.gz hard link on astra (atomic temp-then-rename).
ssh ${SSH_OPTS} "${OFFSITE_USER}@${OFFSITE_HOST}" "
    set -e
    cd '${OFFSITE_DIR}'
    ln -f '${BASENAME}' latest.sql.gz.new
    mv -Tf latest.sql.gz.new latest.sql.gz
" || echo "[$(date -Iseconds)] OFFSITE(${DB_NAME}): WARNING — failed to refresh latest.sql.gz"

# Prune offsite backups older than retention.
DELETED=$(ssh ${SSH_OPTS} "${OFFSITE_USER}@${OFFSITE_HOST}" \
    "find ${OFFSITE_DIR} -name '${DB_NAME}-*.sql.gz' -mtime +${OFFSITE_RETENTION_DAYS} -delete -print 2>/dev/null | wc -l" \
    2>/dev/null || echo "0")
if [ "$DELETED" -gt 0 ]; then
    echo "[$(date -Iseconds)] OFFSITE(${DB_NAME}): Pruned ${DELETED} backup(s) older than ${OFFSITE_RETENTION_DAYS} days"
fi

TOTAL=$(ssh ${SSH_OPTS} "${OFFSITE_USER}@${OFFSITE_HOST}" \
    "ls ${OFFSITE_DIR}/${DB_NAME}-*.sql.gz 2>/dev/null | wc -l" \
    2>/dev/null || echo "?")
echo "[$(date -Iseconds)] OFFSITE(${DB_NAME}): Total backups on astra: ${TOTAL}"
