#!/usr/bin/env bash
set -euo pipefail

tmp_dir="$(mktemp -d)"
cleanup() {
  rm -rf "$tmp_dir"
}
trap cleanup EXIT

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
agentrail="${repo_dir}/scripts/agentrail"

assert_grep() {
  local pattern="$1"
  local file="$2"
  local message="$3"

  if ! grep -q -- "$pattern" "$file"; then
    echo "$message" >&2
    echo "--- ${file} ---" >&2
    cat "$file" >&2
    exit 1
  fi
}

json_value() {
  local file="$1"
  local expression="$2"

  node - "$file" "$expression" <<'NODE'
const fs = require("fs");
const file = process.argv[2];
const expression = process.argv[3];
const data = JSON.parse(fs.readFileSync(file, "utf8"));
const fn = new Function("data", `"use strict"; return (${expression});`);
const value = fn(data);
if (typeof value === "boolean") {
  console.log(value ? "true" : "false");
} else if (value === null || value === undefined) {
  console.log("");
} else {
  console.log(String(value));
}
NODE
}

fresh_repo="${tmp_dir}/fresh"
mkdir -p "$fresh_repo"
git -C "$fresh_repo" init --quiet
"$agentrail" init --target "$fresh_repo" >"${tmp_dir}/fresh-init.out"

assert_grep "installed: AGENTS.md" "${tmp_dir}/fresh-init.out" "agentrail init did not install expected files in a fresh repo"
assert_grep "updated: .agentrail/state.json" "${tmp_dir}/fresh-init.out" "agentrail init did not write state"

if [[ ! -f "${fresh_repo}/AGENTS.md" || ! -f "${fresh_repo}/.agentrail/state.json" ]]; then
  echo "agentrail init did not install expected AgentRail files" >&2
  exit 1
fi

legacy_repo="${tmp_dir}/legacy"
mkdir -p "${legacy_repo}/docs/agents"
git -C "$legacy_repo" init --quiet
cat >"${legacy_repo}/AGENTS.md" <<'LEGACY'
# Legacy local instructions

Keep this local edit.
LEGACY
cat >"${legacy_repo}/docs/agents/ralph-loop.md" <<'LEGACY'
# Legacy Ralph loop

Keep this old workflow text.
LEGACY

"$agentrail" init --target "$legacy_repo" >"${tmp_dir}/legacy-init.out"

assert_grep "skip existing: AGENTS.md" "${tmp_dir}/legacy-init.out" "legacy init did not preserve existing AGENTS.md"
assert_grep "skip existing: docs/agents/ralph-loop.md" "${tmp_dir}/legacy-init.out" "legacy init did not preserve existing workflow file"
assert_grep "Keep this local edit." "${legacy_repo}/AGENTS.md" "legacy init overwrote local AGENTS.md"

if [[ "$(json_value "${legacy_repo}/.agentrail/state.json" "data.legacyAdopted")" != "true" ]]; then
  echo "legacy init did not record adoption" >&2
  exit 1
fi

"$agentrail" upgrade --target "$legacy_repo" >"${tmp_dir}/legacy-upgrade.out"
assert_grep "locally modified: AGENTS.md" "${tmp_dir}/legacy-upgrade.out" "upgrade did not report adopted AGENTS.md as user-owned"
assert_grep "preserved local: AGENTS.md" "${tmp_dir}/legacy-upgrade.out" "upgrade did not preserve adopted AGENTS.md"
assert_grep "Keep this local edit." "${legacy_repo}/AGENTS.md" "upgrade overwrote adopted AGENTS.md without --force"

upgrade_repo="${tmp_dir}/upgrade"
mkdir -p "$upgrade_repo"
git -C "$upgrade_repo" init --quiet
"$agentrail" init --target "$upgrade_repo" >/dev/null
"$agentrail" init --target "$upgrade_repo" >/dev/null
"$agentrail" upgrade --target "$upgrade_repo" >"${tmp_dir}/noop-upgrade.out"

if [[ "$(json_value "${upgrade_repo}/.agentrail/state.json" "data.managedFiles.find((file) => file.path === 'AGENTS.md')?.installStatus")" != "preserved" ]]; then
  echo "second init did not exercise preserved managed-file state" >&2
  exit 1
fi

rm "${upgrade_repo}/docs/agents/visual-evidence.md"
printf '\nlocal edit\n' >>"${upgrade_repo}/AGENTS.md"
mkdir -p "${upgrade_repo}/scripts"
cat >"${upgrade_repo}/scripts/ralph-loop" <<'LEGACY_SCRIPT'
#!/usr/bin/env bash
echo legacy ralph
LEGACY_SCRIPT
chmod +x "${upgrade_repo}/scripts/ralph-loop"
printf 'stale hidden ralph\n' >"${upgrade_repo}/.agentrail/source/templates/scripts/ralph-loop"
cat >"${upgrade_repo}/docs/agents/issue-tracker.md" <<'LOCAL'
# Local issue tracker instructions

Keep this pre-existing file.
LOCAL

