#!/usr/bin/env bash

# `mise plugins uninstall --purge` removes every tool a backend plugin provides.

PLUGIN_DIR="$PWD/purge-backend"
mkdir -p "$PLUGIN_DIR/hooks"

cat >"$PLUGIN_DIR/metadata.lua" <<'LUA'
PLUGIN = {
	name = "purge-backend",
	version = "0.1.0",
	description = "backend plugin purge test plugin",
}
LUA

cat >"$PLUGIN_DIR/hooks/backend_list_versions.lua" <<'LUA'
function PLUGIN:BackendListVersions(ctx)
	return { versions = { "1.0.0" } }
end
LUA

cat >"$PLUGIN_DIR/hooks/backend_install.lua" <<'LUA'
function PLUGIN:BackendInstall(ctx)
	local file = io.open(ctx.install_path .. "/manifest", "w")
	file:write(ctx.tool .. "@" .. ctx.version)
	file:close()
	return {}
end
LUA

cat >"$PLUGIN_DIR/hooks/backend_exec_env.lua" <<'LUA'
function PLUGIN:BackendExecEnv(ctx)
	return { env_vars = {} }
end
LUA

mise plugins link purge-backend "$PLUGIN_DIR"
mise plugins link keep-backend "$PLUGIN_DIR"
mise plugins link purge "$PLUGIN_DIR"
mise install purge-backend:demo@1.0.0 purge-backend:other@1.0.0 purge-backend:shared@1.0.0 keep-backend:demo@1.0.0
# purge-backend:twin is installed, and config below also declares
# purge:backend-twin, another backend's tool using the same directory.
mise install purge-backend:twin@1.0.0
# purge:backend-extra lives in installs/purge-backend-extra, the directory
# purge-backend:extra would use.
mise install purge:backend-extra@1.0.0
assert "cat '$MISE_DATA_DIR/installs/purge-backend-extra/1.0.0/manifest'" "backend-extra@1.0.0"
assert_directory_exists "$MISE_CACHE_DIR/purge-backend-extra"
assert "cat '$MISE_DATA_DIR/installs/purge-backend-demo/1.0.0/manifest'" "demo@1.0.0"
assert "cat '$MISE_DATA_DIR/installs/purge-backend-other/1.0.0/manifest'" "other@1.0.0"
assert_directory_exists "$MISE_CACHE_DIR/purge-backend-demo"
assert_directory_exists "$MISE_CACHE_DIR/purge-backend-other"
mkdir -p "$MISE_DATA_DIR/downloads/purge-backend-demo/1.0.0"

# A configured tool whose last version was already uninstalled keeps its
# tool-level cache, and its downloads with always_keep_download.
cat >mise.toml <<'TOML'
[tools]
"purge-backend:gone" = "1.0.0"
"purge-backend:extra" = "1.0.0"
"purge:backend-twin" = "1.0.0"
TOML
mise install purge-backend:gone@1.0.0
MISE_ALWAYS_KEEP_DOWNLOAD=1 mise uninstall purge-backend:gone@1.0.0
assert_directory_exists "$MISE_CACHE_DIR/purge-backend-gone"
mkdir -p "$MISE_DATA_DIR/downloads/purge-backend-gone/1.0.0"
assert_contains "mise ls --installed" "purge-backend:demo"
assert_not_contains "mise ls --installed" "purge-backend:gone"
# A directory is never purged by its name alone: this could be another
# backend's tool.
mkdir -p "$MISE_CACHE_DIR/purge-backend-stray"

# Installs in a shared install dir belong to other users too, so they survive:
# one tool installed only there, and a copy of a tool the user also installed.
SHARED_INSTALLS="$PWD/shared-installs"
mkdir -p "$SHARED_INSTALLS"
mv "$MISE_DATA_DIR/installs/purge-backend-shared" "$SHARED_INSTALLS/"
cp -R "$MISE_DATA_DIR/installs/purge-backend-demo" "$SHARED_INSTALLS/"
export MISE_SHARED_INSTALL_DIRS="$SHARED_INSTALLS"
assert_contains "mise ls purge-backend:shared" "1.0.0"
assert_directory_exists "$MISE_CACHE_DIR/purge-backend-shared"

