#!/usr/bin/env bash
set -Eeuo pipefail

# CONFIG
HOST="$(hostname -s)"
DATE="$(date +'%Y%m%d-%H%M%S')"
MOUNTPOINT="/mnt/backups"
DEST_NFS="/mnt/backups/${HOST}"
FALLBACK="/var/backups/${HOST}"
INCLUDES="/usr/local/etc/backup.includes"
EXCLUDES="/usr/local/etc/backup.excludes"
MODE="${1:-rsync}"  # 'rsync' (default) or 'tar'
LOG_TAG="backup"
LOG_DIR="/var/log/backup"
RUN_DIR="/var/lib/backup"   # for state, e.g., last-run markers

# Ensure dirs exist
mkdir -p "${LOG_DIR}" "${RUN_DIR}"

log() {
  # Log to syslog and to a plain file for logrotate
  /usr/bin/logger -t "${LOG_TAG}" "$*"
  echo "$(date -Is) $*" >> "${LOG_DIR}/backup.log"
}
die() {
  log "ERROR: $*"
  exit 1
}


check_sources() {
  [[ -s "${INCLUDES}" ]] || die "Missing includes file: ${INCLUDES}"
  [[ -s "${EXCLUDES}" ]] || log "WARN: excludes file ${EXCLUDES} missing or empty"
}

resolve_dest() {
  # Prefer NFS if mounted & writable; otherwise fallback
  if mountpoint -q /mnt/backups && [[ -w "${DEST_NFS}" || -w "/mnt/backups" ]]; then
    echo "${DEST_NFS}"
  else
    mkdir -p "${FALLBACK}"
    echo "${FALLBACK}"
  fi
}

do_rsync() {
  local dest="$1/${DATE}"
  mkdir -p "${dest}"
  # Build rsync include/exclude arguments
  local inc_args=()
  while read -r p; do [[ -n "${p}" ]] && inc_args+=("${p}"); done < "${INCLUDES}"

  local exc_args=()
  if [[ -s "${EXCLUDES}" ]]; then
    while read -r p; do [[ -n "${p}" ]] && exc_args+=("--exclude=${p}"); done < "${EXCLUDES}"
  fi

  # Use archive mode with ACLs/xattrs if available; --numeric-ids to preserve ids consistently
  rsync -aAXH --numeric-ids --delete "${exc_args[@]}" "${inc_args[@]}" "${dest}/"
}

do_tar() {
  local dest="$1"
  mkdir -p "${dest}"
  local tarfile="${dest}/backup-${DATE}.tar"
  local exc_file="${EXCLUDES}"
  # Create listing file for reproducibility
  local listfile="${RUN_DIR}/tarlist-${DATE}.txt"
  cp "${INCLUDES}" "${listfile}"

  # Build tar with exclusions
  local exc_args=()
  [[ -s "${exc_file}" ]] && exc_args=(--exclude-from="${exc_file}")

  tar -cpf "${tarfile}" --xattrs --acls "${exc_args[@]}" -T "${listfile}" 2>> "${LOG_DIR}/backup.log" | /usr/bin/logger -t "${LOG_TAG}"

  # Compress after create to keep permissions metadata consistent
  gzip -9 "${tarfile}"
}

main() {
  log "Starting backup in mode=${MODE}"
  check_sources
  local dest
  dest="$(resolve_dest)"
  log "Resolved destination: ${dest}"

  case "${MODE}" in
    rsync) do_rsync "${dest}" ;;
    tar)   do_tar   "${dest}" ;;
    *)     die "Unknown mode: ${MODE} (use 'rsync' or 'tar')" ;;
  esac

  # Write a success marker
  echo "${DATE} ${MODE} OK -> ${dest}" > "${RUN_DIR}/last-success"
  log "Backup completed successfully: ${MODE} -> ${dest}"
}

main "$@"

