from __future__ import annotations

from typing import Mapping

from .provider_registry import get_routing_preferences


class RouterLite:
    """Minimal router with deterministic scoring + session affinity.

    Uses provider registry preferences by default, ensuring single source of
    truth for routing decisions. Custom preferences can be injected for testing.
    """

    def __init__(
        self,
        base_prefs: Mapping[str, float] | None = None,
    ) -> None:
        self.base_prefs = (
            dict(base_prefs) if base_prefs is not None else get_routing_preferences()
        )
        self._session_affinity: dict[str, str] = {}

    def _score(self, provider: str) -> float:
        if provider not in self.base_prefs:
            raise ValueError(
                f"RouterLite has no base preference for provider '{provider}'. "
                "Configure base_prefs explicitly when allowing this provider."
            )
        return float(self.base_prefs[provider])

    def choose(
        self, admissible: list[str], session_id: str | None = None
    ) -> tuple[str, dict[str, float], bool]:
        if not admissible:
            raise ValueError("No admissible providers")

        if session_id and session_id in self._session_affinity:
            p = self._session_affinity[session_id]
            if p in admissible:
                return p, {"session_affinity": 1.0}, True

        scored = sorted(
            ((p, self._score(p)) for p in admissible),
            key=lambda item: (-item[1], item[0]),
        )
        chosen, score = scored[0]
        if session_id:
            self._session_affinity[session_id] = chosen
        return chosen, {"base": score}, False
