"""Solution for the MCP test-automation practice."""

OK, AUTH_REQUIRED, TOOL_ERROR = 0, 3, 5


def smoke(checks: list[tuple[str, int, int]]) -> tuple[int, list[str]]:
    lines, failed = [], 0
    for name, expected, actual in checks:
        if actual == expected:
            lines.append(f"✓ {name}")
        else:
            failed += 1
            lines.append(f"✗ {name} (exit {actual}, expected {expected})")
    lines.append(f"{len(checks) - failed} passed, {failed} failed")
    return (1 if failed else 0), lines


def eval_gate(turns_by_model: dict[str, list[bool]], gate: float = 0.95) -> tuple[int, str]:
    for model, turns in turns_by_model.items():
        if not turns:
            return 2, f"eval failed: no turns for {model}"
    if not turns_by_model:
        return 2, "eval failed: no models"
    weakest = min(sum(t) / len(t) for t in turns_by_model.values())
    r, g = round(weakest * 100), round(gate * 100)
    if weakest >= gate:
        return 0, f"gate: weakest model {r}% ≥ {g}% → PASS"
    return 1, f"gate: weakest model {r}% < {g}% → BLOCK RELEASE"


def suites_for(trigger: str) -> list[str]:
    return {"commit": ["contract", "scorer"], "deploy": ["smoke"],
            "release": ["contract", "scorer", "tool-use eval"]}.get(trigger, [])


def release_decision(exits: dict[str, int]) -> tuple[str, list[str]]:
    reasons = [f"{s} didn't run" for s in suites_for("release") if s not in exits]
    if exits.get("contract", 0) != 0:
        reasons.append("contract tests failed: a real bug")
    if exits.get("scorer", 0) != 0:
        reasons.append("scorer tests failed: the eval can't be trusted")
    if exits.get("tool-use eval") == 1:
        reasons.append("tool-use gate: weakest model below threshold")
    if exits.get("tool-use eval") == 2:
        reasons.append("tool-use eval didn't complete: no verdict")
    return ("block" if reasons else "ship"), reasons
