"""
Practice: answer "why did the assistant say that?" the way Lab 16's script 04 does. An audit log
entry keeps three things: the dated model that answered, the answer itself, and a fingerprint
(hash) of every page the model was shown. You'll compute a page's fingerprint, count what replays
repeat, find the logged answers an edit touched, and name the suspect for one changed answer.

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


def canonical(obj) -> bytes:
    """The same object always gives the same bytes: keys sorted, no spaces, text kept as UTF-8."""
    return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode()


def doc_hash(doc: dict) -> str:
    """A page's fingerprint: SHA-256 of canonical({"title", "text", "groups"}), first 16 hex digits.
    The groups are in it too: a page whose permissions changed is a different page."""
    # TODO
    raise NotImplementedError


def replay_counts(groups: list[dict]) -> dict:
    """Each group is one logged request asked again: {"texts": [logged, r1, ..., r5], "facts": [...]}.
    texts[0] and facts[0] are the logged answer and whether it gave the expected fact.
    Count, over the replays (texts[1:]), compared with the logged answer:
      n          replays in total
      same_text  replays identical to the logged text, word for word
      all_same   requests whose replays are all identical to the logged text
      same_fact  replays that gave the fact, or left it out, the same way as the logged answer"""
    # TODO
    raise NotImplementedError


def shown_an_edited_page(shown: list[list[str]], old: dict, new: dict) -> int:
    """shown: the page ids each logged answer was shown. old / new: page id -> fingerprint, at
    logging time and today. How many logged answers were shown at least one page that changed?"""
    # TODO
    raise NotImplementedError


def diagnose(entry: dict, reply_model: str, hashes_now: dict) -> dict:
    """entry: a log entry with "model_returned" (the dated version that answered) and "doc_hashes"
    (page id -> fingerprint, as logged). reply_model: the dated version named by a reply today.
    Return {"model_changed": bool, "pages_changed": sorted ids whose fingerprint differs today}."""
    # TODO
    raise NotImplementedError


def changed_facts(rows: list[list]) -> dict:
    """rows: [target page id, gave the fact then, gives it now] for each logged answer that was shown
    an edited page and asked again today. Return {target: count} for the answers whose fact changed."""
    # TODO
    raise NotImplementedError
