#!/usr/bin/env bash
# dream-test-quality-scan — ad-hoc helper for roll-.dream Scan 7.
#
# Walks bats files and flags ❶-class anti-patterns (hardcoded business data
# in assertion bodies). Emits structured REFACTOR-shaped lines so the
# maintainer can sanity-check the rubric against the current suite without
# waiting for the nightly dream cycle.
#
# Usage:
#   dream-test-quality-scan [--category N] [--path PATH] [--max N]
#   dream-test-quality-scan --help
#
# Only category 1 (❶ hardcoded business data) is implemented as a deterministic
# heuristic; categories ❷..❻ stay with the dream skill (AI agent applies the
# rubric). The helper exists so a smoke test and a maintainer dry-run can
# confirm ❶ detection keeps working as the suite evolves.

set -euo pipefail

CATEGORY=1
TARGET=""
MAX=5

usage() {
  cat <<'EOF'
dream-test-quality-scan — Scan 7 ❶ dry-run helper

Usage:
  dream-test-quality-scan [--category N] [--path PATH] [--max N]
  dream-test-quality-scan --help

Options:
  --category N   Anti-pattern category (only 1 is implemented; default 1)
  --path PATH    File or directory to scan (default: tests/)
  --max N        Maximum entries to emit (default: 5; matches dream skill cap)
  --help         Show this message

Output:
  One line per finding:
    [test-quality:❶] <file>:<line> — <one-line description>
  Exit code is 0 even when nothing is found (dry-run is informational).
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --category) CATEGORY="${2:-1}"; shift 2 ;;
    --path)     TARGET="${2:-}"; shift 2 ;;
    --max)      MAX="${2:-5}"; shift 2 ;;
    --help|-h)  usage; exit 0 ;;
    *)          echo "unknown flag: $1" >&2; usage >&2; exit 2 ;;
  esac
done

if [[ "$CATEGORY" -ne 1 ]]; then
  echo "category $CATEGORY not yet implemented — only ❶ is mechanical" >&2
  exit 0
fi

# Default scan root.
if [[ -z "$TARGET" ]]; then
  repo_root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
  TARGET="${repo_root}/tests"
fi

if [[ ! -e "$TARGET" ]]; then
  echo "path not found: $TARGET" >&2
  exit 2
fi

scan_file() {
  local file="$1"
  # ❶ heuristic — assertion lines whose RHS contains a numeric literal:
  #   - lines containing `[[` or `[ ` (bats assertion syntax)
  #   - AND containing `==` or `=` (equality)
  #   - AND containing a decimal/integer literal of length ≥ 1 inside quotes
  # Emits one entry per file (not per line) to stay under the rate cap.
  local first_hit
  first_hit=$(grep -nE '\[\[.*"[^"]*[0-9]+(\.[0-9]+)?[^"]*"' "$file" 2>/dev/null \
              | head -1 || true)
  [[ -z "$first_hit" ]] && return 1

  local lineno
  lineno=$(echo "$first_hit" | cut -d: -f1)
  local rel
  rel=$(python3 -c "import os,sys; print(os.path.relpath(sys.argv[1]))" "$file" 2>/dev/null || echo "$file")
  printf '[test-quality:❶] %s:%s — assertion body hardcodes a numeric literal that likely owns its value elsewhere\n' \
    "$rel" "$lineno"
  return 0
}

emitted=0
if [[ -d "$TARGET" ]]; then
  # Iterate over .bats files under TARGET; stop after MAX hits.
  # Exclude vendored bats-core helpers — those are framework tests, not ours.
  while IFS= read -r f; do
    case "$f" in
      */tests/helpers/bats-*/*) continue ;;
    esac
    if scan_file "$f"; then
      emitted=$((emitted + 1))
      [[ "$emitted" -ge "$MAX" ]] && break
    fi
  done < <(find "$TARGET" -type f -name '*.bats' | sort)
else
  scan_file "$TARGET" && emitted=1 || true
fi

# Always succeed — dry-run is informational, the dream cycle decides what to do.
exit 0
