"""Dependency injection container for stream module."""

from dependency_injector import containers, providers

from infra_mvp.stream.server import StreamServer
from yera.agents.decorator import AgentFunctionWrapper

from .services import AgentService, SessionService


class StreamContainer(containers.DeclarativeContainer):
    """Dependency injection container for stream services."""

    # Configuration
    config = providers.Configuration()
    config.host.from_value("0.0.0.0")
    config.port.from_value(8991)
    config.agents.from_value([])
    config.dev_ui.from_value(False)

    # Services - all singletons (stateless)
    session_service: providers.Singleton[SessionService] | None = None
    agent_service: providers.Singleton[AgentService] | None = None

    # Stream server provider - creates fully-formed server
    # Will be set by create_container
    stream_server: providers.Singleton[StreamServer] | None = None


def create_container(
    agents: list[AgentFunctionWrapper],
    host: str = "0.0.0.0",
    port: int = 8991,
    log_events: bool = False,
    dev_ui: bool = False,
) -> StreamContainer:
    """Create and configure a stream container for agent mode.

    Args:
        agents: List of agent function wrappers.
        host: Server host address. Defaults to "0.0.0.0".
        port: Server port number. Defaults to 8991.
        log_events: Enable logging of events to file.
        dev_ui: If True, expect Next.js dev server (localhost:3000) instead of serving static UI.

    Returns:
        Configured stream container
    """
    container = StreamContainer()

    # Create SessionService
    container.session_service = providers.Singleton(
        SessionService,
        log_events=log_events,
    )

    # Create AgentService
    container.agent_service = providers.Singleton(
        AgentService,
        agents=agents,
    )

    # Configure host, port and UI serving
    container.config.host.from_value(host)
    container.config.port.from_value(port)
    container.config.dev_ui.from_value(dev_ui)

    # Store agents in config for factory to access
    container.config.agents.from_value(agents)

    # Create stream server factory that captures the container
    def _create_stream_server() -> StreamServer:
        return StreamServer(
            session_service=container.session_service(),
            agent_service=container.agent_service(),
            host=container.config.host(),
            port=container.config.port(),
            dev_ui=container.config.dev_ui(),
        )

    container.stream_server = providers.Singleton(_create_stream_server)

    return container


def create_stream_server(
    agents: list[AgentFunctionWrapper],
    host: str = "0.0.0.0",
    port: int = 8991,
    log_events: bool = False,
    dev_ui: bool = False,
) -> StreamServer:
    """Create a stream server for agent mode.

    Args:
        agents: List of agent function wrappers.
        host: Server host address. Defaults to "0.0.0.0".
        port: Server port number. Defaults to 8991.
        log_events: Enable logging of events to file.
        dev_ui: If True, expect Next.js dev server (localhost:3000) instead of serving static UI.

    Returns:
        Configured stream server instance
    """
    container = create_container(
        agents=agents,
        host=host,
        port=port,
        log_events=log_events,
        dev_ui=dev_ui,
    )
    return container.stream_server()
