#!/usr/bin/env bash
# verify.sh — automate brief Success Criteria SC1-SC7 for the voyage rebrand.
# Bash 3.2 compatible (no associative arrays, no readarray, no |&).
#
# Modes:
#   --quick   (default) artifact-presence + manifest checks; no e2e pipeline run
#   --live    runs examples/01-add-verbose-flag/ pipeline; diffs against baseline

set -u

MODE="quick"
if [ "${1:-}" = "--live" ]; then
  MODE="live"
elif [ "${1:-}" = "--quick" ]; then
  MODE="quick"
elif [ -n "${1:-}" ]; then
  echo "usage: $0 [--quick|--live]" >&2
  exit 2
fi

PASS=0
FAIL=0

pass() { echo "[PASS] SC$1 — $2"; PASS=$((PASS + 1)); }
fail() { echo "[FAIL] SC$1 — $2"; FAIL=$((FAIL + 1)); exit 1; }

# Tracked-file exclusions (paths preserved verbatim from old name).
# - CHANGELOG/TRADEMARKS/MIGRATION legitimately reference the old name.
# - architecture-discovery.mjs + project-discovery.mjs are Q8 exceptions
#   pointing at the upstream architect producer slot.
# - verify.sh self-references the forbidden patterns to detect them.
# - .claude/, .session-state.local.json, *.local.md handled via gitignore.
exclude_path() {
  case "$1" in
    *CHANGELOG.md|*TRADEMARKS.md|*MIGRATION.md) return 0 ;;
    *lib/validators/architecture-discovery.mjs) return 0 ;;
    *lib/parsers/project-discovery.mjs) return 0 ;;
    *verify.sh) return 0 ;;
    *.local.md|*.local.json) return 0 ;;
  esac
  return 1
}

tracked_sources() {
  git ls-files \
    '*.md' '*.mjs' '*.json' '*.sh' '*.yml' '*.yaml' 2>/dev/null
}

# Per-file ultra/-local check.
#
# SC2 uses a refined pattern that matches `/cmd-local` command suffixes
# but NOT the `--local` CLI flag (legitimate `/trekresearch --local` mode).
file_has_forbidden_match() {
  local f="$1" pattern="$2"
  local resolved="$pattern"
  if [ "$pattern" = "-local" ]; then
    resolved='/[a-zA-Z0-9_-]+-local'
  fi
  grep -q -E -- "$resolved" "$f" 2>/dev/null
}

# ---------------- SC1: zero `ultra` references in tracked source files ----------------
sc1_hits=""
while IFS= read -r f; do
  [ -z "$f" ] && continue
  exclude_path "$f" && continue
  [ -f "$f" ] || continue
  if file_has_forbidden_match "$f" "ultra"; then
    sc1_hits="${sc1_hits}${f}
"
  fi
done <<EOF
$(tracked_sources)
EOF

if [ -z "$sc1_hits" ]; then
  pass 1 "no 'ultra' references in tracked source"
else
  echo "    Files with 'ultra':"
  printf '%s' "$sc1_hits" | sed 's/^/      /'
  fail 1 "ultra references remain"
fi

# ---------------- SC2: zero `-local` suffix references ----------------
sc2_hits=""
while IFS= read -r f; do
  [ -z "$f" ] && continue
  exclude_path "$f" && continue
  [ -f "$f" ] || continue
  if file_has_forbidden_match "$f" "-local"; then
    sc2_hits="${sc2_hits}${f}
"
  fi
done <<EOF
$(tracked_sources)
EOF

if [ -z "$sc2_hits" ]; then
  pass 2 "no '-local' suffix in tracked source"
else
  echo "    Files with '-local':"
  printf '%s' "$sc2_hits" | sed 's/^/      /'
  fail 2 "-local references remain"
fi

# ---------------- SC3: all seven trek-commands present and parseable ----------------
sc3_missing=""
for cmd in trekbrief trekresearch trekplan trekexecute trekreview trekcontinue trekendsession; do
  f="commands/${cmd}.md"
  if [ ! -f "$f" ]; then
    sc3_missing="$sc3_missing $cmd:missing"
    continue
  fi
  if ! grep -q "^name: ${cmd}$" "$f"; then
    sc3_missing="$sc3_missing $cmd:bad-frontmatter"
  fi
done

if [ -z "$sc3_missing" ]; then
  pass 3 "all seven /trek* commands present and parseable"
else
  echo "    Issues:$sc3_missing"
  fail 3 "trek command files missing or malformed"
fi

# ---------------- SC4: no legacy ultra*-local.md command files ----------------
legacy_count=$(ls commands/ultra*-local.md 2>/dev/null | wc -l | tr -d ' ')
if [ "$legacy_count" = "0" ]; then
  pass 4 "no legacy commands/ultra*-local.md files"
else
  fail 4 "$legacy_count legacy ultra*-local.md files remain"
fi

# ---------------- SC5: plugin.json name=voyage, version >= 4.0.0 ----------------
manifest=".claude-plugin/plugin.json"
if [ ! -f "$manifest" ]; then
  fail 5 "$manifest not found"
fi

manifest_name=$(grep -E '"name"[[:space:]]*:' "$manifest" | head -1 | sed -E 's/.*"name"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')
manifest_version=$(grep -E '"version"[[:space:]]*:' "$manifest" | head -1 | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')

manifest_ok=1
if [ "$manifest_name" != "voyage" ]; then
  manifest_ok=0
fi
case "$manifest_version" in
  4.*|5.*|6.*|7.*|8.*|9.*) ;;
  *) manifest_ok=0 ;;
esac

if [ "$manifest_ok" = "1" ]; then
  pass 5 "plugin.json reports name=$manifest_name version=$manifest_version"
else
  echo "    Got name=$manifest_name version=$manifest_version (expected name=voyage version>=4.0.0)"
  fail 5 "plugin.json mismatch"
fi

# ---------------- SC6: npm test exits 0 ----------------
if npm test >/tmp/voyage-verify-npm-test.log 2>&1; then
  test_count=$(grep -E '^[^[:alnum:]]*tests[[:space:]]+[0-9]+' /tmp/voyage-verify-npm-test.log | head -1 | grep -oE '[0-9]+' | head -1)
  pass 6 "npm test exits 0 (${test_count:-?} tests)"
else
  echo "    See /tmp/voyage-verify-npm-test.log"
  fail 6 "npm test failed"
fi

# ---------------- SC7: end-to-end smoke ----------------
if [ "$MODE" = "live" ]; then
  if [ ! -d "examples/01-add-verbose-flag" ]; then
    fail 7 "examples/01-add-verbose-flag not found"
  fi
  echo "    --live mode: pipeline run not yet wired (Step 16+ work)"
  pass 7 "examples/01-add-verbose-flag present (live-run TBD)"
else
  if [ -d "examples/01-add-verbose-flag" ] || [ -d "examples" ]; then
    pass 7 "examples/ artifact present (--quick proxy; use --live for pipeline)"
  else
    fail 7 "examples/ directory missing"
  fi
fi

echo ""
echo "=================================================================="
echo "  verify.sh summary: $PASS pass, $FAIL fail (mode: $MODE)"
echo "=================================================================="
exit 0
