#!/usr/bin/env bash
#
# CLI end-to-end test: builds the lispsearch executable (if missing) and exercises
# every subcommand end to end against throwaway databases. Hits the network for
# the catalog and for enriching a few systems (kept small with --limit 3).
#
# This is the compiled-binary test. The Lisp unit/integration tests use Parachute:
#   (asdf:test-system "lispsearch")            # offline suite
#   (parachute:test 'lispsearch/test:network)  # network suite
#
# Run from the project root:  test/m4-cli.sh
set -u
cd "$(dirname "$0")/.."

BIN=./lispsearch
fail=0
ok()   { printf 'ok   %s\n' "$1"; }
bad()  { printf 'FAIL %s\n' "$1"; fail=$((fail+1)); }
check(){ if eval "$2"; then ok "$1"; else bad "$1"; fi; }

# --- build if needed ---------------------------------------------------------
if [ ! -x "$BIN" ]; then
  echo "building $BIN ..."
  sbcl --script <<'LISP'
(require :asdf)
(load (merge-pathnames ".local/share/ocicl/ocicl-runtime.lisp" (user-homedir-pathname)))
(asdf:load-asd (truename "lispsearch.asd"))
(handler-bind ((warning #'muffle-warning)) (asdf:load-system "lispsearch"))
(asdf:operate 'asdf:program-op "lispsearch" :force t)
LISP
fi
check "executable built" "[ -x $BIN ]"

SMALL=$(mktemp -u /tmp/ls-m4-small.XXXX.db)
FULL=$(mktemp -u /tmp/ls-m4-full.XXXX.db)
trap 'rm -f "$SMALL"* "$FULL"*' EXIT

# --- top-level / help --------------------------------------------------------
check "--help lists subcommands" "$BIN --help 2>&1 | grep -q 'search'"

# --- index (Tier-1 + enrich a small slice) -----------------------------------
out=$($BIN --db "$SMALL" index --limit 3 --jobs 3 2>&1)
check "index --limit 3 enriches 3" "echo \"$out\" | grep -q 'enriched 3'"
check "stats: 3 systems"   "$BIN --db \"$SMALL\" stats | grep -qE 'systems:[[:space:]]+3'"
check "stats: 3 enriched"  "$BIN --db \"$SMALL\" stats | grep -qE 'enriched:[[:space:]]+3'"

# --- show (text + json) ------------------------------------------------------
check "show 1am has description" "$BIN --db \"$SMALL\" show 1am | grep -qi 'testing framework'"
check "show 1am has install hint" "$BIN --db \"$SMALL\" show 1am | grep -q 'ocicl install 1am'"
check "show --json is valid json" "$BIN --db \"$SMALL\" show 1am --json | grep -q '\"system-name\": \"1am\"'"

# --- search (fts text + json) ------------------------------------------------
check "search 3b finds 3b-bmfont" "$BIN --db \"$SMALL\" search 3b --limit 5 | grep -q '3b-bmfont'"
check "search prints install hint" "$BIN --db \"$SMALL\" search 3b --limit 5 | grep -q 'ocicl install'"
check "search --json array of objects" "$BIN --db \"$SMALL\" search 3b --json --limit 2 | grep -q '\"name\": \"3b-bmfont\"'"

# --- dependency-graph queries (deps / rdeps) ---------------------------------
# (deps/rdeps query logic is covered deterministically in test/stretch.lisp;
# here we just check the CLI is wired up and its error paths behave.)
check "--help lists deps"  "$BIN --help 2>&1 | grep -q '^  deps'"
check "--help lists rdeps" "$BIN --help 2>&1 | grep -q '^  rdeps'"

# --- enrichment-source options (on index/refresh, not global) ----------------
check "index --help lists --registry"    "$BIN index --help 2>&1 | grep -q -- '--registry'"
check "index --help lists --catalog-url" "$BIN index --help 2>&1 | grep -q -- '--catalog-url'"
check "registry is NOT a top-level option" "! $BIN --help 2>&1 | grep -q -- '--registry'"

# --- error paths -------------------------------------------------------------
$BIN --db "$SMALL" show definitely-not-a-system >/dev/null 2>&1
check "show missing -> exit 1" "[ $? -eq 1 ]"
$BIN --db "$SMALL" search >/dev/null 2>&1
check "search no-query -> exit 2" "[ $? -eq 2 ]"
$BIN --db "$SMALL" deps definitely-not-a-system >/dev/null 2>&1
check "deps missing -> exit 1" "[ $? -eq 1 ]"
$BIN --db "$SMALL" deps >/dev/null 2>&1
check "deps no-NAME -> exit 2" "[ $? -eq 2 ]"
$BIN --db "$SMALL" rdeps >/dev/null 2>&1
check "rdeps no-NAME -> exit 2" "[ $? -eq 2 ]"

# --- full Tier-1 catalog + name search ---------------------------------------
out=$($BIN --db "$FULL" index --no-enrich 2>&1)
check "full index loads >2000" "echo \"$out\" | grep -qE 'Loaded [0-9]{4,}'"
check "names: trivial-features present" \
  "$BIN --db \"$FULL\" search trivial --names-only --limit 200 | grep -qx 'trivial-features'"

# NOTE: 'refresh' is intentionally not run here — it reloads the full catalog and
# enriches every pending row (the one heavy operation). Its pieces (load-catalog,
# enrich-rows) are covered by M2/M3 and the index test above.

echo
if [ "$fail" -eq 0 ]; then echo "==== ALL M4 CHECKS PASSED ===="; else echo "==== $fail CHECK(S) FAILED ===="; fi
exit $([ "$fail" -eq 0 ] && echo 0 || echo 1)
