"""Capability introspection for adapters.

registry.resolve_adapter() already raises ProviderCapabilityError on
unsupported-capability-without-exception — this module provides:

  - explain_capability(model_id, capability) -> dict
    For CLI/UI display: which providers support what, current route.
  - validate_strategy(strategy) -> list[str]
    For test_provider_capability.py: ensures provider_strategy.json
    declares a routable combination for each (model, capability).
  - supported_providers(model_id, capability) -> list[str]
    Already present in registry — re-exported here as a stable
    public surface for consumers.
"""

from __future__ import annotations

from typing import Iterable

from recoil.execution.providers.base import CAPABILITY_KEYS, ProviderAdapter
from recoil.execution.providers.registry import list_adapters, load_strategy


def supported_providers(model_id: str, capability: str) -> list[str]:
    out: list[str] = []
    for a in list_adapters():
        if model_id in a.supported_models and a.capabilities.get(capability, False):
            out.append(a.provider_id)
    return out


def explain_capability(model_id: str, capability: str) -> dict:
    strategy = load_strategy().get(model_id, {}) or {}
    route = strategy.get("capability_exceptions", {}).get(capability) \
        or strategy.get("primary")
    return {
        "model_id": model_id,
        "capability": capability,
        "route": route,
        "supported_providers": supported_providers(model_id, capability),
        "primary": strategy.get("primary"),
        "fallback": strategy.get("fallback"),
    }


def validate_strategy(strategy: dict) -> list[str]:
    """Return list of human-readable problem strings. Empty list = OK."""
    problems: list[str] = []
    adapters = {a.provider_id: a for a in list_adapters()}
    for model_id, entry in strategy.items():
        if model_id.startswith("__") or model_id == "schema_version":
            continue  # skip metadata keys (legacy __version__, schema_version)
        if not isinstance(entry, dict):
            continue
        primary = entry.get("primary")
        if primary and primary not in adapters:
            problems.append(f"{model_id}: primary '{primary}' has no adapter module")
        fb = entry.get("fallback")
        if fb and fb not in adapters:
            problems.append(f"{model_id}: fallback '{fb}' has no adapter module")
        for cap, pid in (entry.get("capability_exceptions") or {}).items():
            if cap not in CAPABILITY_KEYS:
                problems.append(f"{model_id}: exception capability '{cap}' is not in CAPABILITY_KEYS")
            if pid not in adapters:
                problems.append(f"{model_id}: exception routes to '{pid}' with no adapter module")
            elif pid in adapters and not adapters[pid].capabilities.get(cap, False):
                problems.append(
                    f"{model_id}: exception routes '{cap}' to '{pid}' which does not support it"
                )
    return problems


__all__ = ["explain_capability", "supported_providers", "validate_strategy"]
