#!/usr/bin/env bash

# bootstrap with nothing configured succeeds and does nothing
cat <<EOF >mise.toml
[tools]
EOF
assert_succeed "mise bootstrap --yes"

# bootstrap applies dotfiles, installs tools, and runs the
# `bootstrap` task afterwards, with the installed tools on PATH
echo "gitconfig content" >gitconfig
cat <<'EOF' >mise.toml
[tools]
tiny = "1.0.0"

[dotfiles]
"~/.gitconfig" = "gitconfig"
"~/.zshrc/activate" = { block = 'eval "$(mise activate zsh)"' }

# the task only succeeds if the installed tool is on PATH
[tasks.bootstrap]
run = "command -v rtx-tiny && echo task-done > bootstrap_ran"
EOF
assert_succeed "mise bootstrap --yes"
assert "cat bootstrap_ran" "task-done"
assert_contains "mise ls tiny" "1.0.0"
assert "readlink ~/.gitconfig" "$PWD/gitconfig"
assert_contains "cat ~/.zshrc" ">>> mise:activate >>>"

# idempotent: re-running is fine
assert_succeed "mise bootstrap --yes"

# dry-run doesn't install or run anything
rm -f bootstrap_ran
cat <<EOF >mise.toml
[tools]
tiny = "2.1.0"

[tasks.bootstrap]
run = "touch bootstrap_ran"
EOF
assert_succeed "mise bootstrap --dry-run"
assert_directory_not_exists "$MISE_DATA_DIR/installs/tiny/2.1.0"
assert_fail "cat bootstrap_ran"

# macOS LaunchAgents in shared configs are inert when launchd is unavailable
cat <<EOF >mise.toml
[bootstrap.macos.launchd.agents.my-sync]
program = "~/.local/bin/my-sync"
run_at_load = true
EOF
assert_succeed "mise bootstrap --dry-run"
if [[ $(uname) == "Darwin" ]]; then
  assert_contains "mise bootstrap launchd status" "my-sync"
else
  assert_contains "mise bootstrap launchd status" "skipped"
fi

# systemd user services are declarative and safe to inspect in dry-runs
cat <<EOF >mise.toml
[bootstrap.linux.systemd.units.my-sync]
description = "sync files"
exec_start = "~/.local/bin/my-sync --watch"
restart = "on-failure"
EOF
DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/mise-test-bus assert_succeed "mise bootstrap --dry-run"
DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/mise-test-bus assert_contains "mise bootstrap systemd status" "my-sync"

# unavailable system package managers are skipped, not errors
cat <<EOF >mise.toml
[bootstrap.packages]
"apt:bc" = "latest"
"dnf:bc" = "latest"
"pacman:bc" = "latest"
EOF
assert_succeed "mise bootstrap --dry-run"

# dotfiles can add config that contributes hooks to later phases in the same run
mkdir -p dotfiles/mise
cat <<'EOF' >dotfiles/mise/config.toml
[bootstrap.hooks.post-dotfiles]
run = "echo post-dotfiles > post_dotfiles_hook_ran"

[bootstrap.hooks.final]
run = "echo final > final_hook_ran"
EOF
cat <<EOF >mise.toml
[dotfiles]
"~/.config/mise/config.toml" = "dotfiles/mise/config.toml"
EOF
rm -f post_dotfiles_hook_ran final_hook_ran
assert_contains "mise bootstrap --dry-run" "echo post-dotfiles > post_dotfiles_hook_ran"
assert_contains "mise bootstrap --dry-run" "echo final > final_hook_ran"
assert_fail "cat post_dotfiles_hook_ran"
assert_fail "cat final_hook_ran"
assert_succeed "mise bootstrap --yes"
assert "cat post_dotfiles_hook_ran" "post-dotfiles"
assert "cat final_hook_ran" "final"

# bootstrap refuses dotfile conflicts unless scoped force is requested
echo "bootstrap source" >dotfiles/bootstrap-force
cat <<EOF >mise.toml
[dotfiles]
"~/.bootstrap-force-dotfiles" = "dotfiles/bootstrap-force"
EOF
echo "local content" >~/.bootstrap-force-dotfiles
assert_fail "mise bootstrap --yes" "use --force-dotfiles"
assert "cat ~/.bootstrap-force-dotfiles" "local content"
assert_succeed "mise bootstrap --yes --force-dotfiles"
assert "readlink ~/.bootstrap-force-dotfiles" "$PWD/dotfiles/bootstrap-force"

# dry-run previews hooks from templated config dotfiles
cat <<'EOF' >dotfiles/mise/config.local.toml.tmpl
[bootstrap.hooks.final]
run = "echo {{ vars.templated_hook_value }} > templated_hook_ran"
EOF
cat <<EOF >mise.toml
[vars]
templated_hook_value = "template-final"

[dotfiles]
"~/.config/mise/config.local.toml" = { source = "dotfiles/mise/config.local.toml.tmpl", mode = "template" }
EOF
rm -f templated_hook_ran
assert_contains "mise bootstrap --dry-run" "echo template-final > templated_hook_ran"
assert_fail "cat templated_hook_ran"

# dry-run recognizes local config targets such as ~/.mise/config.toml
cat <<'EOF' >dotfiles/mise/local-config.toml
[bootstrap.hooks.post-dotfiles]
run = "echo mise-dir > mise_dir_hook_ran"
EOF
cat <<EOF >mise.toml
[dotfiles]
"~/.mise/config.toml" = "dotfiles/mise/local-config.toml"
EOF
rm -f mise_dir_hook_ran
assert_contains "mise bootstrap --dry-run" "echo mise-dir > mise_dir_hook_ran"
assert_fail "cat mise_dir_hook_ran"
