"""Solution for the chapter 7 embedding-search exercise."""

from math import sqrt


def cosine(a: list[float], b: list[float]) -> float:
    if len(a) != len(b):
        raise ValueError("vectors must have the same length")
    dot = sum(x * y for x, y in zip(a, b))
    na = sqrt(sum(x * x for x in a))
    nb = sqrt(sum(y * y for y in b))
    return dot / (na * nb) if na and nb else 0.0


def rank(query: list[float], entries: list[tuple[str, list[float]]]) -> list[str]:
    return [label for label, _ in sorted(entries, key=lambda x: cosine(query, x[1]), reverse=True)]


def gate(score: float, cutoff: float) -> str:
    return "answer" if score >= cutoff else "handoff"


def cutoff_report(cases: list[tuple[float, bool]], cutoff: float) -> dict[str, int]:
    """Tally a cutoff over recorded top scores: (score, should_answer)."""
    return {
        "kept": sum(1 for s, ok in cases if ok and s >= cutoff),
        "stopped": sum(1 for s, ok in cases if not ok and s < cutoff),
        "false_handoffs": sum(1 for s, ok in cases if ok and s < cutoff),
    }
