#!/bin/bash
# Generated by nbkp sh — ${{ timestamp }}
${{ config_line }}
#
# Preserved from nbkp run:
#   - All 4 rsync command variants (local→local, local→remote, remote→local, remote→remote)
#   - SSH options (port, key, -o options, proxy jump -J)
#   - Rsync filters and filter-file support
#   - Btrfs: snapshot creation, pruning
#   - Hard-link: incremental backups via --link-dest, symlink management, pruning
#   - Pre-flight checks: volume sentinels (.nbkp-vol), endpoint sentinels (.nbkp-src/.nbkp-dst)
#   - Dry-run and progress mode support (as runtime script arguments)
#   - Nonzero exit on any sync failure
#
# Dropped from nbkp run:
#   - Rich console output (spinners, tables, progress bars) → simple log messages
#   - JSON output mode → not applicable for a shell script
#   - Python runtime / config parsing → all values hardcoded
#   - --strict/--no-strict flag → checks are inline, comment out if not needed
#   - Paramiko-only SSH options (channel_timeout, disabled_algorithms) → no ssh CLI equivalent
#   - Volume mount management (LUKS attach/close, systemctl mount/umount) → credential
#     retrieval depends on keyring/prompt/command backends that don't translate to shell.
#     Volumes with mount config must be manually mounted/umounted before/after running
#     this script. Use: nbkp volumes mount -c <config> / nbkp volumes umount -c <config>

# Unofficial bash strict mode (http://redsymbol.net/articles/unofficial-bash-strict-mode/)
set -euo pipefail
IFS=$'\n\t'
<% if has_script_dir %>

NBKP_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
<% endif %>

NBKP_DRY_RUN=false
NBKP_PROGRESS=""

# --- Argument parsing ---
while [ $# -gt 0 ]; do
  case "$1" in
    -n|--dry-run) NBKP_DRY_RUN=true; shift;;
    --progress=*) NBKP_PROGRESS="${1#--progress=}"; shift;;
    --progress) NBKP_PROGRESS="$2"; shift 2;;
    -p) NBKP_PROGRESS="$2"; shift 2;;
    *) echo "Unknown option: $1" >&2; exit 1;;
  esac
done

NBKP_FAILURES=0
nbkp_log() {
    if [ "$NBKP_DRY_RUN" = true ]; then
        echo "[nbkp] [dry-run] $*" >&2
    else
        echo "[nbkp] $*" >&2
    fi
}

# --- Rsync runtime flags ---
RSYNC_DRY_RUN_FLAG=""
if [ "$NBKP_DRY_RUN" = true ]; then RSYNC_DRY_RUN_FLAG="--dry-run"; fi
RSYNC_PROGRESS_FLAGS=""
case "$NBKP_PROGRESS" in
  none) ;;
  overall) RSYNC_PROGRESS_FLAGS="--info=progress2 --stats --human-readable";;
  per-file) RSYNC_PROGRESS_FLAGS="-v --progress --human-readable";;
  full) RSYNC_PROGRESS_FLAGS="-v --progress --info=progress2 --stats --human-readable";;
  "") ;;
  *) echo "Unknown progress mode: $NBKP_PROGRESS (use 'none', 'overall', 'per-file', or 'full')" >&2; exit 1;;
esac

# --- Volume checks ---
<% for check in volume_checks %>
${{ check }}
<% endfor %>

# --- Sync functions ---
<% for sync in syncs %>
<% if sync.enabled %>

${{ sync.fn_name }}() {
    nbkp_log "Starting sync: ${{ sync.slug }}"

    # Pre-flight checks
${{ sync.preflight | indent(4, first=true) }}
<% if sync.has_hard_link %>

    # Cleanup orphaned snapshots
${{ sync.orphan_cleanup | indent(4, first=true) }}

    # Link-dest resolution (latest snapshot for incremental backup)
${{ sync.link_dest | indent(4, first=true) }}

    # Create snapshot directory
${{ sync.hl_mkdir | indent(4, first=true) }}
<% endif %>
<% if sync.has_btrfs %>

    # Link-dest resolution (latest snapshot for incremental backup)
${{ sync.link_dest | indent(4, first=true) }}
<% endif %>

    # Rsync
${{ sync.rsync | indent(4, first=true) }}
<% if sync.has_btrfs %>

    # Btrfs snapshot (skip if dry-run)
${{ sync.snapshot | indent(4, first=true) }}

    # Update latest symlink (skip if dry-run)
${{ sync.symlink | indent(4, first=true) }}
<% if sync.has_prune %>

    # Prune old snapshots (max: ${{ sync.max_snapshots }})
${{ sync.prune | indent(4, first=true) }}
<% endif %>
<% endif %>
<% if sync.has_hard_link %>

    # Update latest symlink (skip if dry-run)
${{ sync.symlink | indent(4, first=true) }}
<% if sync.has_prune %>

    # Prune old snapshots (max: ${{ sync.max_snapshots }})
${{ sync.hl_prune | indent(4, first=true) }}
<% endif %>
<% endif %>

    nbkp_log "Completed sync: ${{ sync.slug }}"
}
<% else %>

# : disabled — ${{ sync.slug }}
${{ sync.disabled_body }}
<% endif %>
<% endfor %>

# --- Run all syncs ---
<% if portable %>
NBKP_FAILED=" "
nbkp_has_failed() {
    case "$NBKP_FAILED" in *" $1 "*) return 0 ;; *) return 1 ;; esac
}
<% else %>
declare -A NBKP_FAILED=()
<% endif %>
<% for sync in syncs %>
<% if sync.enabled %>
<% if sync.predecessors %>
<% if portable %>
if <% for dep in sync.predecessors %><% if not loop.first %> || <% endif %>nbkp_has_failed "${{ dep }}"<% endfor %>; then
    nbkp_log "CANCELLED ${{ sync.slug }}: dependency failed"
    NBKP_FAILED="${NBKP_FAILED}${{ sync.fn_name }} "
    NBKP_FAILURES=$((NBKP_FAILURES + 1))
else
    ${{ sync.fn_name }} || { NBKP_FAILED="${NBKP_FAILED}${{ sync.fn_name }} "; NBKP_FAILURES=$((NBKP_FAILURES + 1)); }
fi
<% else %>
if <% for dep in sync.predecessors %><% if not loop.first %> || <% endif %>[ "${NBKP_FAILED[${{ dep }}]+set}" = "set" ]<% endfor %>; then
    nbkp_log "CANCELLED ${{ sync.slug }}: dependency failed"
    NBKP_FAILED[${{ sync.fn_name }}]=1
    NBKP_FAILURES=$((NBKP_FAILURES + 1))
else
    ${{ sync.fn_name }} || { NBKP_FAILED[${{ sync.fn_name }}]=1; NBKP_FAILURES=$((NBKP_FAILURES + 1)); }
fi
<% endif %>
<% else %>
<% if portable %>
${{ sync.fn_name }} || { NBKP_FAILED="${NBKP_FAILED}${{ sync.fn_name }} "; NBKP_FAILURES=$((NBKP_FAILURES + 1)); }
<% else %>
${{ sync.fn_name }} || { NBKP_FAILED[${{ sync.fn_name }}]=1; NBKP_FAILURES=$((NBKP_FAILURES + 1)); }
<% endif %>
<% endif %>
<% else %>
# ${{ sync.fn_name }}  # disabled
<% endif %>
<% endfor %>

# --- Summary ---
if [ "$NBKP_FAILURES" -gt 0 ]; then
    nbkp_log "$NBKP_FAILURES sync(s) failed"
    exit 1
fi
nbkp_log "All syncs completed successfully"
