"""Adapter lookup by name, so a third coding agent needs no state machine change.

ponytail: a module dict, not a plugin system. Entry-point scanning buys nothing
until adapters ship from separate distributions.
"""

from __future__ import annotations

from typing import Any, Callable

from .adapters.base import AgentAdapter

_FACTORIES: dict[str, Callable[..., AgentAdapter]] = {}


class UnknownAdapter(KeyError):
    pass


def register(name: str, factory: Callable[..., AgentAdapter]) -> None:
    _FACTORIES[name] = factory


def available() -> list[str]:
    return sorted(_FACTORIES)


def build(name: str, **options: Any) -> AgentAdapter:
    try:
        factory = _FACTORIES[name]
    except KeyError as error:
        raise UnknownAdapter(f"{name!r} is not registered; available: {', '.join(available())}") from error
    return factory(**options)


def _register_builtins() -> None:
    from .adapters.app_server import CodexAppServerAdapter
    from .adapters.claude import ClaudeAdapter
    from .adapters.claude_sdk import ClaudeSDKAdapter
    from .adapters.codex import CodexAdapter
    from .adapters.fake import FakeAgentAdapter

    register("codex", CodexAdapter)
    register("codex-app-server", CodexAppServerAdapter)
    register("claude", ClaudeAdapter)
    register("claude-sdk", ClaudeSDKAdapter)
    register("fake", lambda responses=None, **_: FakeAgentAdapter(responses or {}))


_register_builtins()
