#!/usr/bin/env bash
set -euo pipefail

root="$(cd "$(dirname "$0")" && pwd)"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT

cp -r "$root" "$tmp/wrappers"
rm -f "$tmp/wrappers/lib/remote-seat.sh"

mkdir -p "$tmp/bin" "$tmp/home" "$tmp/ws"
mkdir -p "$tmp/home/.claude/bin"

cat >"$tmp/bin/claude" <<'STUB'
#!/usr/bin/env bash
if [[ "${1:-}" == "auth" && "${2:-}" == "status" && "${3:-}" == "--json" ]]; then
  case "${CLAUDE_TEST_MODE:-success}" in
    health-fail) exit 1;;
    *) printf '%s\n' '{"status":"ok"}'; exit 0;;
  esac
fi

case "${CLAUDE_TEST_MODE:-success}" in
  success)
    printf '%s\n' '{"is_error":false,"session_id":"session-success","result":"ok"}'
    exit 0
    ;;
  rate-with-resume)
    printf '%s\n' '{"is_error":true,"result":"Claude usage limit reached. Your limit will reset at 2026-08-09T12:00:00Z.","session_id":"session-rate"}'
    exit 1
    ;;
  engine-error)
    printf '%s\n' '{"is_error":true,"result":"model refused the task","session_id":"session-engine-error"}'
    exit 7
    ;;
  rate-no-resume)
    printf '%s\n' '{"is_error":true,"result":"usage limit reached"}'
    exit 1
    ;;
  whitespace)
    printf '%s\n' '   '
    exit 0
    ;;
  is-error)
    printf '%s\n' '{"is_error":true,"result":"agent failure","session_id":"session-is-error"}'
    exit 0
    ;;
  bad-json)
    printf '%s\n' 'not-json'
    exit 42
    ;;
  timeout)
    sleep 5
    printf '%s\n' '{"is_error":false,"session_id":"session-timeout","result":"late"}'
    exit 0
    ;;
  *)
    printf '%s\n' '{"is_error":false,"session_id":"session-default","result":"ok"}'
    exit 0
    ;;
esac
STUB
chmod +x "$tmp/bin/claude"
cat >"$tmp/home/.claude/bin/local-dispatch-guard" <<'GUARD'
#!/usr/bin/env bash
exit 0
GUARD
chmod +x "$tmp/home/.claude/bin/local-dispatch-guard"

DISPATCH_ARGS=(
  --workspace "$tmp/ws"
  --trust 'seat fixture'
  --task-slug claudetest
  --model claude-3-5-sonnet
  --timeout 120
)

TIMEOUT_ARGS=(
  --workspace "$tmp/ws"
  --trust 'seat fixture'
  --task-slug claudetest
  --model claude-3-5-sonnet
  --timeout 1
)

PASS=0
FAIL=0
ok() { PASS=$((PASS+1)); echo "PASS $1"; }
bad() { FAIL=$((FAIL+1)); echo "FAIL $1" >&2; }
check() { [[ "$2" == "$3" ]] && ok "$1" || bad "$1: expected $3, got $2"; }

run_case() {
  local mode="$1"
  local engine_bin="$2"
  shift 2

  rm -rf "$tmp/home/Projects"

  local rc=0
  local stdout_file="$tmp/stdout.$RANDOM"
  local stderr_file="$tmp/stderr.$RANDOM"
  if env -i \
    HOME="$tmp/home" \
    PATH="$tmp/bin:/usr/bin:/bin" \
    CLAUDE_TEST_MODE="$mode" \
    _CLAUDE_ENGINE_BIN="$engine_bin" \
    bash "$tmp/wrappers/claude.sh" "$@" >"$stdout_file" 2>"$stderr_file"; then
    rc=0
  else
    rc=$?
  fi

  printf '%s\n%s\n%s\n' "$rc" "$stdout_file" "$stderr_file"
}

capture_case() {
  local mode="$1"
  local engine_bin="$2"
  shift 2

  mapfile -t CAPTURE < <(run_case "$mode" "$engine_bin" "$@")
  CAPTURE_RC="${CAPTURE[0]}"
  CAPTURE_STDOUT="${CAPTURE[1]}"
  CAPTURE_STDERR="${CAPTURE[2]}"
}

