"""In-memory channel adapter for tests and local gateway embedding."""

from __future__ import annotations

from typing import Any

from beaver.foundation.events import ChannelIdentity, InboundMessage, OutboundMessage
from beaver.interfaces.channels.base import ChannelInboundSink


class MemoryChannelAdapter:
    """A local channel that stores outbound messages in memory."""

    def __init__(
        self,
        inbound_sink: ChannelInboundSink,
        *,
        channel_id: str = "memory-dev",
        kind: str = "memory",
        mode: str = "webhook",
        account_id: str = "memory",
    ) -> None:
        self.channel_id = channel_id
        self.kind = kind
        self.mode = mode
        self.account_id = account_id
        self.inbound_sink = inbound_sink
        self.started = False
        self.sent_messages: list[OutboundMessage] = []

    async def start(self) -> None:
        self.started = True

    async def stop(self) -> None:
        self.started = False

    async def send(self, message: OutboundMessage) -> None:
        self.sent_messages.append(message)

    async def publish_text(
        self,
        content: str,
        *,
        session_id: str | None = None,
        user_id: str | None = None,
        title: str | None = None,
        execution_context: str | None = None,
        model: str | None = None,
        provider_name: str | None = None,
        embedding_model: str | None = None,
        peer_id: str = "default",
        thread_id: str | None = None,
        message_id: str | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> InboundMessage:
        """Publish a text message from this channel into the shared bus."""

        identity = ChannelIdentity(
            channel_id=self.channel_id,
            kind=self.kind,
            account_id=self.account_id,
            peer_id=peer_id,
            thread_id=thread_id,
            user_id=user_id,
            message_id=message_id,
        )
        message = InboundMessage(
            channel=self.channel_id,
            content=content,
            session_id=session_id,
            user_id=user_id,
            title=title,
            execution_context=execution_context,
            model=model,
            provider_name=provider_name,
            embedding_model=embedding_model,
            channel_identity=identity,
            metadata=metadata or {},
        )
        await self.inbound_sink.accept_inbound(message)
        return message

    async def publish_external_text(
        self,
        content: str,
        *,
        chat_id: str,
        message_id: str | None = None,
        thread_id: str | None = None,
        raw_payload: dict[str, Any] | None = None,
        user_id: str | None = None,
        title: str | None = None,
    ) -> InboundMessage:
        """Publish an old-style channel payload through the new adapter contract.

        Real platform adapters should keep platform-specific fields here, build
        a stable Beaver session_id, and pass the normalized InboundMessage to
        the shared gateway bus.
        """

        metadata = {
            "chat_id": chat_id,
            "message_id": message_id,
            "thread_id": thread_id,
            "raw_channel_payload": raw_payload or {},
        }
        return await self.publish_text(
            content,
            user_id=user_id,
            title=title,
            peer_id=chat_id,
            thread_id=thread_id,
            message_id=message_id,
            metadata=metadata,
        )