mise plugins uninstall purge-backend --purge >purge.log 2>&1
assert_contains "cat purge.log" "not purging purge-backend:extra"
assert_contains "cat purge.log" "not purging purge-backend:twin"
assert_fail "mise plugins ls | grep -qx purge-backend"
assert_directory_not_exists "$MISE_DATA_DIR/installs/purge-backend-demo"
assert_directory_not_exists "$MISE_DATA_DIR/installs/purge-backend-other"
assert_directory_not_exists "$MISE_CACHE_DIR/purge-backend-demo"
assert_directory_not_exists "$MISE_CACHE_DIR/purge-backend-other"
assert_directory_not_exists "$MISE_DATA_DIR/downloads/purge-backend-demo"
assert_directory_not_exists "$MISE_DATA_DIR/installs/purge-backend-gone"
assert_directory_not_exists "$MISE_CACHE_DIR/purge-backend-gone"
assert_directory_not_exists "$MISE_DATA_DIR/downloads/purge-backend-gone"
assert_directory_exists "$MISE_CACHE_DIR/purge-backend-stray"
# A configured tool that is not installed does not own a directory another
# backend's tool is installed in.
assert "cat '$MISE_DATA_DIR/installs/purge-backend-extra/1.0.0/manifest'" "backend-extra@1.0.0"
assert_directory_exists "$MISE_CACHE_DIR/purge-backend-extra"
# Nor does an installed tool own a directory another backend's configured
# tool would use: which of them its cache belongs to is unknown.
assert "cat '$MISE_DATA_DIR/installs/purge-backend-twin/1.0.0/manifest'" "twin@1.0.0"
assert "cat '$SHARED_INSTALLS/purge-backend-shared/1.0.0/manifest'" "shared@1.0.0"
assert "cat '$SHARED_INSTALLS/purge-backend-demo/1.0.0/manifest'" "demo@1.0.0"
# The user's own cache for the shared-only tool is still purged.
assert_directory_not_exists "$MISE_CACHE_DIR/purge-backend-shared"

# Another backend plugin's tools are left alone.
assert_contains "mise plugins ls" "keep-backend"
assert "cat '$MISE_DATA_DIR/installs/keep-backend-demo/1.0.0/manifest'" "demo@1.0.0"

# A single-tool plugin is skipped the same way when another tool uses its
# directory: plugin keep-backend-tool and keep-backend:tool both use
# keep-backend-tool.
SOLO_DIR="$PWD/solo-plugin"
mkdir -p "$SOLO_DIR/bin"
cat >"$SOLO_DIR/bin/list-all" <<'SCRIPT'
#!/usr/bin/env bash
echo 1.0.0
SCRIPT
cat >"$SOLO_DIR/bin/install" <<'SCRIPT'
#!/usr/bin/env bash
mkdir -p "$ASDF_INSTALL_PATH/bin"
echo solo >"$ASDF_INSTALL_PATH/manifest"
SCRIPT
chmod +x "$SOLO_DIR/bin/list-all" "$SOLO_DIR/bin/install"
mise plugins link keep-backend-tool "$SOLO_DIR"
mise install keep-backend-tool@1.0.0
cat >mise.toml <<'TOML'
[tools]
"keep-backend:tool" = "1.0.0"
TOML
assert_contains "mise plugins uninstall keep-backend-tool --purge 2>&1" "not purging keep-backend-tool"
assert "cat '$MISE_DATA_DIR/installs/keep-backend-tool/1.0.0/manifest'" "solo"

# A single-tool plugin installed only in a shared install dir keeps that
# install, even when config loading has cached a backend for it there.
rm mise.toml
mise plugins link solo-shared "$SOLO_DIR"
mise install solo-shared@1.0.0
mv "$MISE_DATA_DIR/installs/solo-shared" "$SHARED_INSTALLS/"
assert_contains "mise ls solo-shared" "1.0.0"
MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS=solo-shared mise plugins uninstall solo-shared --purge
assert_fail "mise plugins ls | grep -qx solo-shared"
assert "cat '$SHARED_INSTALLS/solo-shared/1.0.0/manifest'" "solo"
assert_directory_not_exists "$MISE_CACHE_DIR/solo-shared"
