"""
Practice: compaction and skills (Lab 07, 03_compaction.py and 05_skills.py).

Fill in the TODOs, then run the tests:
    pytest test_session_practice.py        (locally)
or press "Run tests" on the chapter page.
"""
PLACEHOLDER = "[tool output cleared]"
REFUSALS = ("i don't know", "i do not know")


def clear_tool_output(log: list[dict], keep_recent: int = 4) -> list[dict]:
    """The cheapest compaction: no model call.

    Each message is {"role": "user" | "assistant" | "tool", "text": ...}. Return a NEW list where
    every tool message older than the last `keep_recent` messages has its text replaced by
    PLACEHOLDER. Keep the user's and the agent's own messages, and the last `keep_recent`
    messages, exactly as they are. Don't change the input.

    TODO 1
    """
    return log[-keep_recent:]


def missing_sections(summary: str, sections: list[str]) -> list[str]:
    """Check that a structured summary finished: which of the required sections never appear?

    A section counts as present when "<name>:" appears in the summary, ignoring case.

    TODO 2
    """
    return []


def lab_grade(reply: str, expect: list[str]) -> bool:
    """The lab's grader: every expected string appears in the reply (lower case)."""
    return all(e in reply.lower() for e in expect)


def strict_grade(reply: str, expect: list[str]) -> bool:
    """A stricter grader: lab_grade, AND the reply doesn't start with a refusal (REFUSALS),
    after turning curly apostrophes (\\u2019) into straight ones and lower-casing.

    TODO 3
    """
    return lab_grade(reply, expect)


def listing(skills: list[dict]) -> str:
    """What stays in the prompt: one line per skill, "- <name>: <description>", joined with "\\n".

    TODO 4
    """
    return ""


def pick_rate(picks: list[dict], mode: str) -> tuple[int, int]:
    """(right, total): how often the skill picked under `mode` ("good", "vague" or "coded")
    equals the "expected" skill.

    TODO 5
    """
    return 0, len(picks)
