#!/usr/bin/env bash

# A key from the user's own fnox config (fnox's global config, or a file in or above $HOME)
# reaches a project's task only when the user names it on the command line.

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"
export FNOX_STUB_SOURCES=1

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

[tasks.listed]
secrets = ["PERSONAL_TOKEN"]
run = 'printf %s "${PERSONAL_TOKEN-unset}" >listed.out'

[tasks.home]
secrets = ["HOME_TOKEN"]
run = 'printf %s "${HOME_TOKEN-unset}" >home.out'

[tasks.composed]
env.AUTH = "Bearer {{ secrets.PERSONAL_TOKEN }}"
run = 'printf %s "${AUTH-unset}" >composed.out'

[tasks.show]
run = '''
printf %s "${PERSONAL_TOKEN-unset}" >show-personal.out
printf %s "${STRIPE_KEY-unset}" >show-stripe.out
'''
TOML

resolves() {
  if [[ -f fnox-calls.jsonl ]]; then
    jq -s '[.[]|select((.argv|index("--for")) and ((.argv|index("--describe"))|not))]|length' fnox-calls.jsonl
  else
    echo 0
  fi
}
fresh() {
  rm -f fnox-calls.jsonl ./*.out
}

# a task's own list cannot grant a key from the global config, and nothing is resolved
fresh
assert_fail_contains "mise run listed </dev/null" "PERSONAL_TOKEN comes from your own fnox config, so the project cannot grant it"
assert_fail_contains "mise run listed </dev/null" ".config/fnox/config.toml supplies all or part of PERSONAL_TOKEN"
assert_fail_contains "mise run listed </dev/null" "mise run --secrets PERSONAL_TOKEN listed"
[[ ! -e listed.out ]] || fail "listed ran without its grant"
[[ "$(resolves)" == 0 ]] || fail "a refused grant must not resolve anything"

# nor a key from a fnox.toml in the home directory
fresh
assert_fail_contains "mise run home </dev/null" "HOME_TOKEN comes from your own fnox config"

# nor a reference in the task's env
fresh
assert_fail_contains "mise run composed </dev/null" "PERSONAL_TOKEN comes from your own fnox config"
[[ ! -e composed.out ]] || fail "composed ran without its grant"

# the user naming the key grants it
fresh
mise run --secrets PERSONAL_TOKEN listed </dev/null >/dev/null 2>&1
assert "cat listed.out" "personal-s3cr3t-0011"
fresh
mise run --secrets PERSONAL_TOKEN show </dev/null >/dev/null 2>&1
assert "cat show-personal.out" "personal-s3cr3t-0011"
assert "mise x --secrets PERSONAL_TOKEN -- sh -c 'echo \$PERSONAL_TOKEN'" "personal-s3cr3t-0011"

# --secrets-all gives the project's keys and leaves the user's own out
fresh
mise run --secrets-all show </dev/null >/dev/null 2>&1
assert "cat show-stripe.out" "stripe-s3cr3t-0003"
assert "cat show-personal.out" "unset"
assert "mise x --secrets-all -- sh -c 'echo \${PERSONAL_TOKEN:-unset} \${HOME_TOKEN:-unset} \${STRIPE_KEY:-unset}'" "unset unset stripe-s3cr3t-0003"

# --secrets-all asks only for the project's keys, so a signed-out provider behind the user's
# own key cannot fail the run
fresh
FNOX_STUB_FAIL=PERSONAL_TOKEN mise run --secrets-all show </dev/null >/dev/null 2>&1
assert "cat show-stripe.out" "stripe-s3cr3t-0003"
assert_not_contains "cat fnox-calls.jsonl" "PERSONAL_TOKEN"

# mise secrets ls reports the refused grants
assert_contains "mise secrets ls 2>&1 >/dev/null" "task listed: PERSONAL_TOKEN comes from your own fnox config"
assert "mise secrets ls --json | jq -r '.problems[] | select(.key == \"HOME_TOKEN\") | .kind'" "personal"
