#!/usr/bin/env bash

# Test that postinstall hooks have access to pre_tools environment variables

# Create a mise.toml with env vars that should be available before tools
cat <<EOF >mise.toml
[env]
# Environment variable without tools=true (should be available in postinstall)
PRE_TOOLS_VAR = "available_before_tools"

# Environment variable explicitly with tools=false
EXPLICIT_PRE_TOOLS = {value = "explicitly_pre_tools", tools = false}

# Environment variable with tools=true (should NOT be available in postinstall)
POST_TOOLS_VAR = {value = "available_after_tools", tools = true}

[tools]
dummy = { version = "latest", install_env = { INSTALL_ENV_VAR = "available_during_install", INSTALL_ENV_REMOVE = false }, postinstall = "echo PRE_TOOLS_VAR=\$PRE_TOOLS_VAR; echo EXPLICIT_PRE_TOOLS=\$EXPLICIT_PRE_TOOLS; echo POST_TOOLS_VAR=\$POST_TOOLS_VAR; echo INSTALL_ENV_VAR=\$INSTALL_ENV_VAR; echo INSTALL_ENV_REMOVE=\${INSTALL_ENV_REMOVE-unset}" }
EOF

# Remove any existing dummy installation to force reinstall
rm -rf ~/.mise/installs/dummy

# Run install and capture output
output=$(INSTALL_ENV_REMOVE=inherited mise install dummy 2>&1)

# Check that pre_tools environment variables are available in postinstall
if [[ $output == *"PRE_TOOLS_VAR=available_before_tools"* ]]; then
  echo "✓ PRE_TOOLS_VAR is available in postinstall"
else
  echo "✗ PRE_TOOLS_VAR is NOT available in postinstall"
  echo "Output: $output"
  exit 1
fi

if [[ $output == *"EXPLICIT_PRE_TOOLS=explicitly_pre_tools"* ]]; then
  echo "✓ EXPLICIT_PRE_TOOLS is available in postinstall"
else
  echo "✗ EXPLICIT_PRE_TOOLS is NOT available in postinstall"
  echo "Output: $output"
  exit 1
fi

if [[ $output == *"INSTALL_ENV_VAR=available_during_install"* ]]; then
  echo "✓ INSTALL_ENV_VAR is available in postinstall"
else
  echo "✗ INSTALL_ENV_VAR is NOT available in postinstall"
  echo "Output: $output"
  exit 1
fi

if [[ $output == *"INSTALL_ENV_REMOVE=unset"* ]]; then
  echo "✓ false install_env removes inherited variables from postinstall"
else
  echo "✗ false install_env did not remove inherited variable from postinstall"
  echo "Output: $output"
  exit 1
fi

# The post_tools var should be empty since it's marked as tools=true
if [[ $output == *"POST_TOOLS_VAR="* ]]; then
  echo "✓ POST_TOOLS_VAR is empty as expected"
else
  echo "✗ POST_TOOLS_VAR is not empty"
  echo "Output: $output"
  exit 1
fi

# Verify that POST_TOOLS_VAR with tools=true is NOT available in postinstall hook
if [[ $output != *"POST_TOOLS_VAR=available_after_tools"* ]]; then
  echo "✓ POST_TOOLS_VAR with tools=true is not available as expected"
else
  echo "✗ POST_TOOLS_VAR with tools=true should not be available"
  echo "Output: $output"
  exit 1
fi

# The same pre-tools env must reach a postinstall hook for a backend that does
# not resolve config env on its own. `dummy` is an asdf plugin, and those
# resolve config env to run their own scripts, which is why this held for
# `dummy` alone: every other backend reached the hook with an empty config env.
FIXTURES="$TMPDIR/postinstall-env-fixtures"
PORT_FILE="$TMPDIR/postinstall-env-port"
mkdir -p "$FIXTURES/demo/bin"
cat >"$FIXTURES/demo/bin/demo" <<'BINEOF'
#!/usr/bin/env bash
echo demo
BINEOF
chmod +x "$FIXTURES/demo/bin/demo"
tar czf "$FIXTURES/demo.tar.gz" -C "$FIXTURES" demo

python3 -u - "$FIXTURES" "$PORT_FILE" <<'PYEOF' >/dev/null 2>&1 &
import functools
import http.server
import socketserver
import sys
from pathlib import Path

root = sys.argv[1]
port_file = Path(sys.argv[2])
handler = functools.partial(http.server.SimpleHTTPRequestHandler, directory=root)
with socketserver.TCPServer(("127.0.0.1", 0), handler) as httpd:
    port_file.write_text(str(httpd.server_address[1]))
    httpd.serve_forever()
PYEOF
SERVER_PID=$!
trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT
wait_for_file "$PORT_FILE" "postinstall env test server port file" 30 "$SERVER_PID"
PORT=$(cat "$PORT_FILE")

cat <<TOMLEOF >mise.toml
[env]
PRE_TOOLS_VAR = "available_before_tools"
POST_TOOLS_VAR = { value = "available_after_tools", tools = true }

[tools."http:demo"]
version = "1.0.0"
url = "http://127.0.0.1:$PORT/demo.tar.gz"
bin_path = "demo/bin"
postinstall = "echo HTTP_PRE_TOOLS_VAR=\$PRE_TOOLS_VAR; echo HTTP_POST_TOOLS_VAR=\$POST_TOOLS_VAR"
TOMLEOF

http_output=$(mise install 2>&1)
assert_contains_text "$http_output" "HTTP_PRE_TOOLS_VAR=available_before_tools"
assert_not_contains_text "$http_output" "HTTP_POST_TOOLS_VAR=available_after_tools"

# Hooks run one after another inside a single install batch, and an [env] value
# can read a file an earlier hook just wrote. The config env used to be memoized
# by whichever hook asked first — with parallel installs, a race — so every later
# hook got that snapshot. A hook ordered after another must see what it did.
echo "STATE=before" >state.env

cat <<ORDEREOF >mise.toml
[env]
_.file = "state.env"

[tools]
"http:first" = { version = "1.0.0", url = "http://127.0.0.1:$PORT/demo.tar.gz", bin_path = "demo/bin", postinstall = "echo FIRST_STATE=\$STATE; echo STATE=after > \$MISE_CONFIG_ROOT/state.env" }
"http:second" = { version = "1.0.0", url = "http://127.0.0.1:$PORT/demo.tar.gz", bin_path = "demo/bin", depends = ["http:first"], postinstall = "echo SECOND_STATE=\$STATE" }
ORDEREOF

ordered_output=$(mise install 2>&1)
assert_contains_text "$ordered_output" "FIRST_STATE=before"
assert_contains_text "$ordered_output" "SECOND_STATE=after"
