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

PREFIX="bcbc"
MODE="list"
VMID=""
DRY_RUN=0
LOG_DIR="/var/log/bcbc-lxc-snapshots"
STAMP="$(date +%Y%m%d-%H%M%S)"
RUNLOG="${LOG_DIR}/run-${STAMP}.log"
MANIFEST="${LOG_DIR}/manifest-${STAMP}.tsv"

safe_name() {
  local s="$1"
  s="${s//[^A-Za-z0-9_-]/-}"
  printf '%s' "${s:0:30}"
}

log() {
  printf '%s %s\n' "$(date '+%F %T%z')" "$*" | tee -a "$RUNLOG"
}

need_root() {
  [[ $EUID -eq 0 ]] || {
    echo "ERROR: run as root on the Proxmox host." >&2
    exit 1
  }
}

need_cmds() {
  command -v pct >/dev/null || {
    echo "ERROR: pct not found. Run this on a Proxmox VE host." >&2
    exit 1
  }
}

list_one() {
  local id="$1" name
  name="$(pct config "$id" 2>/dev/null | awk -F': ' '$1=="hostname"{print $2;exit}')"
  printf '\nCT %s  %s\n' "$id" "${name:-unknown}"
  pct listsnapshot "$id" 2>/dev/null || echo "  (no snapshots or listing unavailable)"
}

list_all() {
  pct list
  while read -r id _; do
    [[ "$id" =~ ^[0-9]+$ ]] || continue
    list_one "$id"
  done < <(pct list | tail -n +2)
}

snapshot_one() {
  local id="$1" name snap desc

  pct status "$id" >/dev/null 2>&1 || {
    log "ERROR CT ${id}: not found"
    return 1
  }

  name="$(pct config "$id" | awk -F': ' '$1=="hostname"{print $2;exit}')"
  name="$(safe_name "${name:-ct$id}")"
  snap="$(safe_name "${PREFIX}-${STAMP}")"
  desc="BCBC checkpoint ${STAMP} host=${HOSTNAME} ct=${id} name=${name}"

  log "CT ${id} (${name}): creating snapshot ${snap}"

  if (( DRY_RUN )); then
    log "DRY-RUN: pct snapshot ${id} ${snap} --description '${desc}'"
    printf '%s\t%s\t%s\t%s\tDRY-RUN\n' \
      "$STAMP" "$id" "$name" "$snap" >> "$MANIFEST"
    return 0
  fi

  if pct snapshot "$id" "$snap" --description "$desc" >> "$RUNLOG" 2>&1; then
    log "SUCCESS CT ${id}: ${snap}"
    printf '%s\t%s\t%s\t%s\tSUCCESS\n' \
      "$STAMP" "$id" "$name" "$snap" >> "$MANIFEST"
  else
    log "FAILED CT ${id}: ${snap}"
    printf '%s\t%s\t%s\t%s\tFAILED\n' \
      "$STAMP" "$id" "$name" "$snap" >> "$MANIFEST"
    return 1
  fi
}

while (($#)); do
  case "$1" in
    list)
      MODE="list"
      shift
      ;;
    --all)
      MODE="all"
      shift
      ;;
    --vmid)
      MODE="one"
      VMID="${2:-}"
      shift 2
      ;;
    --prefix)
      PREFIX="$(safe_name "${2:-bcbc}")"
      shift 2
      ;;
    --dry-run)
      DRY_RUN=1
      shift
      ;;
    -h|--help)
      cat <<'EOF'
Usage:
  bcbc-lxc-snapshot list
  bcbc-lxc-snapshot --all [--dry-run] [--prefix NAME]
  bcbc-lxc-snapshot --vmid ID [--dry-run] [--prefix NAME]

Safety:
  Default action is LIST ONLY.
  No snapshot is created unless --all or --vmid is explicitly supplied.
  No pruning or deletion is implemented in this public starter.
EOF
      exit 0
      ;;
    *)
      echo "Unknown option: $1" >&2
      exit 2
      ;;
  esac
done

need_root
need_cmds

mkdir -p "$LOG_DIR"
touch "$RUNLOG" "$MANIFEST"
chmod 750 "$LOG_DIR"
chmod 640 "$RUNLOG" "$MANIFEST"

if [[ "$MODE" == "list" ]]; then
  list_all
  exit 0
fi

fail=0

if [[ "$MODE" == "one" ]]; then
  [[ "$VMID" =~ ^[0-9]+$ ]] || {
    echo "ERROR: --vmid requires a numeric container ID." >&2
    exit 2
  }
  snapshot_one "$VMID" || fail=1
else
  mapfile -t ids < <(pct list | awk 'NR>1 && $1~/^[0-9]+$/{print $1}')
  for id in "${ids[@]}"; do
    snapshot_one "$id" || fail=1
  done
fi

log "Manifest: ${MANIFEST}"
log "Run log: ${RUNLOG}"
exit "$fail"