legacy_script_hash="$(node - "${upgrade_repo}/scripts/ralph-loop" <<'NODE'
const fs = require("fs");
const crypto = require("crypto");
console.log(`sha256:${crypto.createHash("sha256").update(fs.readFileSync(process.argv[2])).digest("hex")}`);
NODE
)"

node - "${upgrade_repo}/.agentrail/state.json" "$legacy_script_hash" <<'NODE'
const fs = require("fs");
const statePath = process.argv[2];
const legacyScriptHash = process.argv[3];
const state = JSON.parse(fs.readFileSync(statePath, "utf8"));
state.agentrailVersion = "0.0.0";
state.managedFiles = state.managedFiles.filter((file) => file.path !== "docs/agents/triage-labels.md" && file.path !== "docs/agents/issue-tracker.md");
state.managedFiles = state.managedFiles.filter((file) => file.path !== "docs/agents/skill-registry.json" && file.path !== "skills/frontend-web/SKILL.md");
state.managedFiles.push({
  path: "scripts/ralph-loop",
  source: "templates/scripts/ralph-loop",
  contentHash: legacyScriptHash,
  installStatus: "installed"
});
const ralph = state.managedFiles.find((file) => file.path === "docs/agents/ralph-loop.md");
ralph.contentHash = "sha256:old-package-hash";
const context = state.managedFiles.find((file) => file.path === "CONTEXT.md");
context.contentHash = "sha256:old-package-hash";
fs.writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\n`);
NODE

"$agentrail" upgrade --target "$upgrade_repo" >"${tmp_dir}/upgrade.out"

assert_grep "added: docs/agents/triage-labels.md" "${tmp_dir}/upgrade.out" "upgrade did not report added managed files"
assert_grep "added: docs/agents/skill-registry.json" "${tmp_dir}/upgrade.out" "upgrade did not report the skill registry as an added managed file"
assert_grep "added: skills/frontend-web/SKILL.md" "${tmp_dir}/upgrade.out" "upgrade did not report bundled skill files as added managed files"
assert_grep "changed: docs/agents/ralph-loop.md" "${tmp_dir}/upgrade.out" "upgrade did not report changed package files"
assert_grep "changed: CONTEXT.md" "${tmp_dir}/upgrade.out" "upgrade treated preserved managed file as local edit"
assert_grep "missing: docs/agents/visual-evidence.md" "${tmp_dir}/upgrade.out" "upgrade did not report missing managed files"
assert_grep "locally modified: AGENTS.md" "${tmp_dir}/upgrade.out" "upgrade did not report locally modified files"
assert_grep "preserved local: AGENTS.md" "${tmp_dir}/upgrade.out" "upgrade did not preserve local edits by default"
assert_grep "preserved existing untracked: docs/agents/issue-tracker.md" "${tmp_dir}/upgrade.out" "upgrade did not preserve existing new-path collision"

if ! grep -q -- "Keep this local edit." "${legacy_repo}/AGENTS.md"; then
  echo "legacy edit was unexpectedly changed" >&2
  exit 1
fi

if ! grep -q -- "local edit" "${upgrade_repo}/AGENTS.md"; then
  echo "upgrade overwrote a local modification without --force" >&2
  exit 1
fi

if [[ ! -f "${upgrade_repo}/docs/agents/visual-evidence.md" ]]; then
  echo "upgrade did not restore missing managed file" >&2
  exit 1
fi

if [[ "$(json_value "${upgrade_repo}/.agentrail/state.json" "data.managedFiles.some((file) => file.path === 'scripts/ralph-loop')")" != "false" ]]; then
  echo "upgrade kept legacy raw scripts in managed inventory" >&2
  exit 1
fi

if [[ ! -x "${upgrade_repo}/scripts/ralph-loop" ]]; then
  echo "upgrade deleted legacy raw script instead of leaving migration cleanup to the user" >&2
  exit 1
fi

if grep -q -- "stale hidden ralph" "${upgrade_repo}/.agentrail/source/templates/scripts/ralph-loop"; then
  echo "upgrade did not refresh hidden AgentRail source internals" >&2
  exit 1
fi

if [[ ! -x "${upgrade_repo}/.agentrail/source/templates/scripts/ralph-loop" ]]; then
  echo "upgrade did not preserve executable mode on hidden Ralph helper" >&2
  exit 1
fi

"$agentrail" upgrade --target "$upgrade_repo" >"${tmp_dir}/upgrade-second.out"
if ! grep -q -- "Keep this pre-existing file." "${upgrade_repo}/docs/agents/issue-tracker.md"; then
  echo "second upgrade overwrote a preserved new-path collision" >&2
  exit 1
fi

"$agentrail" upgrade --target "$upgrade_repo" --force >"${tmp_dir}/upgrade-force.out"
assert_grep "forced: AGENTS.md" "${tmp_dir}/upgrade-force.out" "upgrade --force did not report forced local overwrite"

if grep -q -- "local edit" "${upgrade_repo}/AGENTS.md"; then
  echo "upgrade --force did not overwrite local modification" >&2
  exit 1
fi

if ! grep -q -- "npx --package github:Bensigo/agentrail agentrail init" "${repo_dir}/README.md"; then
  echo "README does not document the immediate install path" >&2
  exit 1
fi

echo "upgrade test passed"
