# Colors and formatting
bold    := `tput bold 2>/dev/null || true`
green   := `tput setaf 2 2>/dev/null || true`
red     := `tput setaf 1 2>/dev/null || true`
reset   := `tput sgr0 2>/dev/null || true`

success := bold + green + "✔︎ "
err     := bold + red + "❌ "

# List available recipes
default:
    @just --list

# Run all lints
lint:
    @echo "Linting and formatting..."
    @uv run ruff format src/ tests/
    @uv run ruff check --fix src/ tests/
    @uv run ty check src/ tests/
    @uv run ruff format --extension py.snap:python tests/snapshots/*.py.snap
    @uv run ruff check --fix --extension py.snap:python tests/snapshots/*.py.snap
    just _ty-check-snaps
    just _biome-check-snaps
    just lint-example
    @echo "{{success}}Lint complete{{reset}}"

# Run tests
test:
    #!/usr/bin/env bash
    set -euo pipefail
    echo "Running tests..."
    uv run pytest
    echo "{{success}}Tests passed{{reset}}"

# Run all pre-commit checks (lint + test), auto-stage mechanical fixes
precommit:
    #!/usr/bin/env bash
    echo "Running pre-commit checks..."
    tmpfile=$(mktemp)
    staged_list=$(mktemp)
    trap 'rm -f "$tmpfile" "$staged_list"' EXIT
    git diff --cached --name-only -z --diff-filter=d > "$staged_list"
    (
        set -e
        just _lint-justfile
        just _check-lock
        just lint
        xargs -r -0 git add < "$staged_list"
        just test
    ) > "$tmpfile" 2>&1
    status=$?
    if [ $status -ne 0 ]; then
        cat "$tmpfile"
        exit $status
    fi
    echo "{{success}}All pre-commit checks passed{{reset}}"

# Lint and type-check the example project
lint-example:
    @echo "Linting example project..."
    @uv run ruff format example/gcloud_run_project/
    @uv run ruff check --fix example/gcloud_run_project/
    @uv --directory example/gcloud_run_project run --with ty ty check .
    @npx biome check --write example/vite_app/
    @echo "{{success}}Example lint complete{{reset}}"

# Regenerate the example project's pre-committed generated files
example-codegen:
    #!/usr/bin/env bash
    set -euo pipefail
    cd example/
    uv run vs parse-test --quiet
    uv run vs codegen
    echo "{{success}}example-codegen complete{{reset}}"

# [private] Format and lint TypeScript snapshots via temp .ts copies (biome doesn't recognise .ts.snap)
_biome-check-snaps:
    #!/usr/bin/env bash
    set -euo pipefail
    tmpdir=$(mktemp -d)
    trap 'rm -rf "$tmpdir"' EXIT
    for snap in tests/snapshots/*.ts.snap; do
        base=$(basename "$snap" .ts.snap)
        cp "$snap" "$tmpdir/${base}.ts"
    done
    npx biome check "$tmpdir/"

# [private] Type-check Python snapshots via temp .py copies (ty doesn't support --extension)
_ty-check-snaps:
    #!/usr/bin/env bash
    set -euo pipefail
    tmpdir=$(mktemp -d)
    trap 'rm -rf "$tmpdir"' EXIT
    for snap in tests/snapshots/*.py.snap; do
        base=$(basename "$snap" .py.snap)
        cp "$snap" "$tmpdir/${base}.py"
    done
    uv run ty check "$tmpdir/"

# [private] Verify uv.lock and package-lock.json are up to date
_check-lock:
    #!/usr/bin/env bash
    set -euo pipefail
    uv lock --check
    just _check-npm-lock

# [private] Verify .npmrc safety settings and package-lock.json is in sync
_check-npm-lock:
    #!/usr/bin/env bash
    set -euo pipefail
    grep -q "ignore-scripts=true" .npmrc || { echo "{{err}}.npmrc must contain ignore-scripts=true{{reset}}"; exit 1; }
    grep -q "min-release-age=3" .npmrc || { echo "{{err}}.npmrc must contain min-release-age=3{{reset}}"; exit 1; }
    grep -q "allow-git=none" .npmrc || { echo "{{err}}.npmrc must contain allow-git=none{{reset}}"; exit 1; }
    npm install --package-lock-only
    git --no-pager diff --exit-code package-lock.json || { echo "{{err}}package-lock.json is out of sync with package.json{{reset}}"; exit 1; }

# [private] Ensure Justfile recipes don't use && chains (which suppress set -e)
_lint-justfile:
    #!/usr/bin/env bash
    set -euo pipefail
    violations=$(awk '
        /^[[:space:]]+#!/ { in_shebang = 1 }
        /^[^[:space:]]/ && NF > 0 { in_shebang = 0 }
        !in_shebang && /&&/ && !/^[[:space:]]*#/ { print NR": "$0 }
    ' justfile)
    if [[ -n "$violations" ]]; then
        echo "{{err}}justfile recipes must not use && chains. Use separate lines for reliable error reporting.{{reset}}"
        echo "$violations"
        exit 1
    fi
