"""One solution to inventory_practice.py. Try the practice file first."""
import re

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:
    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]:
    return set(MODEL_LITERAL.findall(code))


def score(listed, truth):
    t = {canonical(x) for x in truth}
    f = {canonical(x) for x in listed} if listed is not None else set()
    return {"found": len(f & t), "wrong": sorted(f - t), "missed": sorted(t - f)}


def totals(source, key):
    out = {"found": 0, "wrong": 0, "missed": 0}
    for system, truth in key.items():
        s = score(source.get(system), truth)
        out["found"] += s["found"]
        out["wrong"] += len(s["wrong"])
        out["missed"] += len(s["missed"])
    return out


def systems_using(source, model):
    m = canonical(model)
    return sorted(s for s, listed in source.items() if listed and m in {canonical(x) for x in listed})


def is_dated(name):
    return re.search(r"-\d{4}-\d{2}-\d{2}$", name) is not None


def left_for_people(entry):
    return sorted(k for k, v in entry.items() if v in (None, "", []))
