//! Room membership operations delegated to [`crate::repo::traits::ChatRepository`].

use std::sync::Arc;

use sqlx::PgPool;

use crate::dto::commands::{AddMembers, RemoveMember};
use crate::dto::results::MemberView;
use crate::error::ChatResult;
use crate::ids::RoomId;
use crate::repo::traits::{ChatRepository, MembersCommit};

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

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

    /// Lists members visible to `actor` in `room_id`.
    pub async fn list_members(
        &self,
        pool: &PgPool,
        organization_id: &str,
        actor: &str,
        room_id: RoomId,
    ) -> ChatResult<Vec<MemberView>> {
        self.repo
            .list_members(pool, organization_id, actor, room_id)
            .await
    }

    /// Adds users to a room and returns the updated roster plus outbox commit.
    pub async fn add_members(
        &self,
        pool: &PgPool,
        organization_id: &str,
        actor: &str,
        input: AddMembers,
    ) -> ChatResult<MembersCommit> {
        self.repo
            .add_members(pool, organization_id, actor, input)
            .await
    }

    /// Removes a member (or self) and returns the updated roster plus outbox commit.
    pub async fn remove_member(
        &self,
        pool: &PgPool,
        organization_id: &str,
        actor: &str,
        input: RemoveMember,
    ) -> ChatResult<MembersCommit> {
        self.repo
            .remove_member(pool, organization_id, actor, input.room_id, &input.user_id)
            .await
    }
}
