#!/bin/sh

set -eu

backup_dir=${BACKUP_DIR:-/backups}
ssh_key_dir=/root/.ssh
success_marker="$backup_dir/.last-success"

ssh_host=${BACKUP_SSH_HOST:-}
ssh_user=${BACKUP_SSH_USER:-backup}
ssh_port=${BACKUP_SSH_PORT:-22}
ssh_dir=${BACKUP_SSH_DIR:-}

ssh_opts="-o BatchMode=yes -o PasswordAuthentication=no -o StrictHostKeyChecking=yes"

copy_remote() {
  target=$1
  [ -n "$ssh_host" ] || return 0
  [ -d "$ssh_key_dir" ] || {
    printf 'SSH key directory %s not found\n' "$ssh_key_dir" >&2
    return 1
  }
  case "$ssh_port" in
    ''|*[!0-9]*) printf 'BACKUP_SSH_PORT must be numeric\n' >&2; return 1 ;;
  esac
  case "$ssh_user" in
    ''|*[!A-Za-z0-9_.-]*) printf 'BACKUP_SSH_USER contains unsupported characters\n' >&2; return 1 ;;
  esac
  case "$ssh_dir" in
    /|''|*[!A-Za-z0-9_./-]*)
      printf 'BACKUP_SSH_DIR must be a non-root absolute path without spaces\n' >&2
      return 1
      ;;
    /*) ;;
    *)
      printf 'BACKUP_SSH_DIR must be an absolute path\n' >&2
      return 1
      ;;
  esac

  filename=$(basename "$target")
  remote="$ssh_user@$ssh_host"
  remote_target="$ssh_dir/$filename"
  remote_temporary="$ssh_dir/.$filename.tmp"

  ssh $ssh_opts -p "$ssh_port" "$remote" "mkdir -p '$ssh_dir'" >/dev/null
  scp $ssh_opts -P "$ssh_port" "$target" "$remote:$remote_temporary"
  ssh $ssh_opts -p "$ssh_port" "$remote" \
    "mv '$remote_temporary' '$remote_target' && find '$ssh_dir' -maxdepth 1 -type f -name 'cents-*.dump' -mtime +29 -delete"
  printf 'Backup copied to %s:%s\n' "$remote" "$remote_target"
}

run_backup() {
  umask 077
  mkdir -p "$backup_dir/db"

  timestamp=$(date +%Y%m%d-%H%M%S)
  target="$backup_dir/db/cents-$timestamp.dump"
  temporary="$target.tmp"
  trap 'rm -f "$temporary"' EXIT INT TERM

  pg_dump --format=custom --file="$temporary"
  pg_restore --list "$temporary" >/dev/null
  mv "$temporary" "$target"
  trap - EXIT INT TERM

  printf 'Backup created: %s\n' "$target"

  copy_remote "$target"
  find "$backup_dir/db" -maxdepth 1 -type f -name 'cents-*.dump' -mtime +29 -delete
  touch "$success_marker"
  printf 'Backup completed successfully\n'
}

check_health() {
  pgrep crond >/dev/null || return 1
  [ -f "$success_marker" ] || return 1
  now=$(date +%s)
  last_success=$(stat -c %Y "$success_marker")
  age=$((now - last_success))
  [ "$age" -ge 0 ] && [ "$age" -le 108000 ]
}

case "${1:-cron}" in
  run)
    run_backup
    ;;
  cron)
    printf '%s\n' \
      '0 2 * * * /usr/local/bin/cents-backup run >> /proc/1/fd/1 2>> /proc/1/fd/2' \
      > /etc/crontabs/root
    printf 'Backup scheduler started: daily at 02:00 %s, retaining 30 days\n' "${TZ:-local time}"
    exec crond -f -l 2
    ;;
  health)
    check_health
    ;;
  *)
    printf 'Unknown command: %s\n' "$1" >&2
    exit 2
    ;;
esac
