#!/usr/bin/env bash

# A monorepo task's secrets source runs with its own subproject's [env], never the task's env.

export MISE_EXPERIMENTAL=1
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'
monorepo_root = true

[monorepo]
config_roots = ["projects/*"]

[env]
ROOT_ONLY = "1"
TOML
mkdir -p projects/api
cat >projects/api/mise.toml <<'TOML'
[secrets.fnox]

[env]
SUB_ENV_VAR = "staging"
_.path = ["tools-bin"]

[tasks.deploy]
secrets = ["DEPLOY_KEY"]
env = { TASK_ONLY = "1" }
run = 'printf %s "$DEPLOY_KEY" >deploy.out'
TOML

mise run //projects/api:deploy </dev/null >/dev/null 2>&1 || fail "the monorepo task did not run"
assert "jq -e 'select(.argv|index(\"--keys\"))|(.env_keys|index(\"SUB_ENV_VAR\")) != null and (.env_keys|index(\"TASK_ONLY\")) == null' fnox-calls.jsonl"
assert "jq -e 'select(.argv|index(\"--describe\"))|(.env_keys|index(\"SUB_ENV_VAR\")) != null' fnox-calls.jsonl"
assert "cat projects/api/deploy.out" "deploy-s3cr3t-0001"
# the subproject's own _.path comes first on fnox's PATH, for both calls
sub="$(pwd -P)/projects/api/tools-bin"
assert "jq -e --arg p \"$sub\" 'select(.argv|index(\"--keys\"))|.path|startswith(\$p + \":\")' fnox-calls.jsonl"
assert "jq -e --arg p \"$sub\" 'select(.argv|index(\"--describe\"))|.path|startswith(\$p + \":\")' fnox-calls.jsonl"

# a default is judged against the subproject's own [env], not the root's
mkdir -p projects/web
cat >projects/web/mise.toml <<'TOML'
[secrets.fnox]

[env]
TOKEN = "from-sub"

[tasks.deploy]
secrets = ["DEPLOY_KEY"]
env = { TOKEN = { default = "{{ env.DEPLOY_KEY }}" } }
run = 'true'

[tasks.plain]
secrets = ["DEPLOY_KEY"]
env = { OTHER = { default = "{{ env.DEPLOY_KEY }}" } }
run = 'true'
TOML
# TOKEN is assigned by the subproject, so the default never renders; run from the root
assert_succeed "env -u TOKEN mise run //projects/web:deploy </dev/null"
# OTHER is not assigned anywhere, so its default renders and reads the granted key
assert_fail_contains "env -u OTHER mise run //projects/web:plain </dev/null" "cannot see the secret DEPLOY_KEY"

# the preflight never runs a subproject's `_.source` scripts: a task with no grant, and a task
# with one, cause the same number of runs of the script
mkdir -p projects/src
cat >projects/src/hook.sh <<'SH'
echo run >>"$MARKER_FILE"
SH
cat >projects/src/mise.toml <<'TOML'
[secrets.fnox]

[env]
_.source = "hook.sh"

[tasks.plain]
run = 'true'

[tasks.granted]
secrets = ["DEPLOY_KEY"]
run = 'true'
TOML
export MARKER_FILE="$PWD/marker.txt"
: >"$MARKER_FILE"
mise run -n //projects/src:plain </dev/null >/dev/null 2>&1
plain_runs=$(wc -l <"$MARKER_FILE")
: >"$MARKER_FILE"
mise run -n //projects/src:granted </dev/null >/dev/null 2>&1
granted_runs=$(wc -l <"$MARKER_FILE")
[[ $plain_runs -eq $granted_runs ]] || fail "the preflight ran the _.source script ($plain_runs vs $granted_runs runs)"
# and under a real run the granted task runs it exactly as often as a plain one: the task env
# and the fnox source env share one evaluation of the hierarchy's [env]
: >"$MARKER_FILE"
mise run //projects/src:plain </dev/null >/dev/null 2>&1
plain_runs=$(wc -l <"$MARKER_FILE")
: >"$MARKER_FILE"
mise run //projects/src:granted </dev/null >/dev/null 2>&1
granted_runs=$(wc -l <"$MARKER_FILE")
[[ $plain_runs -ge 1 ]] || fail "the plain task never ran the script"
[[ $granted_runs -eq $plain_runs ]] || fail "a granted task re-ran the _.source script ($plain_runs vs $granted_runs runs)"

# keys a `_.source` script sets are unknown to the static preflight, which then leaves defaults
# to the spawn-time check (where the scripts have run): a script that sets TOKEN means the
# default never renders, so the run is not refused
mkdir -p projects/ss
cat >projects/ss/set.sh <<'SH'
export TOKEN=set-by-script
SH
cat >projects/ss/mise.toml <<'TOML'
[secrets.fnox]

[env]
_.source = "set.sh"

[tasks.deploy]
secrets = ["DEPLOY_KEY"]
env = { TOKEN = { default = "{{ env.DEPLOY_KEY }}" } }
run = 'printf %s "$TOKEN" >tok.out'

[tasks.other]
secrets = ["DEPLOY_KEY"]
env = { OTHER = { default = "{{ env.DEPLOY_KEY }}" } }
run = 'true'
TOML
assert_succeed "env -u TOKEN DEPLOY_KEY=old mise run //projects/ss:deploy </dev/null"
assert "cat projects/ss/tok.out" "set-by-script"
# a default no script satisfies is still refused, at spawn
assert_fail_contains "env -u OTHER DEPLOY_KEY=old mise run //projects/ss:other </dev/null" "cannot see the secret DEPLOY_KEY"

# the shared hierarchy evaluation never crosses toolsets: a CLI --tool changes the base env, so
# the task env is evaluated afresh and still sees the tool
mkdir -p projects/tl
cat >projects/tl/mise.toml <<'TOML'
[secrets.fnox]

[env]
SEEN = "{{ exec(command='echo ${PATH}') | split(pat=':') | first }}"

[tasks.deploy]
secrets = ["DEPLOY_KEY"]
run = 'printf %s "$SEEN" >seen.out'
TOML
mise run //projects/tl:deploy </dev/null >/dev/null 2>&1
without_tool=$(cat projects/tl/seen.out)
mise run --tool dummy@1.0.0 //projects/tl:deploy </dev/null >/dev/null 2>&1
with_tool=$(cat projects/tl/seen.out)
[[ $without_tool != "$with_tool" ]] || fail "the task env did not reflect --tool ($with_tool)"
