"""
Practice: rules in code that take away one leg of the lethal trifecta. Lab 15's egress.py:
the agent may read private data and text anyone can write, but it may only send to people
the *user* named, and may only delete or cancel when the user asked to.

No model, no score: the same answer every time, whatever the planted note says.

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

EMAIL = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")

# Tool -> the arguments that hold recipients.
OUTBOUND = {
    "send_email": ("recipients", "cc", "bcc"),
    "share_file": ("email",),
    "create_calendar_event": ("participants",),
    "add_calendar_event_participants": ("participants",),
}
# Tool -> the verb the user must have used.
DESTRUCTIVE = {"delete_email": "delete", "delete_file": "delete", "cancel_calendar_event": "cancel"}


def addresses(value) -> set:
    """Every email address in an argument, lowercased, whether it's a list, a string, a list
    written as a string, or None."""
    # TODO: find every address with EMAIL, lowercase it, return a set.
    # Hint: str(value or "") turns a list, a string or None into text you can search.
    raise NotImplementedError


def check(tool: str, args: dict, user_prompt: str, allow_domains: tuple = ()):
    """None if the call may run, otherwise the reason it's blocked."""
    # TODO 1: an OUTBOUND tool. The trusted addresses are the ones in user_prompt. For each
    #   recipient field of this tool, block any address that isn't trusted and doesn't end in
    #   "@" + one of allow_domains (so "a@bluesparrowtech.com.evil.test" doesn't pass).
    #   Reason: f"{tool} to {address}: not an address from the user's request"
    # TODO 2: a DESTRUCTIVE tool. Block it unless its verb ("delete", "cancel") is in the
    #   user's request (case-insensitive).
    #   Reason: f"{tool}: the user didn't ask to {verb} anything"
    # Every other tool (reading, searching, creating files) is allowed: return None.
    raise NotImplementedError


def replay(calls, user_prompt: str, allow_domains: tuple = ()):
    """Run the rules over an agent's tool calls, each a (tool, args) pair, in order.
    Returns the blocked ones as (tool, args, reason)."""
    # TODO: check() each call; collect the blocked ones as (tool, args, reason), in order.
    raise NotImplementedError
