#!/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 "--- output ---" >&2
    cat "$file" >&2
    exit 1
  fi
}

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

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

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

if [[ "$(node - "${fixture}/.agentrail/config.json" <<'NODE'
const fs = require("fs");
const config = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const context = config.context || {};
console.log(Boolean(
  Array.isArray(context.includeGlobs) &&
  Array.isArray(context.excludeGlobs) &&
  Number.isFinite(context.maxFileSizeBytes) &&
  context.skipBinary === true &&
  context.respectGitIgnore === true &&
  context.summary &&
  context.summary.mode === "disabled" &&
  context.summary.provider === null &&
  context.secretRedaction &&
  context.secretRedaction.enabled === true &&
  Array.isArray(context.secretRedaction.denyGlobs)
));
NODE
)" != "true" ]]; then
  echo "installed config does not expose context inventory controls" >&2
  cat "${fixture}/.agentrail/config.json" >&2
  exit 1
fi

mkdir -p \
  "${fixture}/src" \
  "${fixture}/docs/agents" \
  "${fixture}/docs/memory" \
  "${fixture}/docs/prd" \
  "${fixture}/docs/milestones" \
  "${fixture}/skills/backend-api" \
  "${fixture}/.agentrail/context/index" \
  "${fixture}/.agentrail/runs/run-1" \
  "${fixture}/apps/web" \
  "${fixture}/node_modules/pkg" \
  "${fixture}/dist" \
  "${fixture}/ignored"

cat >"${fixture}/src/app.js" <<'JS'
console.log("hello");
JS
cat >"${fixture}/docs/agents/local.md" <<'DOC'
# Local Agent Doc
DOC
cat >"${fixture}/docs/memory/lesson.md" <<'DOC'
# Lesson
DOC
cat >"${fixture}/docs/prd/feature.md" <<'DOC'
# Feature PRD
DOC
cat >"${fixture}/docs/milestones/m1.md" <<'DOC'
# Milestone
DOC
cat >"${fixture}/skills/backend-api/SKILL.md" <<'DOC'
# Backend API
DOC
cat >"${fixture}/.agentrail/runs/run-1/findings.json" <<'JSON'
{"findings":[]}
JSON
cat >"${fixture}/.agentrail/context/index/sources.json" <<'JSON'
[]
JSON
cat >"${fixture}/node_modules/pkg/index.js" <<'JS'
module.exports = {};
JS
cat >"${fixture}/dist/bundle.js" <<'JS'
console.log("built");
JS
cat >"${fixture}/ignored/skip.md" <<'DOC'
# Ignored
DOC
cat >"${fixture}/.env" <<'ENV'
TOKEN=secret
ENV
cat >"${fixture}/apps/web/.env.local" <<'ENV'
TOKEN=secret
ENV
cat >"${fixture}/private.pem" <<'ENV'
PRIVATE KEY
ENV
cat >"${fixture}/nested-secret.txt" <<'ENV'
SECRET
ENV
cat >"${fixture}/API_SECRET.txt" <<'ENV'
SECRET
ENV
cat >"${fixture}/Private.KEY" <<'ENV'
SECRET
ENV
printf 'binary\0file' >"${fixture}/src/image.bin"
cat >"${fixture}/.gitignore" <<'GITIGNORE'
ignored/
GITIGNORE

first="${tmp_dir}/sources-1.out"
second="${tmp_dir}/sources-2.out"
"$agentrail" context sources --target "$fixture" >"$first"
"$agentrail" context sources --target "$fixture" >"$second"

cmp "$first" "$second" >/dev/null || {
  echo "context sources output is not deterministic" >&2
  exit 1
}

assert_grep '"sourceType": "code"' "$first" "repo code file was not listed"
assert_grep '"path": "src/app.js"' "$first" "included repo file missing"
assert_grep '"sourceType": "agent_doc"' "$first" "agent docs were not typed"
assert_grep '"sourceType": "memory"' "$first" "memory docs were not typed"
assert_grep '"sourceType": "prd"' "$first" "PRD docs were not typed"
assert_grep '"sourceType": "milestone"' "$first" "milestone docs were not typed"
assert_grep '"sourceType": "skill"' "$first" "skills were not typed"
assert_grep '"sourceType": "agentrail_state"' "$first" "AgentRail state was not typed"
assert_grep '"sourceType": "run_artifact"' "$first" "run artifacts were not typed"
assert_grep '"contentHash": "sha256:' "$first" "source records did not include content hashes"
assert_grep '"freshness": {' "$first" "source records did not include freshness"
assert_grep '"authority":' "$first" "source records did not include authority"
assert_grep '"visibility": "local"' "$first" "source records did not include visibility"
assert_grep '"linkedIssues": \[\]' "$first" "source records did not include linked issues"
assert_grep '"linkedPullRequests": \[\]' "$first" "source records did not include linked PRs"
assert_grep '"chunkIds": \[\]' "$first" "source records did not include chunk IDs"

assert_not_grep 'node_modules' "$first" "node_modules should be excluded"
assert_not_grep 'dist/bundle.js' "$first" "build output should be excluded"
assert_not_grep 'ignored/skip.md' "$first" "gitignored files should be excluded"
assert_not_grep 'src/image.bin' "$first" "binary files should be excluded"
assert_not_grep '".env"' "$first" "secret-bearing paths should be excluded"
assert_not_grep 'apps/web/.env.local' "$first" "nested env files should be excluded"
assert_not_grep 'private.pem' "$first" "root private keys should be excluded"
assert_not_grep 'nested-secret.txt' "$first" "root secret-looking files should be excluded"
assert_not_grep 'API_SECRET.txt' "$first" "case-varied secret-looking files should be excluded"
assert_not_grep 'Private.KEY' "$first" "case-varied key files should be excluded"
assert_not_grep '.agentrail/context/index/sources.json' "$first" "generated context artifacts should be excluded"
assert_not_grep '".git/' "$first" ".git paths should be excluded"

optional_missing="${tmp_dir}/optional-missing"
mkdir -p "$optional_missing"
git -C "$optional_missing" init --quiet
"$agentrail" install --target "$optional_missing" >"${tmp_dir}/optional-install.out"
rm -rf "${optional_missing}/docs/memory" "${optional_missing}/docs/prd" "${optional_missing}/docs/milestones"
"$agentrail" context sources --target "$optional_missing" >"${tmp_dir}/optional.out"
assert_grep '"path": "CONTEXT.md"' "${tmp_dir}/optional.out" "optional docs fixture did not list required docs"

custom_glob="${tmp_dir}/custom-glob"
mkdir -p "$custom_glob/src/nested" "$custom_glob/docs"
git -C "$custom_glob" init --quiet
"$agentrail" install --target "$custom_glob" >"${tmp_dir}/custom-install.out"
cat >"${custom_glob}/src/app.js" <<'JS'
console.log("top");
JS
cat >"${custom_glob}/src/nested/app.js" <<'JS'
console.log("nested");
JS
cat >"${custom_glob}/docs/README.md" <<'DOC'
# Docs
DOC
node - "${custom_glob}/.agentrail/config.json" <<'NODE'
const fs = require("fs");
const configPath = process.argv[2];
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
config.context.includeGlobs = ["src/**/*.js", "docs/**/*.md"];
config.context.excludeGlobs = [];
fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
NODE
"$agentrail" context sources --target "$custom_glob" >"${tmp_dir}/custom-glob.out"
assert_grep '"path": "src/app.js"' "${tmp_dir}/custom-glob.out" "src/**/*.js should match top-level files"
assert_grep '"path": "src/nested/app.js"' "${tmp_dir}/custom-glob.out" "src/**/*.js should match nested files"
assert_grep '"path": "docs/README.md"' "${tmp_dir}/custom-glob.out" "docs/**/*.md should match top-level files"

malformed="${tmp_dir}/malformed"
mkdir -p "$malformed"
git -C "$malformed" init --quiet
"$agentrail" install --target "$malformed" >"${tmp_dir}/malformed-install.out"
printf '{\n' >"${malformed}/.agentrail/config.json"
if "$agentrail" context sources --target "$malformed" >"${tmp_dir}/malformed.out" 2>&1; then
  echo "context sources accepted malformed .agentrail/config.json" >&2
  exit 1
fi
assert_grep "invalid .agentrail/config.json" "${tmp_dir}/malformed.out" "malformed config should fail closed"

if "$agentrail" context sources --target >"${tmp_dir}/invalid.out" 2>&1; then
  echo "context sources accepted --target without a directory" >&2
  exit 1
fi
assert_grep "--target requires a directory" "${tmp_dir}/invalid.out" "context sources did not reject missing --target value"

echo "context sources test passed"
