#!/usr/bin/env bash
# One recovery journey: independent/offline edits, conflicts, an interrupted
# pull, undo, and fresh setup on a third machine from ordinary Git history.
# shellcheck disable=SC2016
require_cmd git
export MISE_EXPERIMENTAL=0

origin="$PWD/origin.git"
git init -q --bare -b main "$origin"
mkdir -p ~/.config/journey
printf 'initial\n' >~/.config/journey/bindings
printf 'machine-specific\n' >~/.config/journey/monitor
chmod 600 ~/.config/journey/monitor
assert_succeed 'mise bootstrap dotfiles track ~/.config/journey/bindings'
assert_succeed "mise bootstrap dotfiles origin set file://$origin --sync manual --yes"
initial=$(git --git-dir="$origin" rev-parse main)

wrapper() {
  mkdir -p "$2/.config/mise"
  cat <<WRAPPER >"$PWD/$1"
#!/usr/bin/env bash
export HOME="$2" XDG_CONFIG_HOME="$2/.config" MISE_CONFIG_DIR="$2/.config/mise" \\
  MISE_STATE_DIR="$2/.local/state/mise" MISE_DATA_DIR="$2/.local/share/mise" \\
  MISE_CACHE_DIR="$2/.cache/mise" MISE_TRUSTED_CONFIG_PATHS="$2"
cd "\$HOME" && exec mise "\$@"
WRAPPER
  chmod +x "$PWD/$1"
}
B="$(dirname "$HOME")/journey-b"
C="$(dirname "$HOME")/journey-c"
wrapper journey-b "$B"
wrapper journey-c "$C"
b="$PWD/journey-b"
c="$PWD/journey-c"
assert_succeed "$b bootstrap --from-git file://$origin --yes --only dotfiles"
assert "cat $B/.config/journey/bindings" 'initial'
assert_fail "test -e $B/.config/journey/monitor"

# Independent edits survive an offline interval; neither side silently wins.
printf 'laptop edit\n' >~/.config/journey/bindings
assert_succeed 'mise bootstrap dotfiles save'
mv "$origin" "$origin.offline"
printf 'desktop edit\n' >"$B/.config/journey/bindings"
chmod +x "$B/.config/journey/bindings"
assert_succeed "$b bootstrap dotfiles save"
assert_fail "$b bootstrap dotfiles sync"
assert_contains "$b bootstrap dotfiles history diff latest --patch" '+desktop edit'
mv "$origin.offline" "$origin"
assert_succeed 'mise bootstrap dotfiles sync'
assert_succeed "$b bootstrap dotfiles sync"
assert_fail "$b bootstrap dotfiles pull --yes" 'sync paused'
assert "cat $B/.config/journey/bindings" 'desktop edit'
assert_contains "$b bootstrap dotfiles status" 'mise dot conflicts'
assert_contains "$b bootstrap dotfiles conflicts $B/.config/journey/bindings" '-desktop edit'
assert_contains "$b bootstrap dotfiles conflicts $B/.config/journey/bindings" '+laptop edit'
HOME="$B" git config --global merge.tool mise-test
HOME="$B" git config --global mergetool.mise-test.cmd \
  'grep -q "desktop edit" "$LOCAL" && grep -q "laptop edit" "$REMOTE" && touch "$HOME/difftool-ran"'
assert_contains "$b bootstrap dotfiles conflicts --difftool $B/.config/journey/bindings" 'mode: 100755 -> 100644'
assert_succeed "test -f $B/difftool-ran"
assert_succeed "$b bootstrap dotfiles pull --take-remote $B/.config/journey/bindings --yes"
assert "cat $B/.config/journey/bindings" 'laptop edit'

# Stop a real pull at its first Git operation after the live file changes,
# before it records the outcome checkpoint. The shim affects only this child.
pidfile="$PWD/pull.pid"
real_git=$(command -v git)
mkdir "$PWD/crash-bin"
cat <<WRAPPER >"$PWD/crash-bin/git"
#!/usr/bin/env bash
if [[ \$(cat "$B/.config/journey/bindings") == 'incoming edit' ]]; then
  kill -KILL "\$(cat "$pidfile")"
  exit 1
fi
exec "$real_git" "\$@"
WRAPPER
chmod +x "$PWD/crash-bin/git"
cat <<WRAPPER >"$PWD/interrupted-pull"
#!/usr/bin/env bash
echo \$\$ >"$pidfile"
export PATH="$PWD/crash-bin:\$PATH"
exec "$b" bootstrap dotfiles pull --yes
WRAPPER
chmod +x "$PWD/interrupted-pull"
printf 'incoming edit\n' >~/.config/journey/bindings
assert_succeed 'mise bootstrap dotfiles sync'
assert_succeed "$b bootstrap dotfiles sync"
assert_fail "$PWD/interrupted-pull"
assert "cat $B/.config/journey/bindings" 'incoming edit'
assert "$b bootstrap dotfiles history --pending --json | jq length" '1'
assert_succeed "$b bootstrap dotfiles save"
assert "cat $B/.config/journey/bindings" 'laptop edit'
assert_succeed "$b bootstrap dotfiles pull --yes"
assert_succeed "$b bootstrap dotfiles undo --yes"
assert "cat $B/.config/journey/bindings" 'laptop edit'

# Fresh-machine bootstrap restores shared state, but not private machine files.
assert_succeed "$c bootstrap --from-git file://$origin --yes --only dotfiles"
assert "cat $C/.config/journey/bindings" 'incoming edit'
assert_fail "test -e $C/.config/journey/monitor"
assert_succeed "$c bootstrap dotfiles rollback $C/.config/journey/bindings --to $initial --yes"
assert "cat $C/.config/journey/bindings" 'initial'
assert_succeed "$c bootstrap dotfiles undo --yes"
assert "cat $C/.config/journey/bindings" 'incoming edit'
assert_fail "test -e $C/.config/mise/config.toml"
assert "git --git-dir=$origin for-each-ref --format='%(refname)' refs/mise-history" ''
