"""档位路由：tier -> 回退链 [(provider, model), ...]（ARCH §4.3/§4.5）。

- `resolve_route(tier)`：单路由（M1 兼容；返回链首）。
- `resolve_chain(tier)`：回退链。默认实现只读全局 `config.tier_defaults`（单元素链）。
  真正的多 provider 回退链由 apps/api 按 DB `tier_routing.fallback` 构造一个
  `ChainResolver` 注入网关（§4.3 三级解析 + §4.5 回退链）。
"""

from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass

from ww_config import get_settings

from .types import Tier


@dataclass(frozen=True)
class Route:
    provider: str
    model: str


# 解析器缝：tier -> 回退链。apps/api 注入据 DB tier_routing 构造的实现。
ChainResolver = Callable[[Tier], "list[Route]"]


def _parse_spec(spec: str) -> Route:
    provider, sep, model = spec.partition(":")
    if not sep or not provider or not model:
        raise ValueError(f"invalid tier route {spec!r}; expected 'provider:model'")
    return Route(provider=provider, model=model)


def resolve_route(tier: Tier) -> Route:
    spec = get_settings().tier_defaults.get(tier)
    if not spec:
        raise ValueError(f"no tier_defaults entry for tier={tier!r}")
    return _parse_spec(spec)


def resolve_chain(tier: Tier) -> list[Route]:
    """默认链解析：仅全局默认（单元素）。多 provider 回退由注入的 `ChainResolver` 提供。"""
    return [resolve_route(tier)]


def chain_from_routing(tier: Tier, primary: str, fallback: list[str]) -> list[Route]:
    """据 DB `tier_routing` 行（primary `provider:model` + fallback 列表）构造回退链。

    供 apps/api 包成 `ChainResolver` 注入网关；放这里以便单测覆盖解析逻辑。
    去重保序：同一 (provider, model) 只保留首次出现。
    """
    routes: list[Route] = [_parse_spec(primary)]
    routes.extend(_parse_spec(s) for s in fallback)
    seen: set[tuple[str, str]] = set()
    unique: list[Route] = []
    for r in routes:
        key = (r.provider, r.model)
        if key not in seen:
            seen.add(key)
            unique.append(r)
    return unique