expect_lines() {
  local expected="$1"
  local file="$2"
  [[ -f "$file" ]] || return 1
  [[ "$(wc -l < "$file")" -eq "$expected" ]] || return 1
}

expect_contains() {
  local needle="$1"
  local file="$2"
  grep -Fq "$needle" "$file"
}

expect_not_contains() {
  local needle="$1"
  local file="$2"
  ! grep -Fq "$needle" "$file"
}

capture_case success "$tmp/bin/claude" "${DISPATCH_ARGS[@]}"
check "success dispatch rc" "$CAPTURE_RC" 0
expect_lines 1 "$CAPTURE_STDOUT" && ok "success prints exactly one status line" || bad "success prints exactly one status line"
expect_contains '"ok":true' "$CAPTURE_STDOUT" && ok "success status has ok true" || bad "success status has ok true"
expect_contains '"session_id":"session-success"' "$CAPTURE_STDOUT" && ok "success returns session_id" || bad "success returns session_id"

capture_case rate-with-resume "$tmp/bin/claude" "${DISPATCH_ARGS[@]}"
check "rate limit with resume rc" "$CAPTURE_RC" 75
expect_contains '"detail":"rate-limited"' "$CAPTURE_STDOUT" && ok "rate limit with resume detail" || bad "rate limit with resume detail"
expect_contains '"resume_at":"2026-08-09T12:00:00Z"' "$CAPTURE_STDOUT" && ok "rate limit with resume_at" || bad "rate limit with resume_at"

capture_case rate-no-resume "$tmp/bin/claude" "${DISPATCH_ARGS[@]}"
check "rate limit without resume rc" "$CAPTURE_RC" 75
expect_contains '"detail":"rate-limited"' "$CAPTURE_STDOUT" && ok "rate limit without resume detail" || bad "rate limit without resume detail"
expect_not_contains '"resume_at"' "$CAPTURE_STDOUT" && ok "rate limit without resume no resume_at" || bad "rate limit without resume no resume_at"

capture_case whitespace "$tmp/bin/claude" "${DISPATCH_ARGS[@]}"
check "whitespace output rc" "$CAPTURE_RC" 3

capture_case is-error "$tmp/bin/claude" "${DISPATCH_ARGS[@]}"
check "is_error true rc0 maps to 124" "$CAPTURE_RC" 124

capture_case bad-json "$tmp/bin/claude" "${DISPATCH_ARGS[@]}"
check "non-contract non-json rc" "$CAPTURE_RC" 42

capture_case engine-error "$tmp/bin/claude" "${DISPATCH_ARGS[@]}"
check "parseable engine error passes its own rc through" "$CAPTURE_RC" 7
expect_contains '"session_id":"session-engine-error"' "$CAPTURE_STDOUT" && ok "engine error keeps session_id" || bad "engine error keeps session_id"

capture_case timeout "$tmp/bin/claude" "${TIMEOUT_ARGS[@]}"
check "timeout dispatch rc" "$CAPTURE_RC" 124

capture_case success "$tmp/bin/claude" --health
check "health rc" "$CAPTURE_RC" 0

capture_case health-fail "$tmp/bin/claude" --health
check "health failure rc" "$CAPTURE_RC" 3
[[ ! -s "$CAPTURE_STDOUT" ]] && ok "health failure has no stdout" || bad "health failure has no stdout"

capture_case success "$tmp/bin/claude" --list-models
check "list-models rc" "$CAPTURE_RC" 2
[[ ! -s "$CAPTURE_STDOUT" ]] && ok "list-models has no stdout" || bad "list-models has no stdout"

capture_case success "$tmp/bin/claude" \
  --workspace "$tmp/ws" \
  --trust 'seat fixture' \
  --task-slug missing-model
check "missing --model rc" "$CAPTURE_RC" 2

touch "$tmp/not-a-dir"
capture_case success "$tmp/bin/claude" \
  --workspace "$tmp/not-a-dir" \
  --trust 'seat fixture' \
  --task-slug bad-workspace \
  --model claude-3-5-sonnet
check "non-dir workspace rc" "$CAPTURE_RC" 2

capture_case success "$tmp/no-such-claude" "${DISPATCH_ARGS[@]}"
check "missing engine binary rc" "$CAPTURE_RC" 3

echo "---- claude-classification: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]
