"""
Practice: word error rate from scratch.

WER = (substitutions + deletions + insertions) / number of reference words

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


def edit_counts(ref: list[str], hyp: list[str]) -> tuple[int, int, int]:
    """Line up two word lists with the fewest edits and return (sub, dele, ins).

    Hint: build a table cost[i][j] = fewest edits to turn the first i reference words
    into the first j hypothesis words. Then walk back from cost[n][m] to count
    which edits were used (match/substitute, delete, insert).
    """
    n, m = len(ref), len(hyp)
    cost = [[0] * (m + 1) for _ in range(n + 1)]
    for i in range(1, n + 1):
        cost[i][0] = i  # delete everything
    for j in range(1, m + 1):
        cost[0][j] = j  # insert everything

    # TODO 1: fill in the rest of the table
    # cost[i][j] = min(match or substitute, delete a reference word, insert a hypothesis word)

    # TODO 2: walk back from (n, m) and count sub, dele, ins
    sub = dele = ins = 0
    return sub, dele, ins


def wer(ref: str, hyp: str) -> float:
    """WER for one clip. Texts are already normalized: just split on whitespace.
    An empty reference gives 0.0 for an empty hypothesis, and infinity otherwise."""
    r, h = ref.split(), hyp.split()
    sub, dele, ins = edit_counts(r, h)
    if not r:
        return 0.0 if not h else float("inf")
    return (sub + dele + ins) / len(r)


def corpus_wer(pairs: list[tuple[str, str]]) -> float:
    """Corpus WER over many clips: total errors / total reference words.

    TODO 3: don't average the per-clip WERs. Sum errors and words first.
    """
    return 0.0
