#!/usr/bin/env bash

# Test that mise deactivate properly removes mise-managed environment
# while preserving user-added paths and variables

# Create a mise config with tools, env._.path, and env vars
mkdir -p custom_bin shared_entry user_bin
SHARED_PATH="$PWD/shared_entry"
cat >.mise.toml <<EOF
[tools]
tiny = "latest"

[env]
_.path = ["./custom_bin", "./shared_entry"]
FOO = "mise_foo"
BAR = "mise_bar"
EOF

mise install

# Save the original PATH and environment
ORIGINAL_PATH="$PATH"

# Activate mise and run hook-env
eval "$(mise activate bash)"
eval "$(mise hook-env -s bash)"

# Verify mise environment is set up
assert "echo $FOO" "mise_foo"
assert "echo $BAR" "mise_bar"
assert_contains "echo $PATH" "custom_bin"
assert_contains "echo $PATH" "/mise/installs/tiny"
assert_contains "echo $PATH" "$SHARED_PATH"

# User manually adds paths after activation
export PATH="$SHARED_PATH:$PATH"
export PATH="/user_path_1:$PATH"
export PATH="/user_path_2:$PATH"
# Add SHARED_PATH again after mise so PATH now has it before, within, and after
export PATH="$PATH:$SHARED_PATH"

# User sets their own environment variables
export USER_VAR="user_value"
export USER_PATH="/usr/local/myapp"

# Verify everything is in place before deactivation
assert "echo $FOO" "mise_foo"
assert "echo $USER_VAR" "user_value"
assert_contains "echo $PATH" "/user_path_1"
assert_contains "echo $PATH" "/user_path_2"
assert_contains "echo $PATH" "custom_bin"
assert_contains "echo $PATH" "/mise/installs/tiny"
assert_contains "echo $PATH" "$SHARED_PATH"

# SHARED_PATH should appear three times (before, inside, and after mise entries)
SHARED_COUNT=$(echo "$PATH" | tr ':' '\n' | grep -Fxc "$SHARED_PATH")
assert "echo $SHARED_COUNT" "3"

# Deactivate mise
# Note: Use 'command' to bypass the shell function and call the binary directly
eval "$(command mise deactivate)"

# After deactivation:

# 1. Mise-managed environment variables should be removed
assert "echo ${FOO:-unset}" "unset"
assert "echo ${BAR:-unset}" "unset"

# 2. User's own environment variables should be preserved
assert "echo $USER_VAR" "user_value"
assert "echo $USER_PATH" "/usr/local/myapp"

# 3. Mise-managed paths should be removed from PATH
assert_not_contains "echo $PATH" "/mise/installs/tiny"
assert_not_contains "echo $PATH" "custom_bin"

# Shared path should now appear exactly twice (before and after mise)
SHARED_COUNT=$(echo "$PATH" | tr ':' '\n' | grep -Fxc "$SHARED_PATH")
assert "echo $SHARED_COUNT" "2"

# 4. User-added paths should be preserved
assert_contains "echo $PATH" "/user_path_1"
assert_contains "echo $PATH" "/user_path_2"

# 5. Original PATH components should still be present
assert_contains "echo $PATH" "${ORIGINAL_PATH%%:*}"

# 6. No duplicate paths other than SHARED_PATH
PATH_COUNT=$(echo "$PATH" | tr ':' '\n' | grep -Fvx "$SHARED_PATH" | sort | uniq -d | wc -l)
assert "echo $PATH_COUNT" "0"

# 7. Mise shell integration should be removed
# The mise function should no longer exist
if type mise 2>/dev/null | grep -q "function"; then
	echo "ERROR: mise function still exists after deactivate"
	exit 1
fi

# 8. Test edge case: deactivating when not activated should be safe
eval "$(command mise deactivate)"
assert "echo deactivate_twice" "deactivate_twice"

# 9. Test reactivation after deactivation
eval "$(mise activate bash)"
eval "$(mise hook-env -s bash)"

# After reactivation, mise env vars should be back
assert "echo $FOO" "mise_foo"
assert "echo $BAR" "mise_bar"

# User additions should still be preserved
assert_contains "echo $PATH" "/user_path_1"
assert_contains "echo $PATH" "/user_path_2"
assert_contains "echo $PATH" "$SHARED_PATH"

# After reactivation, shared_entry appears 3 times:
# - Once from env._.path config (mise adds it to maintain user's intended ordering)
# - Twice from user manual additions (lines 36 and 40, preserved in PATH)
# This is correct behavior: user-configured paths are always added even if they
# exist elsewhere in PATH, to ensure the user's intended precedence is maintained.
SHARED_COUNT=$(echo "$PATH" | tr ':' '\n' | grep -Fxc "$SHARED_PATH")
assert "echo $SHARED_COUNT" "3"

# And user vars should still be there
assert "echo $USER_VAR" "user_value"

# 10. Test deactivation with modified env vars
# If user modifies a mise-managed variable, deactivation should still remove it
export FOO="user_modified_foo"
eval "$(command mise deactivate)"

# FOO should be removed entirely by deactivation (mise doesn't track user modifications)
assert "echo ${FOO:-unset}" "unset"
