"""
Practice: read the hidden bill and pick the effort level (Lab 02, Scripts 1-3).

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

# The lab's prices for gpt-5.4-nano, in USD per million tokens.
PRICES = {"input": 0.20, "output": 1.25}
EFFORTS = ["none", "low", "medium", "high", "xhigh"]


def split_output(usage: dict) -> tuple[int, int, float]:
    """`usage` is the response's usage block, as the API returns it:
        {"prompt_tokens": 56, "completion_tokens": 477,
         "completion_tokens_details": {"reasoning_tokens": 464}}
    completion_tokens counts the visible answer AND the hidden reasoning. The details block can be
    missing (or its reasoning_tokens None) when the model didn't think: count that as 0.

    Return (visible, hidden, hidden_share), where hidden_share = hidden / completion_tokens
    (0.0 if there were no output tokens).

    TODO 1
    """
    return 0, 0, 0.0


def call_cost(usage: dict, prices: dict = PRICES) -> float:
    """Dollar cost of one call: input tokens at the input price, and ALL output tokens (visible and
    hidden) at the output price. Prices are per million tokens.

    TODO 2
    """
    return 0.0


def per_thousand(total_cost: float, questions: int) -> float:
    """Cost per 1,000 questions, from the total cost of a test over `questions` questions.

    TODO 3
    """
    return total_cost


def lowest_effort(scores: dict[str, list[int]], bar: int) -> str | None:
    """`scores` maps an effort level to its number of right answers in each run, e.g.
    {"none": [6, 9, 7], "low": [8, 9, 9], ...}. Return the lowest level (in EFFORTS order) that
    clears the bar (right >= bar) in EVERY run, or None if no level does. Levels missing from
    `scores` are skipped.

    TODO 4
    """
    return "none"
