#!/usr/bin/env bash

# `mise secrets ls` lists the keys of the project's fnox source without ever reading values.

mkdir -p "$HOME/bin"
printf '#!/usr/bin/env bash\nexec python3 "%s" "$@"\n' "$TEST_ROOT/helpers/scripts/fnox_stub.py" >"$HOME/bin/fnox"
chmod +x "$HOME/bin/fnox"
export PATH="$HOME/bin:$PATH"
export FNOX_STUB_LOG="$PWD/fnox-calls.jsonl"

cat >mise.toml <<'TOML'
[secrets.fnox]
TOML

# basic listing
assert_contains "mise secrets ls" "DEPLOY_KEY"
assert_contains "mise secrets ls" "GCP_SA_JSON"
assert_contains "mise secrets ls" "yes"
assert_contains "mise secrets ls" "(lease aws)"
assert_contains "mise secrets ls" "exec"
assert_not_contains "mise secrets ls 2>&1" "s3cr3t"
assert "jq -e -s 'all(.[]; (.argv|index(\"--describe\")) and (.argv|index(\"--non-interactive\")) and (.argv|index(\"--no-daemon\")) and ((.argv|index(\"--keys\"))|not))' fnox-calls.jsonl"
assert "mise secrets ls -J | jq -e '.keys[] | select(.key==\"SIGNING_KEY\") | .env == false'"
assert "mise secrets ls -J | jq -e '.keys[] | select(.key==\"AWS_ACCESS_KEY_ID\") | .env == null and .lease == \"aws\"'"
assert_not_contains "mise secrets ls -J" "s3cr3t"
assert_contains "mise secrets ls -J | jq -r .source.profile" "default"

# profile and location
project="$(pwd -P)"
cat >mise.toml <<'TOML'
[secrets.fnox]
profile = "prod"
TOML
rm -f fnox-calls.jsonl
mkdir sub
(cd sub && mise secrets ls >/dev/null)
assert "jq -e -s --arg root \"$project\" 'all(.[]; (.cwd == \$root) and ((.argv|index(\"-P\")) < (.argv|index(\"env\"))) and (.argv[((.argv|index(\"-P\")) + 1)] == \"prod\"))' fnox-calls.jsonl"

# no source, and files that are ignored
rm mise.toml
assert_contains "mise secrets ls 2>&1" "no secrets source is configured"
assert "mise secrets ls"
mkdir -p "$MISE_CONFIG_DIR"
printf '[secrets.fnox]\n' >"$MISE_CONFIG_DIR/config.toml"
assert_contains "mise secrets ls 2>&1" "is ignored"
assert "mise secrets ls -J | jq -e '.source == null and (.ignored | length) == 1'"
rm "$MISE_CONFIG_DIR/config.toml"

# refusals
printf '[secrets.fnox]\n' >mise.toml
assert_fail "MISE_SAFE=1 mise secrets ls"
assert_fail_contains "MISE_EXPERIMENTAL=0 mise secrets ls" "experimental"
printf '[secrets.fnox]\nexec = ["A"]\n' >mise.toml
assert_fail_contains "mise secrets ls" "unknown field"
printf '[secrets.fnox]\n' >mise.toml

# S2: fnox missing
minimal_path="$(dirname "$(command -v mise)"):/usr/bin:/bin"
if ! PATH="$minimal_path" command -v fnox >/dev/null; then
  assert_fail_contains "PATH='$minimal_path' mise secrets ls" "fnox not found"
fi

# a standalone fnox exposed only through [env] _.path is found from an unactivated shell
mkdir -p "$PWD/extra-bin"
mv "$HOME/bin/fnox" "$PWD/extra-bin/fnox"
printf '[env]\n_.path = ["{{config_root}}/extra-bin"]\n\n[secrets.fnox]\n' >mise.toml
assert_contains "PATH='$minimal_path' mise secrets ls" "DEPLOY_KEY"
assert_contains "PATH='$minimal_path' mise secrets ls -J | jq -r .source.tool.path" "extra-bin/fnox"
printf '[secrets.fnox]\n' >mise.toml
mv "$PWD/extra-bin/fnox" "$HOME/bin/fnox"

# bad fnox output
rm -f fnox-calls.jsonl
esc="$(printf '\033')"
assert_not_contains "FNOX_STUB_MODE=ansi mise secrets ls 2>&1" "$esc"
assert_contains "FNOX_STUB_MODE=ansi mise secrets ls 2>&1" "pwned"
assert_fail_contains "FNOX_STUB_LEGACY=1 mise secrets ls" "no JSON result"
assert_fail_contains "FNOX_STUB_SCHEMA=2 mise secrets ls" "schema 2"
assert_fail_contains "FNOX_STUB_MODE=garbage mise secrets ls" "could not parse"
assert_not_contains "FNOX_STUB_MODE=garbage mise secrets ls 2>&1 || true" "s3cr3t"

# parent flags apply to the subcommand too
assert "mise secrets -J ls | jq -e '.keys | length > 0'"
assert_not_contains "mise secrets --no-header ls" "DESCRIPTION"

# a conf.d fragment at the home level applies to every project, so it is ignored
rm mise.toml
mkdir -p "$HOME/.mise/conf.d/team"
printf '[secrets.fnox]\nprofile = "home"\n' >"$HOME/.mise/conf.d/team/mise.toml"
assert_contains "mise secrets ls 2>&1" "no secrets source is configured"
assert_contains "mise secrets ls 2>&1" "is ignored"
rm -r "$HOME/.mise/conf.d"

# doctor reports the deprecated plugin in both outputs
printf '[plugins]\nmise-env-fnox = "https://github.com/jdx/mise-env-fnox"\n' >mise.toml
assert_contains "mise doctor 2>&1 || true" "mise-env-fnox plugin is deprecated"
assert_contains "mise doctor -J 2>&1 || true" "mise-env-fnox plugin is deprecated"

# tasks that list keys
cat >mise.toml <<'TOML'
[secrets.fnox]

[tasks.deploy]
secrets = ["DEPLOY_KEY", "DEPLOY_KYE"]
run = "true"
TOML
assert_contains "mise secrets ls" "deploy"
assert_contains "mise secrets ls 2>&1" "unknown secret DEPLOY_KYE"
assert "mise secrets ls -J | jq -e '.keys[] | select(.key==\"DEPLOY_KEY\") | .scopes==[\"run\",\"exec\"] and .tasks[0].task==\"deploy\" and .tasks[0].via==\"list\"'"
assert "mise secrets ls -J | jq -e '.keys[] | select(.key==\"SIGNING_KEY\") | .scopes==[] and .tasks==[]'"
assert "mise secrets ls -J | jq -e '.problems[0].key==\"DEPLOY_KYE\" and .problems[0].suggestion==\"DEPLOY_KEY\"'"

# tasks validate flags grants that every mise run would refuse
cat >mise.toml <<'TOML'
[secrets.fnox]

[env]
DEPLOY_KEY = "x"

[tasks.deploy]
secrets = ["DEPLOY_KEY"]
run = "true"

[tasks.sandboxed]
secrets = ["DEPLOY_KEY"]
deny_env = true
run = "true"
TOML
output=$(mise tasks validate 2>&1 || true)
grep -q "DEPLOY_KEY is both a secret and a mise env var" <<<"$output" || fail "validate missed G11: $output"
grep -q "sandbox denies env vars" <<<"$output" || fail "validate missed G13: $output"
