#!/usr/bin/env bash
# Regression tests for bin/shim-drift-check — the check that fails when the shims this
# machine executes are not the ones landed on the canonical ref. Fixture-based: it
# never spawns a PATH shim, so it is safe to run anywhere.
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
CHECK="$ROOT/bin/shim-drift-check"
PASS=0; FAIL=0
ok()  { PASS=$((PASS+1)); printf 'PASS %s\n' "$1"; }
bad() { FAIL=$((FAIL+1)); printf 'FAIL %s\n     %s\n' "$1" "$2"; }

TMP=$(mktemp -d "${TMPDIR:-/tmp}/sdc-test-XXXX")
trap 'rm -rf "$TMP"' EXIT

REPO="$TMP/repo"
BIN="$REPO/modules/workstation/claude/bin"
LIB="$REPO/modules/workstation/claude/lib"
mkdir -p "$BIN" "$LIB"
for f in _git-guard-shim.sh _cpu-guard-shim.sh _tmpjail-shim.sh _agent-session-tmux _kill-guard-shim.sh install-git-guard-real shim-drift-check generate-tool-shims install-tool-shims-real ccr podman systemctl; do
  printf 'landed %s\n' "$f" > "$BIN/$f"
done
printf 'landed shim-guard\n' > "$LIB/shim-guard.sh"
printf 'landed tmux config\n' > "$LIB/human-session.tmux.conf"
printf 'landed tool-shims snapshot\n' > "$LIB/tool-shims.snapshot.json"
git -C "$REPO" init -q
git -C "$REPO" config user.email t@t; git -C "$REPO" config user.name t; git -C "$REPO" config commit.gpgsign false
git -C "$REPO" add -A; git -C "$REPO" commit -qm landed
git -C "$REPO" branch -f canonical

