# Debtmap - Justfile
# Quick development commands for Rust projects

# Default recipe - show available commands
default:
    @just --list

# Development commands
alias d := dev
alias r := run
alias t := test
alias c := check
alias f := fmt
alias l := lint

# === DEVELOPMENT ===

# Run the project in development mode
dev:
    cargo run

# Run the project with hot reloading
watch:
    cargo watch -x run

# Run the project in release mode
run:
    cargo run --release

# Run with all features enabled
run-all:
    cargo run --all-features

# === BUILDING ===

# Build the project
build:
    cargo build

# Build in release mode
build-release:
    cargo build --release

# Build with optimizations for native CPU
build-native:
    RUSTFLAGS="-C target-cpu=native" cargo build --release

# Clean build artifacts
clean:
    cargo clean

# === TESTING ===

# Run all tests with nextest for faster execution
test:
    @echo "Running tests with cargo nextest..."
    SKIP_INTEGRATION_TESTS=1 cargo nextest run --lib \
        --test analyzer_tests --test complexity_tests --test core_metrics_tests \
        --test debt_tests --test entropy_tests \
        --status-level fail --final-status-level slow

# Run only the integration tests that don't hang
test-safe:
    cargo build
    cargo nextest run --lib
    @echo "Running safe integration tests..."
    @for test in analyzer_tests apply_entropy_dampening_tests bug_documentation_tests \
        call_graph_closure_test call_graph_extraction_test call_graph_improved_test \
        call_graph_resolution_test cognitive_complexity_tests complexity_comparison_test \
        complexity_module_tests complexity_tests context_aware_integration_test \
        context_aware_test core_ast_tests core_cache_tests core_display_tests \
        core_metrics_tests core_monadic_tests core_untested_functions_tests \
        cross_module_call_false_positive_test cross_module_field_access_test \
        cyclomatic_complexity_tests debt_grouping_tests debt_tests \
        debug_real_callgraph_test dependency_and_coupling_tests \
        entropy_integration_tests entropy_tests error_swallowing_test \
        external_api_detection_tests external_api_detector_integration_test \
        false_positive_reproduction_tests fast_unit_tests field_access_chain_test \
        io_walker_tests; do \
        echo "Testing $$test..."; \
        cargo nextest run --test $$test || exit 1; \
    done
    @echo "✅ All safe tests passed!"

# Run tests with output
test-verbose:
    cargo nextest run --nocapture

# Run tests with specific pattern
test-pattern PATTERN:
    cargo nextest run {{PATTERN}}

# Run tests and watch for changes
test-watch:
    cargo watch -x 'nextest run'

# Run fast coverage using the default local test scope
coverage: coverage-fast

# Run fast coverage using cargo-llvm-cov and nextest
coverage-fast:
    #!/usr/bin/env bash
    set -euo pipefail
    # Ensure rustup's cargo is in PATH (needed for llvm-tools-preview)
    export PATH="$HOME/.cargo/bin:$PATH"
    mkdir -p target/coverage
    find target/llvm-cov-target -maxdepth 1 -name '*.profraw' -delete 2>/dev/null || true
    echo "Generating fast HTML coverage report with cargo-llvm-cov nextest..."
    SKIP_INTEGRATION_TESTS=1 cargo llvm-cov nextest --no-clean --html --output-dir target/coverage \
        --lib --test analyzer_tests --test complexity_tests --test core_metrics_tests \
        --test debt_tests --test entropy_tests --status-level fail --final-status-level slow
    echo "Coverage report generated at target/coverage/html/index.html"

# Run tests with coverage (lcov format)
coverage-lcov: coverage-fast-lcov

