"""Fake provider stubs for BDD and benchmark tests.

These lightweight stand-ins avoid importing the real ``ProviderInfo`` (which
pulls in heavy dependencies) while satisfying ``ActorRegistry``'s duck-typed
contract for provider discovery.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any
from unittest.mock import MagicMock

from cleveragents.actor.registry import ActorRegistry
from cleveragents.domain.models.core.actor import Actor
from cleveragents.providers.registry import ProviderCapabilities


@dataclass
class FakeProviderInfo:
    """Minimal stand-in for ``ProviderInfo``."""

    name: str
    default_model: str
    provider_type: Any = None
    capabilities: Any = None
    api_key_env_var: str = ""

    def __post_init__(self) -> None:
        if self.provider_type is None:
            self.provider_type = MagicMock(value=self.name)
        if self.capabilities is None:
            self.capabilities = ProviderCapabilities()


@dataclass
class FakeProviderRegistry:
    """Stand-in for ``ProviderRegistry``."""

    providers: list[FakeProviderInfo] = field(default_factory=list)

    def get_configured_providers(self) -> list[FakeProviderInfo]:
        return self.providers


def make_registry(
    providers: list[FakeProviderInfo] | None = None,
) -> tuple[MagicMock, ActorRegistry]:
    """Build a real ``ActorRegistry`` with mocked service/settings.

    The ``ActorService`` is mocked so there is no database dependency, but
    the ``ActorRegistry`` code (including ``_actor_name()``) runs for real.

    Actors successfully created by ``upsert_actor`` are captured so that
    ``list_actors`` returns them — ensuring Scenario 3 ("valid JSON") can
    detect when the bug is actually fixed.
    """
    provider_reg = FakeProviderRegistry(providers=providers or [])

    captured_actors: list[Actor] = []

    def _capturing_upsert(**kwargs: Any) -> Actor:
        actor = Actor(
            name=kwargs.get("name", "mock/actor"),
            provider=kwargs.get("provider", "mock"),
            model=kwargs.get("model", "actor"),
            config_blob={},
            config_hash=Actor.compute_hash({}),
        )
        captured_actors.append(actor)
        return actor

    mock_service = MagicMock()
    mock_service.list_actors.side_effect = lambda: list(captured_actors)
    mock_service.get_default_actor.return_value = None
    mock_service.upsert_actor.side_effect = _capturing_upsert

    mock_settings = MagicMock()
    mock_settings.resolve_provider_defaults.return_value = MagicMock(
        provider=None, model=None
    )

    registry = ActorRegistry(
        actor_service=mock_service,
        provider_registry=provider_reg,
        settings=mock_settings,
    )
    return mock_service, registry
