#!/usr/bin/env bash
# test-rp-isolate.sh — regression suite for rp-isolate.sh. Self-contained: builds a throwaway
# origin+primary repo pair under a tmp dir, runs setup/teardown/gc, asserts BOTH happy and refuse paths.
set -uo pipefail
SELF_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
RP="$SELF_DIR/rp-isolate.sh"
pass=0; fail=0
ok()   { if [[ "$2" == "$3" ]]; then echo "PASS: $1"; pass=$((pass+1)); else echo "FAIL: $1 — got '$2' want '$3'"; fail=$((fail+1)); fi; }
okne() { if [[ -n "$2" ]]; then echo "PASS: $1"; pass=$((pass+1)); else echo "FAIL: $1 — empty"; fail=$((fail+1)); fi; }

WORK=$(mktemp -d "${TMPDIR:-/tmp}/rpiso-test.XXXXXX")
SLUG="rpiso-selftest"
ISO_ROOT="/tmp/rp-iso"
cleanup() {
  bash "$RP" teardown "$SLUG" >/dev/null 2>&1
  bash "$RP" teardown "${SLUG}-dollar" >/dev/null 2>&1
  rm -rf -- "$WORK"
}
trap cleanup EXIT

export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t

# ── fixture: bare origin + primary working clone with a seeded (uncommitted) plan + spec anchor ──
ORIGIN="$WORK/origin.git"
git init -q --bare -b main "$ORIGIN"
SEED="$WORK/seed"; git init -q -b main "$SEED"
echo "# harness" > "$SEED/README.md"
mkdir -p "$SEED/docs/specs"; echo "spec body" > "$SEED/docs/specs/2026-06-30-${SLUG}-design.md"
git -C "$SEED" add -A; git -C "$SEED" commit -q -m init
git -C "$SEED" remote add origin "$ORIGIN"; git -C "$SEED" push -q origin main

PROJECTS="$WORK/Projects"; PRIMARY="$PROJECTS/harness"
mkdir -p "$PROJECTS"
git clone -q "$ORIGIN" "$PRIMARY"
# plan artifacts live UNCOMMITTED in the primary working tree (the real-world case --isolate must seed).
mkdir -p "$PRIMARY/docs/plans"
JSONL="$PRIMARY/docs/plans/2026-06-30-${SLUG}.jsonl"
cat > "$JSONL" <<EOF
{"type":"meta","schema":"session-state/v1","slug":"${SLUG}","land_mode":"merge-to-main","base_branch":"main","land_testcmd":"bash -c 'echo land-gate-ok'"}
{"type":"anchor","path":"docs/specs/2026-06-30-${SLUG}-design.md","what":"spec"}
{"type":"task","id":"t1","wave":1,"desc":"x","status":"PENDING","deps":[]}
EOF
echo "# plan" > "${JSONL%.jsonl}.md"

