namespace Morgana.AI.Interfaces;

/// <summary>
/// Abstraction over the outbound channel that delivers Morgana's responses to an end user.
/// A channel is the transport + client pair (e.g. SignalR + Cauldron web UI, HTTP webhook,
/// polling REST endpoint, ...) through which messages leave the actor system and reach
/// whoever is consuming them.
/// </summary>
/// <remarks>
/// <para><strong>Purpose:</strong></para>
/// <para>This service decouples the actor system from any specific transport. Actors invoke
/// it to emit messages without knowing whether the underlying channel is SignalR, a webhook,
/// Server-Sent Events, or a plain HTTP long-poll.</para>
///
/// <para><strong>Metadata contract:</strong></para>
/// <para>This interface intentionally exposes no channel identity or capability budget:
/// identity + capabilities belong to the <em>client</em> that announces itself at the
/// conversation-start handshake, not to the transport that carries the bytes. Per-conversation
/// metadata is published by <c>ConversationManagerActor</c> into the <c>IChannelMetadataStore</c>,
/// and everything downstream (adapter, supervisor, presenter) consults the store keyed by
/// conversation id. A missing entry is always an error — there is no transport-level fallback.</para>
///
/// <para><strong>Built-In implementation:</strong></para>
/// <para><c>SignalRChannelService</c> (in Morgana.Web) is the reference transport used by the
/// Cauldron web UI. It only knows how to push <see cref="Records.ChannelMessage"/> envelopes
/// and streaming chunks over a SignalR hub; it has no opinion on who is listening.</para>
/// </remarks>
public interface IChannelService
{
    /// <summary>
    /// Sends a message to the conversation group targeted by
    /// <see cref="Records.ChannelMessage.ConversationId"/>. The message envelope carries the
    /// full payload (text, message type, quick replies, rich card, agent identity, error
    /// reason, fading duration) and is delivered through the channel's native transport.
    /// </summary>
    /// <param name="channelMessage">The fully-formed channel message to deliver.</param>
    /// <returns>Task representing the async send operation</returns>
    Task SendMessageAsync(Records.ChannelMessage channelMessage);

    /// <summary>
    /// Sends a streaming chunk to a conversation group via the channel for progressive response rendering.
    /// Enables real-time display of agent responses as they are generated by the LLM. Callers are
    /// responsible for gating the call on the conversation's registered capabilities; transports
    /// that cannot carry streaming are free to no-op.
    /// </summary>
    /// <param name="conversationId">Unique identifier of the conversation (channel group/routing key)</param>
    /// <param name="chunkText">Partial response text to append to the current message</param>
    /// <returns>Task representing the async send operation</returns>
    Task SendStreamChunkAsync(string conversationId, string chunkText);
}