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

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BIN="$ROOT_DIR/bin/harness-adapter"

PASS=0
FAIL=0

ok() {
  PASS=$((PASS + 1))
  printf 'ok %s\n' "$1"
}

bad() {
  FAIL=$((FAIL + 1))
  printf 'not ok %s -- %s\n' "$1" "$2"
}

run() {
  bash "$BIN" "$@"
}

json_eq_text() {
  local json=$1
  local filter=$2
  local expected=$3
  local actual
  actual=$(jq -Sc "$filter" <<<"$json")
  [[ "$actual" == "$(jq -Sc . <<<"$expected")" ]]
}

echo "adapter-read fixtures:"

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

root="$tmpdir/root"
machine="machine-a"
catalog_dir="$root/catalog/adapters"
wrapper_dir="$tmpdir/wrappers"
state_file="$root/$machine/adapters-state.json"
secret_file="$root/$machine/secrets/codex/api_key"
count_file="$tmpdir/wrapper-count.txt"
models_file="$tmpdir/wrapper-models.json"
wrapper="$wrapper_dir/models-wrapper.sh"

mkdir -p "$catalog_dir" "$wrapper_dir"
printf '0\n' > "$count_file"
printf '["gpt-5","gpt-5-mini"]\n' > "$models_file"

cat > "$wrapper" <<EOF
#!/usr/bin/env bash
set -euo pipefail
count_file=$(printf '%q' "$count_file")
models_file=$(printf '%q' "$models_file")
count=\$(cat "\$count_file")
printf '%s\n' "\$((count + 1))" > "\$count_file"
cat "\$models_file"
EOF
chmod +x "$wrapper"

cat > "$catalog_dir/codex.json" <<EOF
{
  "id": "codex",
  "label": "Codex",
  "wrapper": $(jq -Rn --arg v "$wrapper" '$v'),
  "config": {
    "mode": "balanced",
    "nested": {
      "retry": 1,
      "keep": true
    }
  },
  "models": ["fallback-model"],
  "secrets": ["api_key", "session_token"],
  "availableModelsCommand": [$(jq -Rn --arg v "$wrapper" '$v'), "--catalog-models"]
}
EOF

cat > "$catalog_dir/north.json" <<'EOF'
{
  "id": "north",
  "label": "North",
  "config": {
    "mode": "fast"
  },
  "models": ["north-mini"]
}
EOF

if run enable --root "$root" --machine "$machine" --adapter codex \
  && run config --root "$root" --machine "$machine" --adapter codex --json '{"nested":{"timeout":30},"extra":true}' \
  && run set-models --root "$root" --machine "$machine" --adapter codex gpt-5-high; then
  ok "state fixture setup"
else
  bad "state fixture setup" "fixture command failed"
fi

show_json=$(run show --root "$root" --machine "$machine" --adapter codex 2>/dev/null) || show_rc=$?
show_rc=${show_rc:-0}
if [[ $show_rc -ne 0 ]]; then
  bad "show returns effective descriptor" "exit=$show_rc"
else
  if json_eq_text "$show_json" '.id' '"codex"' \
    && json_eq_text "$show_json" '.enabled' 'true' \
    && json_eq_text "$show_json" '.wrapper' "$(jq -cn --arg v "$wrapper" '$v')" \
    && json_eq_text "$show_json" '.config' '{"mode":"balanced","nested":{"retry":1,"keep":true,"timeout":30},"extra":true}' \
    && json_eq_text "$show_json" '.models' '["gpt-5-high"]' \
    && json_eq_text "$show_json" '.requiredSecrets' '["api_key","session_token"]' \
    && json_eq_text "$show_json" '.configuredSecrets' '[]'; then
    ok "show returns effective descriptor"
  else
    bad "show returns effective descriptor" "unexpected merged descriptor"
  fi
fi