# Run fast tests with coverage (lcov format)
coverage-fast-lcov:
    #!/usr/bin/env bash
    set -euo pipefail  # Exit on error, undefined variables, and pipe failures
    # Ensure rustup's cargo is in PATH (needed for llvm-tools-preview)
    export PATH="$HOME/.cargo/bin:$PATH"
    # Ensure target/coverage directory exists
    mkdir -p target/coverage
    cargo llvm-cov clean --profraw-only
    # Use the default libtest harness for LCOV: nextest is fast at running tests,
    # but source coverage creates one raw profile per test process, which makes
    # LLVM's final merge/export step dominate this suite.
    echo "Generating LCOV report with cargo-llvm-cov..."
    SKIP_INTEGRATION_TESTS=1 cargo llvm-cov --no-clean --lcov --output-path target/coverage/lcov.info \
        --lib --test analyzer_tests --test complexity_tests --test core_metrics_tests \
        --test debt_tests --test entropy_tests -- --quiet
    echo "Coverage report generated at target/coverage/lcov.info"
    # Verify the file was actually created
    if [ ! -f target/coverage/lcov.info ]; then
        echo "ERROR: Coverage file was not generated at target/coverage/lcov.info"
        exit 1
    fi

# Run tests with coverage and check threshold
coverage-check:
    #!/usr/bin/env bash
    set -euo pipefail
    # Ensure rustup's cargo is in PATH (needed for llvm-tools-preview)
    export PATH="$HOME/.cargo/bin:$PATH"
    mkdir -p target/coverage
    find target/llvm-cov-target -maxdepth 1 -name '*.profraw' -delete 2>/dev/null || true
    echo "Checking fast line coverage threshold..."
    SKIP_INTEGRATION_TESTS=1 cargo llvm-cov nextest --no-clean --json --output-path target/coverage/coverage.json \
        --lib --test analyzer_tests --test complexity_tests --test core_metrics_tests \
        --test debt_tests --test entropy_tests --status-level fail --final-status-level slow
    COVERAGE=$(jq -r '.data[0].totals.lines.percent' target/coverage/coverage.json)
    echo "Current coverage: ${COVERAGE}%"
    if (( $(echo "$COVERAGE < 80" | bc -l) )); then
        echo "⚠️  Coverage is below 80%: $COVERAGE%"
        exit 1
    else
        echo "✅ Coverage meets 80% threshold: $COVERAGE%"
    fi

# Run exhaustive coverage using all feature combinations in the default cargo test harness
coverage-full:
    #!/usr/bin/env bash
    set -euo pipefail
    # Ensure rustup's cargo is in PATH (needed for llvm-tools-preview)
    export PATH="$HOME/.cargo/bin:$PATH"
    echo "Building debtmap binary for integration tests..."
    cargo build --bin debtmap
    echo "Cleaning previous coverage data..."
    cargo llvm-cov clean
    echo "Generating full HTML coverage report with cargo-llvm-cov..."
    cargo llvm-cov --all-features --html --output-dir target/coverage
    echo "Coverage report generated at target/coverage/html/index.html"

# Run exhaustive tests with coverage (lcov format)
coverage-full-lcov:
    #!/usr/bin/env bash
    set -euo pipefail
    # Ensure rustup's cargo is in PATH (needed for llvm-tools-preview)
    export PATH="$HOME/.cargo/bin:$PATH"
    echo "Building debtmap binary for integration tests..."
    cargo build --bin debtmap
    echo "Cleaning previous coverage data..."
    cargo llvm-cov clean
    mkdir -p target/coverage
    echo "Generating full LCOV report with cargo-llvm-cov..."
    cargo llvm-cov --all-features --lcov --output-path target/coverage/lcov.info
    echo "Coverage report generated at target/coverage/lcov.info"
    if [ ! -f target/coverage/lcov.info ]; then
        echo "ERROR: Coverage file was not generated at target/coverage/lcov.info"
        exit 1
    fi

# Run exhaustive tests with coverage and check threshold
coverage-full-check:
    #!/usr/bin/env bash
    set -euo pipefail
    echo "Building debtmap binary for integration tests..."
    cargo build --bin debtmap
    echo "Setting up LLVM tools..."
    RUSTUP_TOOLCHAIN=$(rustup show active-toolchain | cut -d' ' -f1)
    LLVM_DIR=$(rustup which rustc | xargs dirname | xargs dirname)/lib/rustlib/$(rustc -vV | grep host | cut -d' ' -f2)/bin
    export LLVM_PROFDATA="$LLVM_DIR/llvm-profdata"
    export LLVM_COV="$LLVM_DIR/llvm-cov"
    echo "Checking code coverage threshold..."
    cargo llvm-cov clean
    cargo llvm-cov --all-features --json --output-path target/coverage/coverage.json
    COVERAGE=$(cat target/coverage/coverage.json | jq -r '.data[0].totals.lines.percent')
    echo "Current coverage: ${COVERAGE}%"
    if (( $(echo "$COVERAGE < 80" | bc -l) )); then
        echo "⚠️  Coverage is below 80%: $COVERAGE%"
        exit 1
    else
        echo "✅ Coverage meets 80% threshold: $COVERAGE%"
    fi

