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

BEAGLE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
BIN="$BEAGLE_DIR/bin"

# Pin racket for the whole dispatch tree (incl. bare-shebang racket scripts like
# beagle-syntax) so `beagle <cmd>` is robust outside the direnv shell.
source "$BIN/_beagle-racket"

usage() {
    cat >&2 <<'EOF'
beagle — a typed Clojure subset; one AST → Clojure / ClojureScript /
JavaScript / Nix / Odin (SQL emitter dormant; schema-typing live).

Usage: beagle <command> [args...]

Author:
  syntax FILE               Parse-check (--ledger, --repair --emit-patch)
  check [--profile N] [PATH...]  Type-check without emitting
  validate [FILE...]        Parse + check + schema validation
  build [PATH...]           Compile to target (--out DIR, --warn)
  fix [--dry-run] [PATH...] Surface high-confidence auto-fixes
  repair DIR VERIFY         Evidence-ranked repair (--emit-patch / --auto)
  doctor [--deep]           Is the repair loop online and working?

Query (the compiler is the source of truth):
  sig <fn> <path...>        Typed signature
  fields <record> <path>    Record fields, types, accessors
  callers <fn> <path...>    Call sites
  provides <file>           Exports
  impact <fn> <path...>     Change-impact
  expand <file>             Macro-expanded source
  explain <CODE>            Diagnostic explanation (E001, …)
  explain-type <file>       Inferred types as a view

Project / loop:
  init [--hooks] [--target T]  Bootstrap a project (+ portable repair hooks)
  daemon start|status|stop  Watch + cache type results
  test [--active-only]      Run the test tiers
  rejection-stats DIR       Diagnostics by cause-class
  lsp | repl                LSP server / typed REPL

Deeper dev tools stay as bin/beagle-* (blame, specfix, trace, cascade,
oracle, proptest, muttest, dtrace, smap).
EOF
    exit 1
}

[[ $# -eq 0 ]] && usage

cmd="$1"; shift

case "$cmd" in
    check)
        # Count non-flag args to decide single-file vs batch.
        # --profile takes a value arg, so skip the next arg after it.
        _check_files=()
        _skip_next=false
        for _a in "$@"; do
            if $_skip_next; then
                _skip_next=false
                continue
            fi
            case "$_a" in
                --profile) _skip_next=true ;;
                --*) ;;
                *) _check_files+=("$_a") ;;
            esac
        done
        if [[ ${#_check_files[@]} -eq 1 ]] && [[ -f "${_check_files[0]}" ]]; then
            exec "$BIN/beagle-check" "$@"
        else
            exec "$BIN/beagle-check-all" "$@"
        fi
        ;;
    build)
        if [[ $# -ge 1 ]] && [[ -f "$1" ]] && [[ $# -le 2 ]] && [[ "${2:-}" != --* ]]; then
            exec "$BIN/beagle-build" "$@"
        else
            exec "$BIN/beagle-build-all" "$@"
        fi
        ;;
    fix)
        exec "$BIN/beagle-fix" "$@"
        ;;
    sig)
        exec "$BIN/beagle-sig" "$@"
        ;;
    fields)
        exec "$BIN/beagle-fields" "$@"
        ;;
    expand)
        exec "$BIN/beagle-expand" "$@"
        ;;
    lsp)
        exec "$BIN/beagle-lsp" "$@"
        ;;
    repl)
        exec "$BIN/beagle-repl" "$@"
        ;;
    init)            exec "$BIN/beagle-init" "$@" ;;
    syntax)          exec "$BIN/beagle-syntax" "$@" ;;
    validate)        exec "$BIN/beagle-validate" "$@" ;;
    repair)          exec "$BIN/beagle-repair" "$@" ;;
    doctor)          exec "$BIN/beagle-doctor" "$@" ;;
    callers)         exec "$BIN/beagle-callers" "$@" ;;
    provides)        exec "$BIN/beagle-provides" "$@" ;;
    impact)          exec "$BIN/beagle-impact" "$@" ;;
    explain)         exec "$BIN/beagle-explain" "$@" ;;
    explain-type)    exec "$BIN/beagle-explain-type" "$@" ;;
    daemon)          exec "$BIN/beagle-daemon" "$@" ;;
    test)            exec "$BIN/beagle-test" "$@" ;;
    rejection-stats) exec "$BIN/beagle-rejection-stats" "$@" ;;
    help|--help|-h)
        usage
        ;;
    *)
        echo "beagle: unknown command '$cmd'" >&2
        echo "Run 'beagle help' for usage." >&2
        exit 1
        ;;
esac
