"""
Practice: build an AI inventory the way Lab 17's script 01 does. Three sources say which models
each system uses (the README read by an AI, a code scanner, records of what ran), and a hand check
of the code is the answer key. You'll write the scanner, score each source against the key, ask
"which systems use this model?", spot a dated model version, and list the registry fields an AI
draft leaves for people.

Fill in the TODOs, then run the tests:
    pytest test_inventory_practice.py        (locally)
or press "Run tests" on the chapter page.
"""
import re

# The lab's scanner pattern: a quoted string that starts like a model name (gpt, tts, whisper, ...),
# or an org/name on Hugging Face with a known model family in it.
MODEL_LITERAL = re.compile(
    r"""["']((?:gpt|o[134]|chatgpt|text-embedding|whisper|tts|claude|gemini)[-\w.]*"""
    r"""|[\w.-]+/[\w.-]*(?:Qwen|Llama|llama|Mistral|mistral|gemma|Gemma|Phi|phi|deberta|bge|MiniLM|e5|SmolLM)[\w.-]*)["']""")


def canonical(name: str) -> str:
    """Compare names the way a reviewer would: lowercase, without an 'openai/' or 'mlx-community/'
    prefix or a 4-bit/8-bit tag, and with 'Qwen3-0.6B' the same as 'Qwen/Qwen3-0.6B'. (Given.)"""
    n = name.strip().lower()
    if not n.startswith("openai/clip"):
        n = n.removeprefix("openai/")
    n = re.sub(r"[-_@](4|8)-?bit$", "", n).removeprefix("mlx-community/")
    return {"qwen3-0.6b": "qwen/qwen3-0.6b", "qwen3-1.7b": "qwen/qwen3-1.7b", "qwen3-4b": "qwen/qwen3-4b",
            "qwen3-8b": "qwen/qwen3-8b"}.get(n, n)


def scan(code: str) -> set[str]:
    """Every model-like string literal in a piece of code (use MODEL_LITERAL)."""
    # TODO
    raise NotImplementedError


def score(listed: list[str] | None, truth: list[str]) -> dict:
    """Score one source for one system against the answer key, comparing canonical names.
    listed is None when the source has no record of this system at all (then it missed everything).
    Return {"found": count listed and right, "wrong": sorted canonical names listed but not in the key,
            "missed": sorted canonical names in the key but not listed}."""
    # TODO
    raise NotImplementedError


def totals(source: dict, key: dict) -> dict:
    """source: system -> list of models (or None); key: system -> list of models.
    Add up score() over every system in the key: {"found": n, "wrong": n, "missed": n}."""
    # TODO
    raise NotImplementedError


def systems_using(source: dict, model: str) -> list[str]:
    """The systems a source says use this model (canonical match), sorted. A model is shutting down:
    which systems break?"""
    # TODO
    raise NotImplementedError


def is_dated(name: str) -> bool:
    """True for a dated model version like 'gpt-5.4-nano-2026-03-17' (ends in -YYYY-MM-DD),
    False for a plain name like 'gpt-5.4-nano', which the provider can point at a new version."""
    # TODO
    raise NotImplementedError


def left_for_people(entry: dict) -> list[str]:
    """The fields of a drafted registry entry that are still empty (None, "" or []), sorted."""
    # TODO
    raise NotImplementedError