# ── 1. setup happy path ──────────────────────────────────────────────────────
OUT=$(RUN_PLAN_PROJECTS="$PROJECTS" bash "$RP" setup "$SLUG" 2>"$WORK/setup.err"); rc=$?
ok   "setup: exit 0" "$rc" "0"
[[ $rc -eq 0 ]] || { echo "--- setup.err ---"; cat "$WORK/setup.err"; }
CLONE="$ISO_ROOT/$SLUG/repo"
ok   "setup: reused=false on first run"        "$(printf '%s' "$OUT" | grep -c '"reused":false')" "1"
ok   "setup: clone .git exists"                "$([[ -d "$CLONE/.git" ]] && echo y)" "y"
ok   "setup: plan jsonl seeded into clone"     "$([[ -f "$CLONE/docs/plans/2026-06-30-${SLUG}.jsonl" ]] && echo y)" "y"
ok   "setup: plan md seeded into clone"        "$([[ -f "$CLONE/docs/plans/2026-06-30-${SLUG}.md" ]] && echo y)" "y"
ok   "setup: spec anchor seeded into clone"    "$([[ -f "$CLONE/docs/specs/2026-06-30-${SLUG}-design.md" ]] && echo y)" "y"
ok   "setup: land_mode flipped to pr in clone" "$(grep -c '"land_mode":"pr"' "$CLONE/docs/plans/2026-06-30-${SLUG}.jsonl")" "1"
ok   "setup: primary jsonl land_mode UNCHANGED" "$(grep -c '"land_mode":"merge-to-main"' "$JSONL")" "1"
ok   "setup: pr ship wrapper materialized"     "$([[ -f "$CLONE/.claude/scripts/ship.sh" ]] && echo y)" "y"
ok   "setup: wrapper MODE is pr"               "$(grep -c "^MODE='pr'\$" "$CLONE/.claude/scripts/ship.sh")" "1"
# the baked wrapper must be RUNNABLE: a $-laden testcmd would expand under set -u at load → drift crashes.
( cd "$CLONE" && bash "$CLONE/.claude/scripts/ship.sh" drift >/dev/null 2>&1 ); dr=$?
ok   "setup: baked ship.sh 'drift' runs (no set-u crash)" "$([[ $dr -eq 0 ]] && echo y)" "y"
ok   "setup: sentinel written"                 "$([[ -f "$ISO_ROOT/$SLUG/.rp-isolate-sentinel" ]] && echo y)" "y"
okne "setup: projects path in JSON"            "$(printf '%s' "$OUT" | grep -oE '"projects":"[^"]*"')"

# ── 2. idempotent reuse: second setup REUSES (must not re-clone, must not wipe in-clone state) ──
touch "$CLONE/docs/plans/.run-progress-marker"   # a file the run would have written
OUT2=$(RUN_PLAN_PROJECTS="$PROJECTS" bash "$RP" setup "$SLUG" 2>/dev/null)
ok   "reuse: reused=true on second run"        "$(printf '%s' "$OUT2" | grep -c '"reused":true')" "1"
ok   "reuse: in-clone state NOT wiped"         "$([[ -f "$CLONE/docs/plans/.run-progress-marker" ]] && echo y)" "y"

# ── 3. teardown REFUSE branch: a dir with NO sentinel must NOT be removed ─────
FOREIGN="$ISO_ROOT/${SLUG}-foreign"
mkdir -p "$FOREIGN/keep"; echo precious > "$FOREIGN/keep/data"
rc=0; bash "$RP" teardown "${SLUG}-foreign" >/dev/null 2>&1 || rc=$?
ok   "teardown: refuses dir without sentinel (exit!=0)" "$([[ $rc -ne 0 ]] && echo y)" "y"
ok   "teardown: foreign data UNTOUCHED"        "$([[ -f "$FOREIGN/keep/data" ]] && echo y)" "y"
rm -rf -- "$FOREIGN"

# ── 4. teardown HAPPY branch: valid iso dir IS removed ───────────────────────
OUTT=$(bash "$RP" teardown "$SLUG" 2>/dev/null)
ok   "teardown: removed=true"                  "$(printf '%s' "$OUTT" | grep -c '"removed":true')" "1"
ok   "teardown: iso dir gone"                  "$([[ ! -e "$ISO_ROOT/$SLUG" ]] && echo y)" "y"
OUTT2=$(bash "$RP" teardown "$SLUG" 2>/dev/null)
ok   "teardown: absent is a clean no-op"       "$(printf '%s' "$OUTT2" | grep -c '"removed":false')" "1"

# ── 5. validation: traversal / empty slug rejected ───────────────────────────
rc=0; bash "$RP" teardown "../etc" >/dev/null 2>&1 || rc=$?
ok   "validate: rejects traversal slug"        "$([[ $rc -ne 0 ]] && echo y)" "y"
rc=0; bash "$RP" setup "" >/dev/null 2>&1 || rc=$?
ok   "validate: rejects empty slug"            "$([[ $rc -ne 0 ]] && echo y)" "y"

# ── 6. $-laden testcmd is SAFE: ship-init now single-quotes the bake (shq), so setup succeeds AND the
#       baked wrapper stays runnable (the old double-quoted bake crashed every subcommand under set -u) ──
DSLUG="${SLUG}-dollar"
cat > "$PRIMARY/docs/plans/2026-06-30-${DSLUG}.jsonl" <<EOF
{"type":"meta","schema":"session-state/v1","slug":"${DSLUG}","land_mode":"merge-to-main","base_branch":"main"}
{"type":"task","id":"t1","wave":1,"desc":"x","status":"PENDING","deps":[]}
EOF
rc=0; RUN_PLAN_PROJECTS="$PROJECTS" bash "$RP" setup "$DSLUG" --testcmd 'echo $t' >/dev/null 2>&1 || rc=$?
ok   "shq: \$-laden testcmd setup succeeds (exit 0)" "$rc" "0"
DCLONE="$ISO_ROOT/$DSLUG/repo"
ok   "shq: \$-laden testcmd baked single-quoted"  "$(grep -c "^TESTCMD='echo \$t'\$" "$DCLONE/.claude/scripts/ship.sh")" "1"
( cd "$DCLONE" && bash "$DCLONE/.claude/scripts/ship.sh" drift >/dev/null 2>&1 ); ddr=$?
ok   "shq: baked ship.sh 'drift' runs with \$-laden TESTCMD (no set-u crash)" "$([[ $ddr -eq 0 ]] && echo y)" "y"

echo "── $pass passed, $fail failed ──"
[[ $fail -eq 0 ]]