# Open coverage report in browser
coverage-open: coverage
    open target/coverage/html/index.html

# Analyze the current repository with debtmap using coverage data
analyze-self:
    #!/usr/bin/env bash
    echo "Building debtmap..."
    cargo build --bin debtmap
    echo "Setting up LLVM tools..."
    RUSTUP_TOOLCHAIN=$(rustup show active-toolchain | cut -d' ' -f1)
    LLVM_DIR=$(rustup which rustc | xargs dirname | xargs dirname)/lib/rustlib/$(rustc -vV | grep host | cut -d' ' -f2)/bin
    export LLVM_PROFDATA="$LLVM_DIR/llvm-profdata"
    export LLVM_COV="$LLVM_DIR/llvm-cov"
    echo "Generating code coverage (lcov format)..."
    cargo llvm-cov clean
    cargo llvm-cov --all-features --lcov --output-path target/coverage/lcov.info
    echo "Analyzing current repository with debtmap..."
    ./target/debug/debtmap analyze . --lcov target/coverage/lcov.info -vv
    echo "Analysis complete!"

# Run property-based tests only (if using proptest)
test-prop:
    cargo nextest run prop

# Run integration tests only
test-integration:
    cargo nextest run --test '*'

# Run benchmarks
bench:
    cargo bench

# Run ignored tests (including performance tests)
test-ignored:
    cargo nextest run --run-ignored ignored-only

# Run slow git/context regression tests explicitly
test-slow:
    cargo nextest run --run-ignored ignored-only 'risk::context'

# Run performance tests only
test-perf:
    cargo nextest run --run-ignored ignored-only perf

# Run all tests including ignored ones
test-all:
    cargo nextest run --run-ignored all

# === CODE QUALITY ===

# Format code
fmt:
    cargo fmt

# Check formatting without making changes
fmt-check:
    cargo fmt --check

# Run clippy linter
lint:
    cargo clippy -- -D warnings

# Run clippy with all targets
lint-all:
    cargo clippy --all-targets --all-features -- -D warnings

# Quick check without building
check:
    cargo check

# Check all targets and features
check-all:
    cargo check --all-targets --all-features

# Fix automatically fixable lints
fix:
    cargo fix --allow-dirty

# === DOCUMENTATION ===

# Generate and open documentation
doc:
    cargo doc --open

# Generate documentation for all dependencies
doc-all:
    cargo doc --all --open

# Check documentation for errors
doc-check:
    cargo doc --no-deps

# === DEPENDENCIES ===

# Update dependencies
update:
    cargo update

# Audit dependencies for security vulnerabilities
audit:
    cargo audit

# Check for outdated dependencies
outdated:
    cargo outdated

# Add a new dependency
add CRATE:
    cargo add {{CRATE}}

# Add a development dependency
add-dev CRATE:
    cargo add --dev {{CRATE}}

# Remove a dependency
remove CRATE:
    cargo remove {{CRATE}}

# === UTILITY ===

# Show project tree structure
tree:
    tree -I 'target|node_modules'

# Show git status
status:
    git status

# Create a new module
new-module NAME:
    mkdir -p src/{{NAME}}
    echo "//! {{NAME}} module" > src/{{NAME}}/mod.rs
    echo "pub mod {{NAME}};" >> src/lib.rs

# Create a new integration test
new-test NAME:
    echo "//! Integration test for {{NAME}}" > tests/{{NAME}}.rs

# Create a new example
new-example NAME:
    echo "//! Example: {{NAME}}" > examples/{{NAME}}.rs

# === CI/CD SIMULATION ===

