#!/usr/bin/env bash
# Verify that an already-installed rolling version is NOT skipped as "already
# installed" when the upstream checksum changes, and IS skipped when unchanged.
#
# Uses a hermetic local vfox plugin fixture so the test is deterministic and
# network-free after the plugin git-init step.

PLUGIN_DIR="$PWD/vfox-rolling"
mkdir -p "$PLUGIN_DIR/hooks"

cat >"$PLUGIN_DIR/metadata.lua" <<'LUA'
PLUGIN = {}
PLUGIN.name = "rolling-test"
PLUGIN.version = "0.1.0"
PLUGIN.homepage = "https://example.com"
PLUGIN.license = "MIT"
PLUGIN.description = "rolling release detection test plugin"
LUA

# available.lua declares nightly as a rolling release with an explicit checksum.
# is_rolling_version_outdated reads this checksum and compares it against the
# value stored on disk from the previous install.
cat >"$PLUGIN_DIR/hooks/available.lua" <<'LUA'
function PLUGIN:Available(ctx)
  return {
    { version = "1.0.0" },
    { version = "nightly", rolling = true, checksum = "sha256:aaa111" },
  }
end
LUA

cat >"$PLUGIN_DIR/hooks/pre_install.lua" <<'LUA'
function PLUGIN:PreInstall(ctx)
  -- No download URL: this is a hermetic fixture.
  return { version = ctx.version }
end
LUA

# post_install.lua writes two things into the install dir:
#   - version.txt  : the "build content" so we can assert which version is live
#   - .mise.checksum: the installed checksum that is_rolling_version_outdated
#                     reads on the next invocation to decide whether to reinstall.
# Normally vfox writes .mise.checksum from result.sha256 after a real download.
# Since this fixture has no download, we write it directly from the hook so the
# checksum baseline is set — mirroring what a real vfox plugin would produce.
cat >"$PLUGIN_DIR/hooks/post_install.lua" <<'LUA'
function PLUGIN:PostInstall(ctx)
  local cmd = require("cmd")
  cmd.exec("printf 'content-v1' > '" .. ctx.rootPath .. "/version.txt'")
  cmd.exec("printf 'sha256:aaa111' > '" .. ctx.rootPath .. "/.mise.checksum'")
end
LUA

cat >"$PLUGIN_DIR/hooks/env_keys.lua" <<'LUA'
function PLUGIN:EnvKeys(ctx)
  return {}
end
LUA

git -C "$PLUGIN_DIR" init -q
git -C "$PLUGIN_DIR" add .
git -C "$PLUGIN_DIR" -c user.name="mise" -c user.email="mise@example.com" commit -q -m "initial plugin"

cat >mise.toml <<EOF
[tools]
"vfox:file://$PLUGIN_DIR" = "nightly"
EOF

# --- step 1: initial install ---
mise install
INSTALL_PATH=$(mise where "vfox:file://$PLUGIN_DIR")
assert "cat '$INSTALL_PATH/version.txt'" "content-v1"

# --- step 2: same checksum → no upgrade needed ---
# mise upgrade --dry-run must produce no "Would install" output when the
# installed checksum already matches the upstream value.
assert_not_contains "mise upgrade --dry-run" "Would install"

# --- step 3: upstream checksum changes → reinstall ---
# Update the plugin so nightly now has a different checksum and different content.
cat >"$PLUGIN_DIR/hooks/available.lua" <<'LUA'
function PLUGIN:Available(ctx)
  return {
    { version = "1.0.0" },
    { version = "nightly", rolling = true, checksum = "sha256:bbb222" },
  }
end
LUA

cat >"$PLUGIN_DIR/hooks/post_install.lua" <<'LUA'
function PLUGIN:PostInstall(ctx)
  local cmd = require("cmd")
  cmd.exec("printf 'content-v2' > '" .. ctx.rootPath .. "/version.txt'")
  cmd.exec("printf 'sha256:bbb222' > '" .. ctx.rootPath .. "/.mise.checksum'")
end
LUA

git -C "$PLUGIN_DIR" add .
git -C "$PLUGIN_DIR" -c user.name="mise" -c user.email="mise@example.com" commit -q -m "bump nightly to v2"

# Refresh the plugin clone from the updated source repo. mise clones file://
# plugins into $MISE_DATA_DIR/plugins/ at first install and does not re-read
# the source dir automatically. Refreshing also busts the version-list cache
# (it uses with_fresh_file on the plugin path) so available.lua is re-executed.
mise plugins update

# Dry-run must report "Would install" after the checksum change. mise upgrade
# detects rolling-version staleness via OutdatedInfo / is_rolling_version_outdated,
# which compares the upstream checksum (available.lua) against the stored one
# (.mise.checksum written by post_install). mise install --dry-run is not used
# here because missing_tools only checks is_version_installed and never reaches
# the rolling_reinstall path for an already-present install dir.
# Note: tv.version == tv.request.version() == "nightly" for this fixture, so the
# test does not distinguish a key mismatch between those two fields.
assert_contains "mise upgrade --dry-run" "Would install"

# mise upgrade detects the checksum change and reinstalls in place.
mise upgrade
assert "cat '$INSTALL_PATH/version.txt'" "content-v2"

# --- step 4: checksum now matches → no further upgrade ---
assert_not_contains "mise upgrade --dry-run" "Would install"
