#!/usr/bin/env bash
# b3-cat — create / verify BLAKE3 checksum catalog(s)
set -euo pipefail
shopt -s nullglob inherit_errexit

# ── Configurable defaults ───────────────────────────────────────────────
LOG_PREFIX='📦'
HASHCMD=${HASHCMD:-b3sum}      # override with env if desired
CATALOG=${CATALOG:-BLAKE3SUMS}
HASH_ARGS=()                   # extra args to b3sum for hashing
CHECK_ARGS=(--check --strict)  # strict verification

# ── Log helpers ─────────────────────────────────────────────────────────
log()  { printf '%s %s\n' "$LOG_PREFIX" "$*"; }
ok()   { printf '✔️  %s\n' "$*"; }
warn() { printf '⚠️  %s\n' "$*"; }
err()  { printf '❌  %s\n' "$*" >&2; }

# ── Verify dependency ───────────────────────────────────────────────────
need_hashcmd() {
  command -v "$HASHCMD" &>/dev/null || {
    err "$HASHCMD not found; install it or set HASHCMD.";
    exit 127; }
}

# ── Create catalog for DIR or FILE ──────────────────────────────────────
create_catalog() {
  need_hashcmd
  local target=${1:-.}

  [[ -e $target ]] || { err "Path '$target' does not exist."; return 1; }

  local tmp; tmp=$(mktemp)    # auto-clean in trap
  trap 'rm -f "$tmp"' RETURN

  log "Generating $CATALOG for $target …"

  if [[ -d $target ]]; then
    # directories: hash every regular file (skip existing catalog & .git)
    find "$target" -type f ! -name "$CATALOG" ! -path "*/.git/*" -print0 \
      | xargs -0 "$HASHCMD" "${HASH_ARGS[@]}" >"$tmp"
    local out="$target/$CATALOG"
  else
    "$HASHCMD" "${HASH_ARGS[@]}" "$target" >"$tmp"
    local out="$(dirname "$target")/$CATALOG"
  fi

  sort -k2 "$tmp" > "$out"
  rm -f "$tmp"

  log "Preview of $(basename "$out"):"
  head -n 5 "$out" || true
  ok "Wrote $(basename "$out") with $(grep -cve '^[[:space:]]*$' "$out") entries"
}

# ── Verify catalog ──────────────────────────────────────────────────────
verify_catalog() {
  need_hashcmd
  local dir=${1:-.}
  local catalog="$dir/$CATALOG"
  [[ -f $catalog ]] || { err "$catalog missing."; return 1; }

  log "Verifying checksums in $(realpath "$catalog") …"
  if ( cd "$dir" && "$HASHCMD" "${CHECK_ARGS[@]}" "$CATALOG" ); then
       ok "All OK"
  else warn "Mismatch detected."; return 2; fi
}

# ── Help ────────────────────────────────────────────────────────────────
usage() {
cat <<EOF
Usage: ${0##*/} [--check|-c] [PATH]

PATH  a directory or single file (default: .)

Examples
  ${0##*/}           # create catalog in current dir
  ${0##*/} /path     # create for that dir
  ${0##*/} foo.tar.xz          # create alongside file
  ${0##*/} --check             # verify catalog in .
  ${0##*/} -c /path/to/dir     # verify in dir
EOF
}

# ── Main dispatcher ─────────────────────────────────────────────────────
case ${1:-} in
  -h|--help)  usage ;;
  -c|--check) shift; verify_catalog "${1:-.}" ;;
  *)          create_catalog "${1:-.}" ;;
esac