list_json=$(run list --root "$root" --machine "$machine" --adapter ignored 2>/dev/null) || list_rc=$?
list_rc=${list_rc:-0}
if [[ $list_rc -ne 0 ]]; then
  bad "list returns catalog descriptors" "exit=$list_rc"
else
  if json_eq_text "$list_json" 'map(.id)' '["codex","north"]' \
    && json_eq_text "$list_json" 'map(select(.id == "codex"))[0].enabled' 'true' \
    && json_eq_text "$list_json" 'map(select(.id == "north"))[0].models' '["north-mini"]'; then
    ok "list returns catalog descriptors"
  else
    bad "list returns catalog descriptors" "unexpected list output"
  fi
fi

if printf 'super-secret-token' | run set-secret --root "$root" --machine "$machine" --adapter codex --secret api_key; then
  if [[ -f "$secret_file" ]] \
    && [[ "$(cat "$secret_file")" == "super-secret-token" ]] \
    && [[ "$(stat -c '%a' "$secret_file")" == "600" ]]; then
    secret_show=$(run show --root "$root" --machine "$machine" --adapter codex)
    if [[ "$secret_show" != *"super-secret-token"* ]] \
      && json_eq_text "$secret_show" '.configuredSecrets' '["api_key"]'; then
      ok "set-secret writes 0600 file and keeps value out of descriptors"
    else
      bad "set-secret writes 0600 file and keeps value out of descriptors" "secret leaked into descriptor"
    fi
  else
    bad "set-secret writes 0600 file and keeps value out of descriptors" "secret file mismatch"
  fi
else
  bad "set-secret writes 0600 file and keeps value out of descriptors" "command failed"
fi

models_json=$(run available-models --root "$root" --machine "$machine" --adapter codex 2>/dev/null) || models_rc=$?
models_rc=${models_rc:-0}
if [[ $models_rc -ne 0 ]]; then
  bad "available-models populates cache from wrapper" "exit=$models_rc"
else
  if json_eq_text "$models_json" '.' '["gpt-5","gpt-5-mini"]' \
    && [[ "$(cat "$count_file")" == "1" ]]; then
    ok "available-models populates cache from wrapper"
  else
    bad "available-models populates cache from wrapper" "unexpected wrapper output or count"
  fi
fi

printf '["gpt-6"]\n' > "$models_file"
cached_json=$(run available-models --root "$root" --machine "$machine" --adapter codex 2>/dev/null) || cached_rc=$?
cached_rc=${cached_rc:-0}
if [[ $cached_rc -ne 0 ]]; then
  bad "available-models reuses fresh cache" "exit=$cached_rc"
else
  if json_eq_text "$cached_json" '.' '["gpt-5","gpt-5-mini"]' \
    && [[ "$(cat "$count_file")" == "1" ]]; then
    ok "available-models reuses fresh cache"
  else
    bad "available-models reuses fresh cache" "cache miss"
  fi
fi

cache_file="$root/$machine/cache/available-models/codex.json"
touch -d '2 days ago' "$cache_file"
refreshed_json=$(run available-models --root "$root" --machine "$machine" --adapter codex 2>/dev/null) || refreshed_rc=$?
refreshed_rc=${refreshed_rc:-0}
if [[ $refreshed_rc -ne 0 ]]; then
  bad "available-models refreshes stale cache" "exit=$refreshed_rc"
else
  if json_eq_text "$refreshed_json" '.' '["gpt-6"]' \
    && [[ "$(cat "$count_file")" == "2" ]]; then
    ok "available-models refreshes stale cache"
  else
    bad "available-models refreshes stale cache" "stale cache not refreshed"
  fi
fi

printf 'not-json\n' > "$state_file"
if run show --root "$root" --machine "$machine" --adapter codex >/dev/null 2>&1; then
  bad "show fails closed on invalid state" "expected failure"
else
  rc=$?
  if [[ $rc -eq 2 ]]; then
    ok "show fails closed on invalid state"
  else
    bad "show fails closed on invalid state" "exit=$rc"
  fi
fi

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