#!/usr/bin/env bash

assert "mise generate bootstrap -w"
# shellcheck disable=SC2016
assert_contains "cat ./bin/mise" 'exec -a "$0" "$MISE_INSTALL_PATH" "$@"'
assert "./bin/mise version"

# The Windows launcher is opt-in, so the default must leave a project with the one file it had
# before the flag existed.
assert_fail "test -f ./bin/mise.cmd"

# `--windows` requires `--write`: stdout cannot carry two files, and silently ignoring the flag
# would look like it worked.
assert_fail "mise generate bootstrap --windows"

# `C:foo` is an ordinary directory name here and unrepresentable on Windows, so there is no value
# the launcher could carry. Refused at generate time rather than on the contributor's machine.
assert_fail "mise generate bootstrap -l --localized-dir C:foo -w ./bin/mise-drive --windows" "cannot be carried to Windows"
# The control: without --windows the same directory is still fine, because only the launcher cares.
assert "mise generate bootstrap -l --localized-dir C:foo -w ./bin/mise-drive"

# Windows cannot execute the shebang script, so `--windows` writes a `.cmd` beside it. Generated
# here too, not only on Windows: this file is committed, and whoever runs it on Windows is not the
# person who generated it.
assert "mise generate bootstrap -w --windows"
assert_succeed "test -f ./bin/mise.cmd"
assert_contains "cat ./bin/mise.cmd" "rem generated by mise generate bootstrap"
# Both architectures, for the same reason -- the generating host does not decide the running one.
assert_contains "cat ./bin/mise.cmd" 'set "sum_x64='
assert_contains "cat ./bin/mise.cmd" 'set "sum_arm64='
# The override has to clear the embedded hash or it would be checked against another version's exe.
# shellcheck disable=SC2016
assert_contains "cat ./bin/mise.cmd" 'if not "%resolved_version%"=="%pinned_version%" set "expected="'
# cmd variable names are case-insensitive, so a local named `mise_version` would *be* MISE_VERSION
# and would clobber the caller's value before it could be read.
assert_not_contains "cat ./bin/mise.cmd" 'set "mise_version='

# The two files must pin the same version. Everything above is structural and would still pass if
# the Windows half were generated against a different release than the bash half.
bash_version="$(grep -o 'MISE_VERSION:-[0-9.]*' ./bin/mise | head -1 | cut -d- -f2)"
test -n "$bash_version" # the grep above is the load-bearing part; an empty match must not pass
assert_contains "cat ./bin/mise.cmd" "set \"pinned_version=$bash_version\""

assert "mise tasks add xxx -- echo 'running xxx'"
assert "mise generate task-stubs --mise-bin ./bin/mise"
assert "./bin/xxx" "running xxx"

assert "mise generate bootstrap -l -w"
# shellcheck disable=SC2016
assert_contains "cat ./bin/mise" 'exec -a "$0" "$MISE_INSTALL_PATH" "$@"'

# ensure that the commands don't rely on the global mise bin
original_mise="$(which mise)"
mise_dir="$(dirname "$original_mise")"
OLD_PATH="$PATH"
PATH="$(echo "$PATH" | tr ':' '\n' | grep -v "^${mise_dir}$" | tr '\n' ':')"
PATH="${PATH%:}" # remove trailing colon

assert_contains "./bin/mise tasks ls" "xxx"

assert_not_contains "MISE_IGNORED_CONFIG_PATHS=$(pwd) ./bin/mise tasks ls" "xxx"

echo '
[tasks.other_task]
run = "echo running other_task"

[tasks.my_task]
run = ["{{mise_bin}} run other_task"]
' >mise.toml

assert_contains "./bin/mise run my_task" "running other_task"

PATH="$OLD_PATH"

# ./bin/mise is the localized script at this point, so generate a plain one too
assert "mise generate bootstrap -w ./bin/mise-plain"

# a stub at the resolved install path proves which path the script picked: it finds
# a binary there, skips the install, and execs it. Nothing is downloaded.
stub() {
  mkdir -p "$(dirname "$1")"
  echo '#!/usr/bin/env bash' >"$1"
  echo "echo \"$2 \$*\"" >>"$1"
  chmod +x "$1"
}

# a caller-provided MISE_INSTALL_PATH wins over the path baked into the script
stub "$PWD/custom/mise" custom-stub
assert "MISE_INSTALL_PATH=$PWD/custom/mise ./bin/mise-plain hello" "custom-stub hello"
assert "MISE_INSTALL_PATH=$PWD/custom/mise ./bin/mise hello" "custom-stub hello"

# MISE_VERSION keys the install path, otherwise changing it silently reuses the
# binary cached for the version the script was generated with. 9999.1.2 never exists.
stub "$HOME/.cache/mise/mise-9999.1.2" version-stub
assert "MISE_VERSION=v9999.1.2 ./bin/mise-plain hello" "version-stub hello"
assert "MISE_VERSION=9999.1.2 ./bin/mise-plain hello" "version-stub hello"

stub "$PWD/.mise/mise-9999.1.2" localized-version-stub
assert "MISE_VERSION=v9999.1.2 ./bin/mise hello" "localized-version-stub hello"

# Absolute localized directories must not be nested under the generated script's project root.
# Shell metacharacters in the path must also stay literal in the generated script.
absolute_localized_dir="$PWD/localized \$dir's cache"
printf -v absolute_localized_dir_arg '%q' "$absolute_localized_dir"
assert "mise generate bootstrap -l --localized-dir $absolute_localized_dir_arg -w ./bin/mise-absolute"
stub "$absolute_localized_dir/mise-9999.1.2" absolute-localized-stub
assert "MISE_VERSION=v9999.1.2 ./bin/mise-absolute hello" "absolute-localized-stub hello"
