//! Message history and mutation operations delegated to [`crate::repo::traits::ChatRepository`].

use std::sync::Arc;

use sqlx::PgPool;

use crate::dto::commands::{DeleteMessage, EditMessage, ListMessages, SendMessage};
use crate::dto::results::MessagePage;
use crate::error::ChatResult;
use crate::repo::traits::{
    ChatRepository, DeleteMessageCommit, MessageMutationCommit, SendMessageCommit,
};

/// Message facade used by [`crate::SqlxChatApp`].
#[derive(Clone)]
pub struct MessageService {
    repo: Arc<dyn ChatRepository>,
}

impl MessageService {
    /// Constructs a service backed by the given repository.
    pub fn new(repo: Arc<dyn ChatRepository>) -> Self {
        Self { repo }
    }

    /// Returns a paginated message history page for a room.
    pub async fn list_messages(
        &self,
        pool: &PgPool,
        organization_id: &str,
        actor: &str,
        input: ListMessages,
    ) -> ChatResult<MessagePage> {
        self.repo
            .list_messages(pool, organization_id, actor, input)
            .await
    }

    /// Inserts a message (idempotent on `client_message_id`) and returns an outbox commit.
    pub async fn send_message(
        &self,
        pool: &PgPool,
        organization_id: &str,
        actor: &str,
        input: SendMessage,
    ) -> ChatResult<SendMessageCommit> {
        self.repo
            .send_message(pool, organization_id, actor, input)
            .await
    }

    /// Edits message content and returns an outbox commit.
    pub async fn edit_message(
        &self,
        pool: &PgPool,
        organization_id: &str,
        actor: &str,
        input: EditMessage,
    ) -> ChatResult<MessageMutationCommit> {
        self.repo
            .edit_message(pool, organization_id, actor, input)
            .await
    }

    /// Soft-deletes a message and returns an outbox commit.
    pub async fn delete_message(
        &self,
        pool: &PgPool,
        organization_id: &str,
        actor: &str,
        input: DeleteMessage,
    ) -> ChatResult<DeleteMessageCommit> {
        self.repo
            .delete_message(
                pool,
                organization_id,
                actor,
                input.room_id,
                input.message_id,
            )
            .await
    }
}
