#!/usr/bin/env bash
# Tests resolve.sh in a sandboxed HOME so it touches no real session state.
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
RESOLVE="${HERE}/resolve.sh"
pass=0; fail=0
ok()   { pass=$((pass+1)); echo "ok   - $*"; }
bad()  { fail=$((fail+1)); echo "FAIL - $*"; }

SANDBOX="$(mktemp -d)"
trap 'rm -rf "$SANDBOX"' EXIT
# emulate cwd /work/app -> slug -work-app
WORK="${SANDBOX}/work/app"; mkdir -p "$WORK"
# slug must match resolve.sh's rule applied to the REAL absolute $WORK path.
SLUG="$(printf '%s' "$WORK" | tr '/.' '--')"
PROJ="${SANDBOX}/.claude/projects/${SLUG}"; mkdir -p "$PROJ"

run() { ( cd "$WORK" && HOME="$SANDBOX" bash "$RESOLVE" "$@" ); }

# fixtures: two top-level transcripts + a nested subagent one that must be ignored
printf '{"x":"hello UNIQUEMARK world"}\n' > "${PROJ}/sess-A.jsonl"
printf '{"x":"unrelated content"}\n'      > "${PROJ}/sess-B.jsonl"
mkdir -p "${PROJ}/subdir"
printf '{"x":"UNIQUEMARK in subagent"}\n' > "${PROJ}/subdir/nested.jsonl"

# 1. unique marker -> exactly sess-A, nested ignored
out=$(run lookup "UNIQUEMARK") || true
echo "$out" | grep -q "SESSION=sess-A" && ok "unique marker resolves top-level session" || bad "unique marker: got [$out]"
echo "$out" | grep -q "AGENT=''$" && ok "no agent stored yet -> empty AGENT" || bad "expected empty AGENT: [$out]"
echo "$out" | grep -q "LASTREAD=0" && ok "no cursor yet -> LASTREAD=0" || bad "expected LASTREAD=0: [$out]"
echo "$out" | grep -q "NOW=1" && ok "NOW = transcript line count" || bad "expected NOW=1: [$out]"

# 2. zero matches -> exit 3
set +e; run lookup "NOPE_NOT_PRESENT" >/dev/null 2>&1; rc=$?; set -e
[ "$rc" -eq 3 ] && ok "zero matches -> exit 3" || bad "zero matches rc=$rc (want 3)"

# 3. two transcripts in one project carrying the same MARKER: two conversations that
# nothing here distinguishes. A newest-mtime pick would advise on the wrong one.
printf '{"x":"SHARED early turn"}\n' > "${PROJ}/sess-A.jsonl"
printf '{"x":"SHARED early turn"}\n' > "${PROJ}/sess-B.jsonl"
touch -d '2020-01-01' "${PROJ}/sess-A.jsonl"
touch -d '2020-06-01' "${PROJ}/sess-B.jsonl"   # B newer, and must NOT be chosen for it
set +e; out=$(run lookup "SHARED" 2>&1); rc=$?; set -e
[ "$rc" -ne 0 ] && ok "same-project ambiguity fails closed" || bad "ambiguity rc=$rc: [$out]"
echo "$out" | grep -q "SESSION=" && bad "resolved a session despite ambiguity: [$out]" \
  || ok "no session is emitted on a refusal"
echo "$out" | grep -q "sess-A" && echo "$out" | grep -q "sess-B" \
  && ok "the refusal names both candidates" || bad "candidates not named: [$out]"

# from here the MARKER is unique to sess-B, as the skill instructs
printf '{"x":"A private turn"}\n' > "${PROJ}/sess-A.jsonl"

# 4. save then lookup -> AGENT populated
run save "sess-B" "a-test-id-123" >/dev/null
out=$(run lookup "SHARED") || true
echo "$out" | grep -q "AGENT=a-test-id-123" && ok "save persists agentId, lookup returns it" || bad "save/lookup: [$out]"

