#!/usr/bin/env bash
# crap.sh — local CRAP (Change Risk Anti-Patterns) analysis for review.
#
# cargo-crap is NOT a baraddur dependency. It must be installed separately
# by each developer who wants to run this analysis. See the crate page for
# install instructions and details on what the score means:
#
#     https://crates.io/crates/cargo-crap
#
# This script wraps cargo-crap with defaults tuned for keeping the
# tracked snapshot at `docs/crap-and-code-cov.md` in sync with the
# current source tree:
#   - production code only (tests/ excluded)
#   - full per-function table (no --top cap)
#   - markdown output so it's readable both in a terminal and pasted
#     into a PR comment
#   - written in place to docs/crap-and-code-cov.md
#   - coverage-aware when an `lcov.info` is present at the repo root
#     (generate one with `cargo llvm-cov --lcov --output-path lcov.info`);
#     without coverage every function is scored as 0% covered, which is
#     still useful for spotting complexity hotspots but isn't a true
#     CRAP run.
#
# Any extra args are forwarded to cargo-crap and take precedence over
# the defaults (the last value of a repeated flag wins), so you can
# redirect or trim the report, e.g.:
#     scripts/crap.sh --summary               # overwrites doc with a 1-line summary
#     scripts/crap.sh --output -              # print to stdout instead
#     scripts/crap.sh --top 5 --format json --output crap.json
#     scripts/crap.sh --threshold 50

set -euo pipefail

if ! command -v cargo-crap >/dev/null 2>&1; then
    cat >&2 <<'EOF'
error: cargo-crap is not installed.

This script depends on cargo-crap, which is NOT a baraddur dependency
and must be installed separately. See the crate page for instructions:

    https://crates.io/crates/cargo-crap

Typical install:
    cargo install cargo-crap
EOF
    exit 1
fi

DOC=docs/crap-and-code-cov.md

# Without coverage data, we run a complexity-only report to stderr but
# refuse to overwrite the tracked doc — keeping it bouncing between
# coverage-aware and complexity-only as lcov.info comes and goes would
# churn the working tree. The watch-mode use case (.baraddur.toml) hits
# this branch; `just ci` generates lcov.info first and hits the other.
if [[ ! -f lcov.info ]]; then
    cat >&2 <<'EOF'
note: lcov.info not found — running complexity-only summary to stderr.
      generate one with: cargo llvm-cov --lcov --output-path lcov.info
      (the tracked report at docs/crap-and-code-cov.md is left untouched.)
EOF
    cargo-crap --threshold 30 --exclude 'tests/**' --summary "$@" >&2
    exit 0
fi

TMP=$(mktemp)
trap 'rm -f "$TMP"' EXIT

ARGS=(
    --lcov lcov.info
    --threshold 30
    --format markdown
    --exclude 'tests/**'
    --output "$TMP"
)

cargo-crap "${ARGS[@]}" "$@"

# If the user passed their own --output (so TMP is empty), bail without
# touching the tracked doc — they've redirected the report elsewhere.
[[ -s "$TMP" ]] || exit 0

{
    cat <<'EOF'
# CRAP & Coverage Report

Per-function CRAP score, cyclomatic complexity (CC), and line coverage,
generated by [`cargo-crap`](https://github.com/minikin/cargo-crap) against
LCOV data from [`cargo-llvm-cov`](https://github.com/taiki-e/cargo-llvm-cov).

A snapshot — regenerate with:

```sh
cargo llvm-cov --lcov --output-path lcov.info
scripts/crap.sh
```

The cleanup plan for the remaining flagged functions lives in
[`plans/crap-cleanup.md`](plans/crap-cleanup.md).

EOF
    cat "$TMP"
} > "$DOC"