# Run all CI checks locally (matches GitHub Actions)
ci:
    @echo "Running CI checks (matching GitHub Actions)..."
    @echo "Setting environment variables..."
    @export CARGO_TERM_COLOR=always && \
     export CARGO_INCREMENTAL=0 && \
     export RUSTFLAGS="-Dwarnings" && \
     export RUST_BACKTRACE=1 && \
     echo "Running tests..." && \
     cargo nextest run --all-features && \
     echo "Running doc tests..." && \
     cargo test --doc && \
     echo "Running clippy..." && \
     cargo clippy --all-targets --all-features -- -D warnings && \
     echo "Checking formatting..." && \
     cargo fmt --all -- --check && \
     echo "Checking documentation..." && \
     cargo doc --no-deps --document-private-items && \
     echo "All CI checks passed!"

# Run compatibility tests only
test-compatibility:
    cargo nextest run --test compatibility -j 1

# Run performance tests only  
test-performance:
    cargo nextest run --test performance

# Full CI build pipeline (equivalent to scripts/ci-build.sh)
ci-build:
    @echo "Building debtmap..."
    @echo "Checking code formatting..."
    cargo fmt --all -- --check
    @echo "Running clippy..."
    cargo clippy --all-targets --all-features -- -D warnings
    @echo "Building project..."
    cargo build --release
    @echo "Running tests..."
    cargo nextest run --all
    @echo "Building benchmarks..."
    cargo bench --no-run
    @echo "Build successful!"

# Pre-commit hook simulation
pre-commit: fmt lint test
    @echo "Pre-commit checks passed!"

# Full development cycle check
full-check: clean build test lint doc audit
    @echo "Full development cycle completed successfully!"

# === INSTALLATION ===

# Install development tools
install-tools:
    rustup component add rustfmt clippy llvm-tools-preview
    cargo install cargo-watch cargo-llvm-cov cargo-audit cargo-outdated cargo-nextest

# Install additional development tools
install-extras:
    cargo install cargo-expand cargo-machete cargo-deny cargo-udeps

# Install git hooks
install-hooks:
    #!/usr/bin/env bash
    echo "Installing git hooks..."
    for hook in git-hooks/*; do
        if [ -f "$hook" ]; then
            hook_name=$(basename "$hook")
            cp "$hook" ".git/hooks/$hook_name"
            chmod +x ".git/hooks/$hook_name"
            echo "  ✓ Installed $hook_name"
        fi
    done
    echo "Git hooks installed successfully!"

# === RELEASE ===

# Prepare for release (dry run)
release-check:
    cargo publish --dry-run

# Create a new release (requires manual version bump)
release:
    cargo publish

# === ADVANCED ===

# Profile the application
profile:
    #!/usr/bin/env bash
    set -euo pipefail

    profiler=""
    if command -v perf >/dev/null 2>&1; then
        profiler="perf"
    elif [[ "$(uname -s)" == "Darwin" ]]; then
        if command -v samply >/dev/null 2>&1; then
            profiler="samply"
        else
            echo "No supported profiler found for macOS."
            echo "Install samply with: cargo install samply"
            echo "Then rerun: just profile"
            exit 127
        fi
    else
        echo "No supported profiler found."
        echo "Install Linux perf or, on macOS, install samply with: cargo install samply"
        exit 127
    fi

    cargo build --release

    binary="./target/release/$(basename "$PWD")"
    if [[ "$profiler" == "perf" ]]; then
        perf record --call-graph=dwarf "$binary"
        perf report
    elif [[ "$profiler" == "samply" ]]; then
        samply record "$binary"
    fi

# Expand macros for debugging
expand:
    cargo expand

# Find unused dependencies
unused-deps:
    cargo machete

# Security-focused dependency check
security-check:
    cargo deny check

# Find duplicate dependencies
duplicate-deps:
    cargo tree --duplicates

# === HELP ===

# Show detailed help for cargo commands
help:
    @echo "Cargo commands reference:"
    @echo "  cargo run      - Run the project"
    @echo "  cargo test     - Run tests"
    @echo "  cargo build    - Build the project"
    @echo "  cargo fmt      - Format code"
    @echo "  cargo clippy   - Run linter"
    @echo "  cargo check    - Quick syntax check"
    @echo "  cargo doc      - Generate documentation"
    @echo ""
    @echo "Use 'just <command>' for convenience aliases!"
