#!/usr/bin/env bash

# Test to verify inconsistent behavior between `mise set` and `mise use`
# This test documents the current broken behavior that needs to be fixed

set -euo pipefail

# Track test failures
test_failures=0

# Disable trust checking for this test
export MISE_TRUSTED_CONFIG_PATHS="/"

original_home="$HOME"
test_home="/tmp/test_home_$$"
test_project="/tmp/test_project_$$"

# Set up test environment
mkdir -p "$test_home/.config/mise"
mkdir -p "$test_project"
export HOME="$test_home"

cleanup() {
  export HOME="$original_home"
  rm -rf "$test_home" "$test_project"
  if [ $test_failures -gt 0 ]; then
    echo "❌ Test failed with $test_failures failures"
    exit 1
  fi
}
trap cleanup EXIT

echo "=== Testing consistent behavior between commands ==="
cd "$test_home"

# Test 1: Both commands should handle global config consistently when explicitly requested
echo "Test 1: Both commands should handle --global flag consistently"
mise use --global dummy@1.0.0 >/dev/null 2>&1
mise set --global TEST_VAR=test_value >/dev/null 2>&1
echo "✓ Both commands accept --global flag without errors"
# Note: The actual global config functionality is tested elsewhere
# This test focuses on config resolution consistency, which is the main PR goal

echo "=== Testing behavior in project directory ==="
cd "$test_project"

# Test 3: In project dir, both should create local config
echo "Test 3: Both commands should create local config in project"
mise set PROJECT_VAR=project_value
if [ -f "$test_project/mise.toml" ]; then
  echo "✓ mise set created local config"
  rm "$test_project/mise.toml"
else
  echo "✗ mise set did not create local config"
  test_failures=$((test_failures + 1))
fi

mise use dummy@1.0.0 || echo "mise use failed (expected if dummy not installed)"
if [ -f "$test_project/mise.toml" ]; then
  echo "✓ mise use created local config"
  rm "$test_project/mise.toml"
else
  echo "✗ mise use did not create local config"
  test_failures=$((test_failures + 1))
fi

echo "=== Testing --path/--file directory handling ==="

# Test 4: mise use supports --path with directory
echo "Test 4: mise use --path with directory"
mkdir -p "$test_project/subdir"
mise use --path "$test_project/subdir" dummy@1.0.0 || echo "mise use failed (expected if dummy not installed)"
if [ -f "$test_project/subdir/mise.toml" ]; then
  echo "✓ mise use --path with directory worked"
  rm "$test_project/subdir/mise.toml"
else
  echo "✗ mise use --path with directory failed"
  test_failures=$((test_failures + 1))
fi

# Test 5: mise set --file should support directory (like mise use --path)
echo "Test 5: mise set --file with directory should work like mise use --path"
if mise set --file "$test_project/subdir" TEST_VAR=test; then
  echo "✓ mise set --file with directory worked"
  if [ -f "$test_project/subdir/mise.toml" ]; then
    echo "✓ mise set created config file in directory"
    rm "$test_project/subdir/mise.toml"
  else
    echo "✗ mise set did not create config file in directory"
    test_failures=$((test_failures + 1))
  fi
else
  echo "✗ mise set --file with directory failed"
  test_failures=$((test_failures + 1))
fi

echo "=== Testing paths mise cannot read back ==="

# Test 5b: a path that does not exist. Neither command can tell "directory the user meant to
# create" from "file with an unrecognised name", and a file mise refuses to read is worse than an
# error: `mise set` used to write one and exit 0. A target per command, so that one creating a
# file cannot be misread as the other doing it, and so nothing has to be deleted to tell them
# apart — the trap at the top of this file owns cleanup.
echo "Test 5b: --path/--file pointing at something that does not exist"
missing_use="$test_project/missing_for_use"
missing_set="$test_project/missing_for_set"

if mise use --path "$missing_use" dummy@1.0.0 >/dev/null 2>&1; then
  echo "✗ mise use --path accepted a path that does not exist"
  test_failures=$((test_failures + 1))
else
  echo "✓ mise use --path rejected it"
fi
if [ -e "$missing_use" ]; then
  echo "✗ mise use --path created $missing_use"
  test_failures=$((test_failures + 1))
fi

if mise set --file "$missing_set" MISSING_VAR=1 >/dev/null 2>&1; then
  echo "✗ mise set --file accepted a path that does not exist"
  test_failures=$((test_failures + 1))
else
  echo "✓ mise set --file rejected it"