LIVE="$TMP/home/.claude/bin"
mkdir -p "$LIVE" "$TMP/home/.claude/lib"
cp "$BIN"/* "$LIVE/"
cp "$LIB/shim-guard.sh" "$TMP/home/.claude/lib/"
cp "$LIB/human-session.tmux.conf" "$TMP/home/.claude/lib/"
cp "$LIB/tool-shims.snapshot.json" "$TMP/home/.claude/lib/"

REGISTRY="$TMP/shim-repos"
: >"$REGISTRY"

run() {
  OD_SHIM_LIVE_DIR="$LIVE" OD_SHIM_REPO="$REPO" OD_SHIM_REF=canonical \
    OD_SHIM_REPOS_FILE="$REGISTRY" bash "$CHECK" >"$TMP/out" 2>"$TMP/err"
}

run
rc=$?
[[ $rc -eq 0 ]] && ok "matching live tree passes" || bad "matching live tree passes" "rc=$rc err=$(cat "$TMP/err")"

printf 'drifted\n' > "$LIVE/_git-guard-shim.sh"
run
rc=$?
[[ $rc -eq 1 && "$(cat "$TMP/err")" == *_git-guard-shim.sh*differs* ]] \
  && ok "content drift in a live shim fails loudly" \
  || bad "content drift in a live shim fails loudly" "rc=$rc err=$(cat "$TMP/err")"
cp "$BIN/_git-guard-shim.sh" "$LIVE/_git-guard-shim.sh"

printf 'drifted lib\n' > "$TMP/home/.claude/lib/shim-guard.sh"
run
rc=$?
[[ $rc -eq 1 && "$(cat "$TMP/err")" == *shim-guard.sh*differs* ]] \
  && ok "content drift in the shared guard lib fails loudly" \
  || bad "content drift in the shared guard lib fails loudly" "rc=$rc err=$(cat "$TMP/err")"
cp "$LIB/shim-guard.sh" "$TMP/home/.claude/lib/shim-guard.sh"

rm -f "$LIVE/_kill-guard-shim.sh"
run
rc=$?
[[ $rc -eq 1 && "$(cat "$TMP/err")" == *"missing on this machine"* ]] \
  && ok "a shim missing from the live tree fails loudly" \
  || bad "a shim missing from the live tree fails loudly" "rc=$rc err=$(cat "$TMP/err")"
cp "$BIN/_kill-guard-shim.sh" "$LIVE/"

git -C "$REPO" worktree add -q -b old "$TMP/oldwt" >/dev/null 2>&1
OD_SHIM_LIVE_DIR="$LIVE" OD_SHIM_REPO="$TMP/oldwt" OD_SHIM_REF=canonical \
  OD_SHIM_REPOS_FILE="$REGISTRY" bash "$CHECK" >"$TMP/out" 2>"$TMP/err"
rc=$?
[[ $rc -eq 0 ]] \
  && ok "the check runs from inside a linked worktree" \
  || bad "the check runs from inside a linked worktree" "rc=$rc err=$(cat "$TMP/err")"

printf 'unrelated executable edit\n' > "$TMP/oldwt/modules/workstation/claude/bin/unrelated-tool"
run
rc=$?
[[ $rc -eq 0 && "$(cat "$TMP/err")" == "" ]] \
  && ok "changes outside the guarded file list are ignored" \
  || bad "changes outside the guarded file list are ignored" "rc=$rc err=$(cat "$TMP/err")"
rm -f "$TMP/oldwt/modules/workstation/claude/bin/unrelated-tool"

printf 'pre-fix recursing content\n' > "$TMP/oldwt/modules/workstation/claude/bin/_git-guard-shim.sh"
run
rc=$?
[[ $rc -eq 3 && "$(cat "$TMP/err")" == *"$TMP/oldwt"*uncommitted* ]] \
  && ok "a worktree holding an uncommitted shim edit reports the copy band" \
  || bad "a worktree holding an uncommitted shim edit reports the copy band" "rc=$rc err=$(cat "$TMP/err")"

printf '%s\n' "$TMP/oldwt" >"$REGISTRY"
run
rc=$?
[[ $rc -eq 3 && $(grep -c "$TMP/oldwt.*uncommitted" "$TMP/err") -eq 1 ]] \
  && ok "a linked worktree registered alongside its own checkout is scanned once" \
  || bad "a linked worktree registered alongside its own checkout is scanned once" "rc=$rc err=$(cat "$TMP/err")"
: >"$REGISTRY"

git -C "$TMP/oldwt" add -A; git -C "$TMP/oldwt" commit -qm "old shim"
run
rc=$?
[[ $rc -eq 0 && "$(cat "$TMP/err")" == "" ]] \
  && ok "a clean checkout parked off the canonical ref is not reported" \
  || bad "a clean checkout parked off the canonical ref is not reported" "rc=$rc err=$(cat "$TMP/err")"
printf 'a second uncommitted edit\n' > "$TMP/oldwt/modules/workstation/claude/bin/_git-guard-shim.sh"

git -C "$REPO" worktree add -q --detach "$TMP/newwt" >/dev/null 2>&1
rm -f "$TMP/newwt/modules/workstation/claude/bin/_kill-guard-shim.sh"
printf 'unlanded new shim\n' > "$TMP/newwt/modules/workstation/claude/bin/_kill-guard-shim.sh"
git -C "$TMP/newwt" rm -q --cached modules/workstation/claude/bin/_kill-guard-shim.sh
git -C "$TMP/newwt" commit -qm "shim not tracked here"
run
rc=$?
[[ $rc -eq 3 && "$(cat "$TMP/err")" == *"$TMP/newwt"*"not committed in its own checkout"* ]] \
  && ok "a shim absent from its checkout's HEAD is reported" \
  || bad "a shim absent from its checkout's HEAD is reported" "rc=$rc err=$(cat "$TMP/err")"
git -C "$REPO" worktree remove --force "$TMP/newwt"

printf 'drifted\n' > "$LIVE/_git-guard-shim.sh"
run
rc=$?
[[ $rc -eq 1 ]] \
  && ok "live drift outranks a drifted copy" \
  || bad "live drift outranks a drifted copy" "rc=$rc err=$(cat "$TMP/err")"
cp "$BIN/_git-guard-shim.sh" "$LIVE/_git-guard-shim.sh"
git -C "$REPO" worktree remove --force "$TMP/oldwt"

OTHER="$TMP/other"
git -C "$REPO" clone -q "$REPO" "$OTHER"
git -C "$OTHER" config user.email t@t; git -C "$OTHER" config user.name t
printf 'pre-fix recursing content\n' > "$OTHER/modules/workstation/claude/bin/_git-guard-shim.sh"
printf '%s\n' "$OTHER" >"$REGISTRY"
run
rc=$?
[[ $rc -eq 3 && "$(cat "$TMP/err")" == *"$OTHER"*uncommitted* ]] \
  && ok "a registered second checkout is scanned too" \
  || bad "a registered second checkout is scanned too" "rc=$rc err=$(cat "$TMP/err")"

printf '%s\n%s\n%s\n' "$REPO" "$REPO" "$REPO" >"$REGISTRY"
run
rc=$?
[[ $rc -eq 0 && "$(cat "$TMP/err")" == "" ]] \
  && ok "a checkout registered twice is scanned once" \
  || bad "a checkout registered twice is scanned once" "rc=$rc err=$(cat "$TMP/err")"

rm -f "$REGISTRY"
run
rc=$?
[[ $rc -eq 3 && "$(cat "$TMP/err")" == *"no checkout registry"* ]] \
  && ok "a missing checkout registry is reported, not skipped" \
  || bad "a missing checkout registry is reported, not skipped" "rc=$rc err=$(cat "$TMP/err")"
: >"$REGISTRY"

printf '%s\n' "$TMP/not-a-repo" >"$REGISTRY"
run
rc=$?
[[ $rc -eq 3 && "$(cat "$TMP/err")" == *"not a git repo"* ]] \
  && ok "a registered path that is not a repo is reported" \
  || bad "a registered path that is not a repo is reported" "rc=$rc err=$(cat "$TMP/err")"
: >"$REGISTRY"

git -C "$REPO" rm -q --cached modules/workstation/claude/bin/_tmpjail-shim.sh
git -C "$REPO" commit -qm unland
git -C "$REPO" branch -f canonical
run
rc=$?
[[ $rc -eq 1 && "$(cat "$TMP/err")" == *"not present in canonical"* ]] \
  && ok "an unlanded live shim fails loudly" \
  || bad "an unlanded live shim fails loudly" "rc=$rc err=$(cat "$TMP/err")"

echo
echo "PASS=$PASS FAIL=$FAIL"
[[ "$FAIL" -eq 0 ]]