# 4b. read cursor: mark then lookup reflects offset; grow file -> delta visible
run mark "sess-B" "1" >/dev/null
printf '{"x":"SHARED new turn"}\n' >> "${PROJECT_B:=${PROJ}/sess-B.jsonl}"  # B now 2 lines
out=$(run lookup "SHARED") || true
echo "$out" | grep -q "LASTREAD=1" && ok "mark sets read cursor" || bad "mark cursor: [$out]"
echo "$out" | grep -q "NOW=2" && ok "NOW tracks grown transcript (delta = lines 2..2)" || bad "NOW after growth: [$out]"

# 4c. mark non-numeric -> fail
set +e; run mark "sess-B" "abc" >/dev/null 2>&1; rc=$?; set -e
[ "$rc" -ne 0 ] && ok "mark non-numeric -> nonzero" || bad "mark non-numeric should fail"

# 4d. agent subcommand: reads stored id, empty when none
[ "$(run agent sess-B)" = "a-test-id-123" ] && ok "agent subcommand returns stored id" || bad "agent read: [$(run agent sess-B)]"
[ -z "$(run agent sess-NOPE)" ] && ok "agent subcommand empty when no record" || bad "agent empty: [$(run agent sess-NOPE)]"

# 4e. a session that moved into a worktree: its cwd slug has no project dir at all,
# and the marker must still find it.
ELSEWHERE="${SANDBOX}/work/app/.worktrees/wt"; mkdir -p "$ELSEWHERE"
[ ! -d "${SANDBOX}/.claude/projects/$(printf '%s' "$ELSEWHERE" | tr '/.' '--')" ] \
  && ok "worktree cwd has no project dir of its own" || bad "fixture: worktree slug dir exists"
out=$( cd "$ELSEWHERE" && HOME="$SANDBOX" bash "$RESOLVE" lookup "SHARED" ) || true
echo "$out" | grep -q "SESSION=sess-B" && ok "lookup from a worktree still resolves the session" || bad "worktree lookup: [$out]"
out=$( cd "$ELSEWHERE" && HOME="$SANDBOX" bash "$RESOLVE" lookup "UNIQUEMARK" 2>&1 ) || true
echo "$out" | grep -q "SESSION=" && bad "worktree lookup matched a nested subagent transcript: [$out]" \
  || ok "nested subagent transcripts stay excluded from the fallback scan"

# 4f. the same MARKER in two different projects: refused from the fallback scan too.
OTHER="${SANDBOX}/.claude/projects/-other-project"; mkdir -p "$OTHER"
printf '{"x":"SHARED early turn"}\n' > "${OTHER}/sess-C.jsonl"
set +e
out=$( cd "$ELSEWHERE" && HOME="$SANDBOX" bash "$RESOLVE" lookup "SHARED" 2>&1 ); rc=$?
set -e
[ "$rc" -ne 0 ] && ok "cross-project ambiguity fails closed" || bad "ambiguous fallback rc=$rc: [$out]"
echo "$out" | grep -q "sess-C" && echo "$out" | grep -q "sess-B" \
  && ok "the refusal names the candidate sessions" || bad "candidates not listed: [$out]"
rm -rf "$OTHER"

# 4g. a project path with spaces and shell metacharacters survives resolution and eval.
NASTY="${SANDBOX}/.claude/projects/-home-My Repo (v2)-\$x"; mkdir -p "$NASTY"
printf '{"x":"NASTYMARK here"}\n' > "${NASTY}/sess-D.jsonl"
out=$( cd "$ELSEWHERE" && HOME="$SANDBOX" bash "$RESOLVE" lookup "NASTYMARK" ) || true
( eval "$out"; [ -f "$TRANSCRIPT" ] && [ "$SESSION" = "sess-D" ] ) \
  && ok "a metacharacter-laden path round-trips through eval" || bad "nasty path: [$out]"
rm -rf "$NASTY"

# 5. save needs both args -> fail
set +e; run save "only-session" >/dev/null 2>&1; rc=$?; set -e
[ "$rc" -ne 0 ] && ok "save missing id -> nonzero" || bad "save missing id should fail"

# 6. lookup with no marker -> fail
set +e; run lookup >/dev/null 2>&1; rc=$?; set -e
[ "$rc" -ne 0 ] && ok "lookup with no marker -> nonzero" || bad "lookup no marker should fail"

echo "----"; echo "pass=$pass fail=$fail"
[ "$fail" -eq 0 ]
