#!/usr/bin/env bash

export CLICOLOR=0

# "local" is the nearest directory with a config file, not every config above it
mkdir -p parent/app/src
echo "dummy 1.0.0" >parent/.tool-versions
cat >parent/app/mise.toml <<EOF
[tools]
dummy = "1.1.0"
EOF
mkdir -p parent/frag/.mise/conf.d/dummy parent/pathed/ext
cat >parent/frag/.mise/conf.d/dummy/mise.toml <<EOF
[tools]
dummy = "2.0.0"
EOF
touch parent/pathed/ext/keep
cat >parent/pathed/mise.toml <<EOF
[tools]
dummy = "path:$PWD/parent/pathed/ext"
EOF
mise i dummy@{1.0.0,1.1.0,2.0.0}

# a project made only of a conf.d folder fragment is found from its root
out="$(cd parent/frag && mise uninstall --project --dry-run 2>&1)"
assert_contains_text "$out" "dummy@2.0.0 is requested by"
assert_not_contains_text "$out" "dummy@1.0.0"
assert_not_contains_text "$out" "dummy@1.1.0"

# every file in the directory counts, even when a later one overrides the tool
mkdir -p parent/layered
printf '[tools]\ndummy = "1.0.0"\n' >parent/layered/mise.toml
printf '[tools]\ndummy = "2.0.0"\n' >parent/layered/mise.local.toml
out="$(cd parent/layered && mise uninstall --project --dry-run 2>&1)"
assert_contains_text "$out" "dummy@1.0.0 is requested by"
assert_contains_text "$out" "dummy@2.0.0 is requested by"
assert_not_contains_text "$out" "dummy@1.1.0"

# daemons that disagree on a version do not block cleanup, and their tools count
mkdir -p parent/daemons
cat >parent/daemons/mise.toml <<EOF
[tools]
dummy = "1.1.0"
[daemons.first]
preset = "redis"
version = "1.0.0"
tool = "dummy"
[daemons.second]
preset = "redis"
version = "2.0.0"
tool = "dummy"
port = 6380
EOF
out="$(cd parent/daemons && mise uninstall --project --dry-run 2>&1)"
assert_contains_text "$out" "dummy@1.1.0 is requested by"
assert_contains_text "$out" "dummy@1.0.0 is requested by"

# a tool that settings disable is left alone
assert_contains "cd parent/app && MISE_DISABLE_TOOLS=dummy mise uninstall --project --dry-run 2>&1" "no installed tools are requested"

# running from inside the .mise folder still finds the project that owns it
mkdir -p parent/dotmise/.mise
printf '[tools]\ndummy = "1.0.0"\n' >parent/dotmise/mise.toml
printf '[tools]\ndummy = "2.0.0"\n' >parent/dotmise/.mise/config.toml
out="$(cd parent/dotmise/.mise && mise uninstall --project --dry-run 2>&1)"
assert_contains_text "$out" "dummy@1.0.0 is requested by"
assert_contains_text "$out" "dummy@2.0.0 is requested by"

# running from inside a plain .config folder does too
mkdir -p parent/dotconfig/.config
printf '[tools]\ndummy = "1.0.0"\n' >parent/dotconfig/mise.toml
printf '[tools]\ndummy = "2.0.0"\n' >parent/dotconfig/.config/mise.toml
out="$(cd parent/dotconfig/.config && mise uninstall --project --dry-run 2>&1)"
assert_contains_text "$out" "dummy@1.0.0 is requested by"
assert_contains_text "$out" "dummy@2.0.0 is requested by"

# a git checkout of its own inside .config is a project of its own
mkdir -p parent/nested/.config
printf '[tools]\ndummy = "1.0.0"\n' >parent/nested/mise.toml
printf '[tools]\ndummy = "2.0.0"\n' >parent/nested/.config/mise.toml
git init -q parent/nested/.config
out="$(cd parent/nested/.config && mise uninstall --project --dry-run 2>&1)"
assert_contains_text "$out" "dummy@2.0.0 is requested by"
assert_not_contains_text "$out" "dummy@1.0.0"

# a path request names a directory mise did not install, so it is never removed
assert_contains "cd parent/pathed && mise uninstall --project --yes 2>&1" "no installed tools are requested"
assert_succeed "test -f parent/pathed/ext/keep"

cd parent/app/src || exit 1

assert_fail "mise uninstall --project --all"
assert_fail "mise uninstall --project dummy@1.1.0"

# a dry run names the version and where it is requested, and removes nothing
out="$(mise uninstall --project --dry-run 2>&1)"
assert_contains_text "$out" "dummy@1.1.0 is requested by"
assert_contains_text "$out" "parent/app/mise.toml"
assert_not_contains_text "$out" "dummy@1.0.0"
assert_not_contains_text "$out" "dummy@2.0.0"
assert_contains "mise ls --installed dummy" "1.1.0"

# a shell override does not hide what the project's config requests
assert_contains "MISE_DUMMY_VERSION=2.0.0 mise uninstall --project --dry-run 2>&1" "dummy@1.1.0 is requested by"
assert_fail_contains "mise uninstall --project --dry-run-code 2>&1" "uninstalled (dry-run)"

# without a terminal to ask, it refuses rather than removing
assert_fail_contains "MISE_YES=0 mise uninstall --project </dev/null 2>&1" "requires confirmation"
assert_contains "mise ls --installed dummy" "1.1.0"

# --yes skips the question; the parent's version and the unrequested one stay
mise uninstall --project --yes
assert_not_contains "mise ls --installed dummy" "1.1.0"
assert_contains "mise ls --installed dummy" "1.0.0"
assert_contains "mise ls --installed dummy" "2.0.0"

# nothing requested is installed any more
assert_contains "mise uninstall --project --yes 2>&1" "no installed tools are requested"
assert_succeed "mise uninstall --project --dry-run-code"

# from the parent, its own config is the local one
cd .. && cd .. || exit 1
mise uninstall --project --yes
assert_not_contains "mise ls --installed dummy" "1.0.0"
assert_contains "mise ls --installed dummy" "2.0.0"
