#!/bin/bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

leak_migration=$(grep -rl 'timeline snapshots leaked by earlier defaults' "$ROOT/migrations" | head -n 1 || true)
[[ -n $leak_migration ]] || fail "Snapper timeline leak migration exists"

test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT

fake_bin="$test_tmp/bin"
mkdir -p "$fake_bin"

cat >"$fake_bin/sudo" <<'STUB'
#!/bin/bash
printf 'sudo %s\n' "$*" >>"$TEST_LOG"
exec "$@"
STUB
chmod +x "$fake_bin/sudo"

cat >"$fake_bin/snapper" <<'STUB'
#!/bin/bash
printf 'snapper %s\n' "$*" >>"$TEST_LOG"
if [[ "$*" == *"--csvout list"* ]]; then
  echo "number,cleanup"
  for i in $(seq 1 45); do
    echo "$i,timeline"
  done
  echo "100,number"
  echo "101,"
fi
STUB
chmod +x "$fake_bin/snapper"

snapper_config="$test_tmp/root"
printf '%s\n' 'TIMELINE_CREATE="no"' 'NUMBER_CLEANUP="yes"' >"$snapper_config"

TEST_LOG="$test_tmp/calls.log" \
PATH="$fake_bin:$PATH" \
OMARCHY_SNAPPER_CONFIG_PATH="$snapper_config" \
  bash -euo pipefail "$leak_migration" >/dev/null

deletes=$(grep -c '^snapper -c root delete ' "$test_tmp/calls.log" || true)
[[ $deletes -eq 3 ]] || fail "leak migration deletes snapshots in batches" "expected 3 delete calls, got $deletes"

first_batch=$(grep -m1 '^snapper -c root delete ' "$test_tmp/calls.log")
[[ $first_batch == "snapper -c root delete $(seq -s ' ' 1 20)" ]] || fail "leak migration caps delete batches at 20 snapshots" "$first_batch"

last_batch=$(grep '^snapper -c root delete ' "$test_tmp/calls.log" | tail -n 1)
[[ $last_batch == "snapper -c root delete $(seq -s ' ' 41 45)" ]] || fail "leak migration deletes the final partial batch" "$last_batch"

! grep -E '^snapper -c root delete .*\b(100|101)\b' "$test_tmp/calls.log" || fail "leak migration only deletes timeline snapshots"
pass "leak migration removes leaked timeline snapshots in batches and keeps the rest"

# omarchy-migrate runs under set -e, so a batch that dies on a DBus timeout
# would otherwise abort the run and skip every migration queued behind it.
: >"$test_tmp/calls.log"
printf '%s\n' 'TIMELINE_CREATE="no"' 'NUMBER_CLEANUP="yes"' >"$snapper_config"

cat >"$fake_bin/snapper" <<'STUB'
#!/bin/bash
printf 'snapper %s\n' "$*" >>"$TEST_LOG"
if [[ "$*" == *"--csvout list"* ]]; then
  echo "number,cleanup"
  for i in $(seq 1 45); do
    echo "$i,timeline"
  done
  exit 0
fi
echo "failure: dbus timeout" >&2
exit 1
STUB

output=$(TEST_LOG="$test_tmp/calls.log" \
  PATH="$fake_bin:$PATH" \
  OMARCHY_SNAPPER_CONFIG_PATH="$snapper_config" \
  bash -euo pipefail "$leak_migration" 2>/dev/null) ||
  fail "leak migration survives a failed delete batch"

deletes=$(grep -c '^snapper -c root delete ' "$test_tmp/calls.log" || true)
[[ $deletes -eq 3 ]] || fail "leak migration keeps draining after a failed batch" "expected 3 delete calls, got $deletes"

# omarchy-migrate writes the completion marker even when the drain gave up, so
# what is left has to be said out loud rather than left for a rerun.
grep -qF '45 snapshots could not be deleted' <<<"$output" || fail "leak migration reports the snapshots it could not delete" "$output"
pass "leak migration tolerates a batch that fails partway"

: >"$test_tmp/calls.log"
printf '%s\n' 'TIMELINE_CREATE="yes"' >"$snapper_config"

TEST_LOG="$test_tmp/calls.log" \
PATH="$fake_bin:$PATH" \
OMARCHY_SNAPPER_CONFIG_PATH="$snapper_config" \
  bash -euo pipefail "$leak_migration" >/dev/null

[[ ! -s $test_tmp/calls.log ]] || fail "leak migration leaves deliberate timeline setups alone"
pass "leak migration skips systems where timeline snapshots are intentional"

: >"$test_tmp/calls.log"

TEST_LOG="$test_tmp/calls.log" \
PATH="$fake_bin:$PATH" \
OMARCHY_SNAPPER_CONFIG_PATH="$test_tmp/missing" \
  bash -euo pipefail "$leak_migration" >/dev/null

[[ ! -s $test_tmp/calls.log ]] || fail "leak migration skips systems without a Snapper root config"
pass "leak migration is a no-op without Snapper configured"

# Snapper's create-config writes a root-only config, and a config this user
# cannot read says nothing about whether timeline snapshots are wanted.
: >"$test_tmp/calls.log"
printf '%s\n' 'TIMELINE_CREATE="no"' >"$snapper_config"
chmod 000 "$snapper_config"

TEST_LOG="$test_tmp/calls.log" \
PATH="$fake_bin:$PATH" \
OMARCHY_SNAPPER_CONFIG_PATH="$snapper_config" \
  bash -euo pipefail "$leak_migration" >/dev/null 2>&1

chmod 600 "$snapper_config"

grep -qF "sudo grep -qFx TIMELINE_CREATE=\"no\" $snapper_config" "$test_tmp/calls.log" ||
  fail "leak migration reads a root-only Snapper config as root" "$(cat "$test_tmp/calls.log")"
pass "leak migration does not mistake an unreadable Snapper config for an intentional one"
