#!/usr/bin/env python3
"""CI guard: fail on undefined-name references (the pyflakes F821 class).

This is the exact bug class behind the case-rename 500 (PR #249): a name
referenced but never imported/defined. It is invisible to tests when it sits
inside a rarely-hit branch or a fire-and-forget ``background_tasks`` callable —
it only NameErrors when that code path runs in production. pyflakes catches it
statically, before merge.

Scope is deliberately narrow — we gate ONLY on undefined names, not on the
other pyflakes findings (unused imports, f-strings without placeholders, unused
locals). Those are style noise, not runtime crashes; gating on them would make
the check too noisy to keep green. Keep this gate high-signal.

Requires pyflakes importable by the running interpreter (the workflow installs
it into a throwaway venv and runs this script with that venv's python).
"""
from __future__ import annotations

import subprocess
import sys

# Paths that ship into the running app / are executed operationally.
TARGETS = ["web", "mcp-server/src", "scripts"]

# pyflakes messages that mean "this reference will NameError at runtime".
FATAL_MARKERS = ("undefined name", "may be undefined")


def main() -> int:
    proc = subprocess.run(
        [sys.executable, "-m", "pyflakes", *TARGETS],
        capture_output=True,
        text=True,
    )
    # pyflakes exits non-zero whenever it has ANY finding; we re-classify so
    # that only the fatal class fails the build.
    lines = (proc.stdout + proc.stderr).splitlines()
    fatal = [ln for ln in lines if any(m in ln for m in FATAL_MARKERS)]

    if fatal:
        print("❌ undefined name(s) detected — these crash at runtime:\n")
        for ln in fatal:
            print(f"   {ln}")
        print(
            f"\n{len(fatal)} undefined-name finding(s). Import or define the "
            "name, or delete the dead reference."
        )
        return 1

    print(f"✓ no undefined names in: {', '.join(TARGETS)}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
