//! Group management handlers — remove member, update metadata, list members, rotate keys.

use std::sync::Arc;

use bytes::Bytes;
use prost::Message;
use quicproquo_proto::qpq::v1;
use quicproquo_rpc::error::RpcStatus;
use quicproquo_rpc::method::{HandlerResult, RequestContext};

use crate::domain::groups::GroupService;
use crate::domain::types::{ListGroupMembersReq, UpdateGroupMetadataReq};

use super::{domain_err, require_auth, ServerState};

/// Handle RemoveMember (410): track member removal server-side.
///
/// Note: actual MLS removal (Remove proposal + Commit) is done client-side
/// via the SDK. This handler records the membership change on the server.
pub async fn handle_remove_member(
    state: Arc<ServerState>,
    ctx: RequestContext,
) -> HandlerResult {
    let identity_key = match require_auth(&state, &ctx) {
        Ok(ik) => ik,
        Err(e) => return e,
    };

    let req = match v1::RemoveMemberRequest::decode(ctx.payload) {
        Ok(r) => r,
        Err(e) => return HandlerResult::err(RpcStatus::BadRequest, &format!("decode: {e}")),
    };

    if req.group_id.is_empty() || req.member_identity_key.is_empty() {
        return HandlerResult::err(
            RpcStatus::BadRequest,
            "group_id and member_identity_key required",
        );
    }

    let svc = GroupService {
        store: Arc::clone(&state.store),
    };

    match svc.remove_member(&req.group_id, &req.member_identity_key) {
        Ok(_) => {
            let _ = identity_key; // caller is authorized; removal tracked
            let proto = v1::RemoveMemberResponse {
                commit: Vec::new(), // commit is generated client-side
            };
            HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
        }
        Err(e) => domain_err(e),
    }
}

/// Handle UpdateGroupMetadata (411): store group name, description, avatar.
pub async fn handle_update_group_metadata(
    state: Arc<ServerState>,
    ctx: RequestContext,
) -> HandlerResult {
    let identity_key = match require_auth(&state, &ctx) {
        Ok(ik) => ik,
        Err(e) => return e,
    };

    let req = match v1::UpdateGroupMetadataRequest::decode(ctx.payload) {
        Ok(r) => r,
        Err(e) => return HandlerResult::err(RpcStatus::BadRequest, &format!("decode: {e}")),
    };

    let svc = GroupService {
        store: Arc::clone(&state.store),
    };

    let domain_req = UpdateGroupMetadataReq {
        group_id: req.group_id,
        name: req.name,
        description: req.description,
        avatar_hash: req.avatar_hash,
    };

    match svc.update_metadata(domain_req, &identity_key) {
        Ok(()) => {
            let proto = v1::UpdateGroupMetadataResponse { success: true };
            HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
        }
        Err(e) => domain_err(e),
    }
}

/// Handle ListGroupMembers (412): return member list with resolved usernames.
pub async fn handle_list_group_members(
    state: Arc<ServerState>,
    ctx: RequestContext,
) -> HandlerResult {
    let _identity_key = match require_auth(&state, &ctx) {
        Ok(ik) => ik,
        Err(e) => return e,
    };

    let req = match v1::ListGroupMembersRequest::decode(ctx.payload) {
        Ok(r) => r,
        Err(e) => return HandlerResult::err(RpcStatus::BadRequest, &format!("decode: {e}")),
    };

    let svc = GroupService {
        store: Arc::clone(&state.store),
    };

    let domain_req = ListGroupMembersReq {
        group_id: req.group_id,
    };

    match svc.list_members(domain_req) {
        Ok(resp) => {
            let proto = v1::ListGroupMembersResponse {
                members: resp
                    .members
                    .into_iter()
                    .map(|m| v1::GroupMemberInfo {
                        identity_key: m.identity_key,
                        username: m.username,
                        joined_at: m.joined_at,
                    })
                    .collect(),
            };
            HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
        }
        Err(e) => domain_err(e),
    }
}

/// Handle RotateKeys (413): acknowledge key rotation.
///
/// Actual MLS key rotation (Update proposal + Commit) is done client-side.
/// This handler exists for server-side tracking and future rate limiting.
pub async fn handle_rotate_keys(
    state: Arc<ServerState>,
    ctx: RequestContext,
) -> HandlerResult {
    let _identity_key = match require_auth(&state, &ctx) {
        Ok(ik) => ik,
        Err(e) => return e,
    };

    let req = match v1::RotateKeysRequest::decode(ctx.payload) {
        Ok(r) => r,
        Err(e) => return HandlerResult::err(RpcStatus::BadRequest, &format!("decode: {e}")),
    };

    if req.group_id.is_empty() {
        return HandlerResult::err(RpcStatus::BadRequest, "group_id required");
    }

    // Key rotation is handled entirely client-side in MLS.
    // This endpoint is for server-side auditing and future rate limiting.
    let proto = v1::RotateKeysResponse {
        commit: Vec::new(), // commit is generated client-side
    };
    HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
}