fi
if [ -e "$missing_set" ]; then
  echo "✗ mise set --file created $missing_set, which mise cannot read back"
  test_failures=$((test_failures + 1))
fi

# Test 5c: a name mise does recognise, but not as TOML. Both halves of it: creating one, and being
# pointed at one that already exists. The second is why the check runs before mise looks at whether
# the file is there — otherwise it fails later as invalid TOML, which does not say what is wrong.
echo "Test 5c: mise set --file pointing at a .tool-versions"
mkdir -p "$test_project/tvnew" "$test_project/tvold"
tv_new="$test_project/tvnew/.tool-versions"
tv_existing="$test_project/tvold/.tool-versions"
printf 'node 20\n' >"$tv_existing"

if mise set --file "$tv_new" TV_VAR=1 >/dev/null 2>&1; then
  echo "✗ mise set --file wrote TOML to a new .tool-versions path"
  test_failures=$((test_failures + 1))
else
  echo "✓ mise set --file rejected a new .tool-versions path"
fi
if [ -e "$tv_new" ]; then
  echo "✗ mise set --file created $tv_new"
  test_failures=$((test_failures + 1))
fi

# Whitespace is squeezed before matching so that wrapping the message cannot break the assertion.
if tv_output=$(mise set --file "$tv_existing" TV_VAR=1 2>&1); then
  echo "✗ mise set --file wrote TOML to an existing .tool-versions"
  test_failures=$((test_failures + 1))
elif ! printf '%s' "$tv_output" | tr -s '[:space:]' ' ' | grep -Fq 'cannot write TOML'; then
  echo "✗ mise set --file rejected an existing .tool-versions without saying why: $tv_output"
  test_failures=$((test_failures + 1))
else
  echo "✓ mise set --file rejected an existing .tool-versions with a reason"
fi
if [ "$(cat "$tv_existing")" != "node 20" ]; then
  echo "✗ mise set --file modified $tv_existing"
  test_failures=$((test_failures + 1))
fi

echo "=== Testing environment-specific configs ==="

# Test 6: Both should handle --env consistently
echo "Test 6: Environment-specific config handling"
cd "$test_project"

mise use --env staging dummy@1.0.0 || echo "mise use failed (expected if dummy not installed)"
staging_file_use=""
if [ -f "mise.staging.toml" ]; then
  staging_file_use="mise.staging.toml"
elif [ -f ".mise.staging.toml" ]; then
  staging_file_use=".mise.staging.toml"
fi

mise set --env staging STAGING_VAR=staging_value
staging_file_set=""
if [ -f "mise.staging.toml" ]; then
  staging_file_set="mise.staging.toml"
elif [ -f ".mise.staging.toml" ]; then
  staging_file_set=".mise.staging.toml"
fi

if [ "$staging_file_use" = "$staging_file_set" ] && [ -n "$staging_file_use" ]; then
  echo "✓ Both commands use same staging config file: $staging_file_use"
  rm "$staging_file_use"
else
  echo "✗ Commands use different staging config files:"
  echo "  mise use: $staging_file_use"
  echo "  mise set: $staging_file_set"
  test_failures=$((test_failures + 1))
  [ -n "$staging_file_use" ] && rm "$staging_file_use"
  [ -n "$staging_file_set" ] && rm "$staging_file_set"
fi

echo "=== Testing config file precedence ==="

# Test 7: Create hierarchy and see where each command writes
echo "Test 7: Config file precedence handling"
cd "$test_project"

# Create parent directory with config
mkdir -p parent
echo '[env]' >parent/mise.toml
echo 'PARENT_VAR = "parent"' >>parent/mise.toml

# Create subdirectory
mkdir -p parent/child
cd parent/child

echo "Current directory: $(pwd)"
echo "Parent config exists: $([ -f ../mise.toml ] && echo yes || echo no)"

# Test where each command writes when parent has config
mise use --pin dummy@1.0.0 || echo "mise use failed (expected if dummy not installed)"
use_created_local=$([ -f mise.toml ] && echo yes || echo no)

mise set CHILD_VAR=child_value
set_created_local=$([ -f mise.toml ] && echo yes || echo no)

echo "mise use created local config: $use_created_local"
echo "mise set created local config: $set_created_local"

if [ "$use_created_local" = "$set_created_local" ]; then
  echo "✓ Both commands handle precedence consistently"
else
  echo "✗ Commands handle precedence differently (INCONSISTENT)"
  test_failures=$((test_failures + 1))
fi
