"""
Solution: what crosses a handoff. Lab 10's three ways to pass a case to the next agent
(agents.run_team, context="note" | "full" | "text"), its labelled log (agents.render_log), and the
counts the chapter uses: repeated lookups, "answered at once" after a handoff, and ping-pong.
"""
import json

READS = {"find_customer", "get_customer", "list_orders", "get_order", "track_shipment", "search_products",
         "check_stock", "get_refunds"}


def render_log(agent: str, messages: list[dict]) -> list[str]:
    lines = []
    for m in messages:
        if m["role"] == "assistant":
            for c in m.get("tool_calls") or []:
                lines.append(f"[{agent}] called {c['function']['name']}({c['function']['arguments']})")
            if m.get("content"):
                lines.append(f"[{agent}] replied to the customer: {m['content']}")
        elif m["role"] == "tool":
            lines.append(f"    → {m['content'][:600]}")
    return lines


def next_input(mode: str, system: str, customer: str, transcript: list[dict], log: list[str],
               note_from: str, note: str) -> list[dict]:
    if mode == "full":
        return [{"role": "system", "content": system}] + list(transcript)
    body = customer
    if mode == "text" and log:
        body += "\n\nWhat the team has done so far (you are taking over):\n" + "\n".join(log)
    body += f"\n\nHandoff note from the {note_from} agent: {note}"
    return [{"role": "system", "content": system}, {"role": "user", "content": body}]


def repeated_lookups(steps: list[dict]) -> int:
    seen, dup = set(), 0
    for s in steps:
        if s.get("tool") not in READS or s.get("status") != "ok":
            continue
        key = (s["tool"], json.dumps(s.get("args") or {}, sort_keys=True))
        if key in seen:
            dup += 1
        seen.add(key)
    return dup


def answered_at_once(runs: list[dict]) -> tuple[int, int, int]:
    handed = [r for r in runs if r["handoffs"] > 0]
    lazy = [r for r in handed if r["last_turns"] == 1]
    return len(handed), len(lazy), sum(not r["success"] for r in lazy)


def ping_pong(path: list[str]) -> int:
    return sum(1 for i in range(2, len(path)) if path[i] == path[i - 2] and path[i] != path[i - 1])
