// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright by contributors to this project.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)

use crate::cipher_suite::CipherSuite;
use crate::client_builder::{recreate_config, BaseConfig, ClientBuilder, MakeConfig};
use crate::client_config::ClientConfig;
use crate::group::framing::MlsMessage;

#[cfg(feature = "by_ref_proposal")]
use crate::group::{
    framing::{Content, MlsMessagePayload, PublicMessage, Sender, WireFormat},
    message_signature::AuthenticatedContent,
    proposal::{AddProposal, Proposal},
};
use crate::group::{snapshot::Snapshot, ExportedTree, Group, NewMemberInfo};
use crate::identity::SigningIdentity;
use crate::key_package::{KeyPackageGeneration, KeyPackageGenerator};
use crate::protocol_version::ProtocolVersion;
use crate::tree_kem::node::NodeIndex;
use alloc::vec::Vec;
use mls_rs_codec::MlsDecode;
use mls_rs_core::crypto::{CryptoProvider, SignatureSecretKey};
use mls_rs_core::error::{AnyError, IntoAnyError};
use mls_rs_core::extension::{ExtensionError, ExtensionList, ExtensionType};
use mls_rs_core::group::{GroupStateStorage, ProposalType};
use mls_rs_core::identity::CredentialType;
use mls_rs_core::key_package::KeyPackageStorage;

use crate::group::external_commit::ExternalCommitBuilder;

#[cfg(feature = "by_ref_proposal")]
use alloc::boxed::Box;

#[derive(Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::enum_to_error_code)]
#[non_exhaustive]
pub enum MlsError {
    #[cfg_attr(feature = "std", error(transparent))]
    IdentityProviderError(AnyError),
    #[cfg_attr(feature = "std", error(transparent))]
    CryptoProviderError(AnyError),
    #[cfg_attr(feature = "std", error(transparent))]
    KeyPackageRepoError(AnyError),
    #[cfg_attr(feature = "std", error(transparent))]
    GroupStorageError(AnyError),
    #[cfg_attr(feature = "std", error(transparent))]
    PskStoreError(AnyError),
    #[cfg_attr(feature = "std", error(transparent))]
    MlsRulesError(AnyError),
    #[cfg_attr(feature = "std", error(transparent))]
    SerializationError(AnyError),
    #[cfg_attr(feature = "std", error(transparent))]
    ExtensionError(AnyError),
    #[cfg_attr(feature = "std", error("Cipher suite does not match"))]
    CipherSuiteMismatch,
    #[cfg_attr(feature = "std", error("Invalid commit, missing required path"))]
    CommitMissingPath,
    #[cfg_attr(feature = "std", error("plaintext message for incorrect epoch"))]
    InvalidEpoch,
    #[cfg_attr(feature = "std", error("invalid signature found"))]
    InvalidSignature,
    #[cfg_attr(feature = "std", error("invalid confirmation tag"))]
    InvalidConfirmationTag,
    #[cfg_attr(feature = "std", error("invalid membership tag"))]
    InvalidMembershipTag,
    #[cfg_attr(feature = "std", error("corrupt private key, missing required values"))]
    InvalidTreeKemPrivateKey,
    #[cfg_attr(feature = "std", error("key package not found, unable to process"))]
    WelcomeKeyPackageNotFound,
    #[cfg_attr(feature = "std", error("leaf not found in tree for index {0}"))]
    LeafNotFound(u32),
    #[cfg_attr(feature = "std", error("message from self can't be processed"))]
    CantProcessMessageFromSelf,
    #[cfg_attr(
        feature = "std",
        error("pending proposals found, commit required before application messages can be sent")
    )]
    CommitRequired,
    #[cfg_attr(
        feature = "std",
        error("ratchet tree not provided or discovered in GroupInfo")
    )]
    RatchetTreeNotFound,
    #[cfg_attr(feature = "std", error("External sender cannot commit"))]
    ExternalSenderCannotCommit,
    #[cfg_attr(feature = "std", error("Unsupported protocol version {0:?}"))]
    UnsupportedProtocolVersion(ProtocolVersion),
    #[cfg_attr(feature = "std", error("Protocol version mismatch"))]
    ProtocolVersionMismatch,
    #[cfg_attr(feature = "std", error("Unsupported cipher suite {0:?}"))]
    UnsupportedCipherSuite(CipherSuite),
    #[cfg_attr(feature = "std", error("Signing key of external sender is unknown"))]
    UnknownSigningIdentityForExternalSender,
    #[cfg_attr(
        feature = "std",
        error("External proposals are disabled for this group")
    )]
    ExternalProposalsDisabled,
    #[cfg_attr(
        feature = "std",
        error("Signing identity is not allowed to externally propose")
    )]
    InvalidExternalSigningIdentity,
    #[cfg_attr(feature = "std", error("Missing ExternalPub extension"))]
    MissingExternalPubExtension,
    #[cfg_attr(feature = "std", error("Epoch not found"))]
    EpochNotFound,
    #[cfg_attr(feature = "std", error("Unencrypted application message"))]
    UnencryptedApplicationMessage,
    #[cfg_attr(
        feature = "std",
        error("NewMemberCommit sender type can only be used to send Commit content")
    )]
    ExpectedCommitForNewMemberCommit,
    #[cfg_attr(
        feature = "std",
        error("NewMemberProposal sender type can only be used to send add proposals")
    )]
    ExpectedAddProposalForNewMemberProposal,
    #[cfg_attr(
        feature = "std",
        error("External commit missing ExternalInit proposal")
    )]
    ExternalCommitMissingExternalInit,
    #[cfg_attr(
        feature = "std",
        error(
            "A ReIinit has been applied. The next action must be creating or receiving a welcome."
        )
    )]
    GroupUsedAfterReInit,
    #[cfg_attr(feature = "std", error("Pending ReIinit not found."))]
    PendingReInitNotFound,
    #[cfg_attr(
        feature = "std",
        error("The extensions in the welcome message and in the reinit do not match.")
    )]
    ReInitExtensionsMismatch,
    #[cfg_attr(feature = "std", error("signer not found for given identity"))]
    SignerNotFound,
    #[cfg_attr(feature = "std", error("commit already pending"))]
    ExistingPendingCommit,
    #[cfg_attr(feature = "std", error("pending commit not found"))]
    PendingCommitNotFound,
    #[cfg_attr(feature = "std", error("unexpected message type for action"))]
    UnexpectedMessageType,
    #[cfg_attr(
        feature = "std",
        error("membership tag on MlsPlaintext for non-member sender")
    )]
    MembershipTagForNonMember,
    #[cfg_attr(feature = "std", error("No member found for given identity id."))]
    MemberNotFound,
    #[cfg_attr(feature = "std", error("group not found"))]
    GroupNotFound,
    #[cfg_attr(feature = "std", error("unexpected PSK ID"))]
    UnexpectedPskId,
    #[cfg_attr(feature = "std", error("invalid sender for content type"))]
    InvalidSender,
    #[cfg_attr(feature = "std", error("GroupID mismatch"))]
    GroupIdMismatch,
    #[cfg_attr(feature = "std", error("storage retention can not be zero"))]
    NonZeroRetentionRequired,
    #[cfg_attr(feature = "std", error("Too many PSK IDs to compute PSK secret"))]
    TooManyPskIds,
    #[cfg_attr(feature = "std", error("Missing required Psk"))]
    MissingRequiredPsk,
    #[cfg_attr(feature = "std", error("Old group state not found"))]
    OldGroupStateNotFound,
    #[cfg_attr(feature = "std", error("leaf secret already consumed"))]
    InvalidLeafConsumption,
    #[cfg_attr(feature = "std", error("key not available, invalid generation {0}"))]
    KeyMissing(u32),
    #[cfg_attr(
        feature = "std",
        error("requested generation {0} is too far ahead of current generation")
    )]
    InvalidFutureGeneration(u32),
    #[cfg_attr(feature = "std", error("leaf node has no children"))]
    LeafNodeNoChildren,
    #[cfg_attr(feature = "std", error("root node has no parent"))]
    LeafNodeNoParent,
    #[cfg_attr(feature = "std", error("index out of range"))]
    InvalidTreeIndex,
    #[cfg_attr(feature = "std", error("time overflow"))]
    TimeOverflow,
    #[cfg_attr(feature = "std", error("invalid leaf_node_source"))]
    InvalidLeafNodeSource,
    #[cfg_attr(feature = "std", error("key package has expired or is not valid yet"))]
    InvalidLifetime,
    #[cfg_attr(feature = "std", error("required extension not found"))]
    RequiredExtensionNotFound(ExtensionType),
    #[cfg_attr(feature = "std", error("required proposal not found"))]
    RequiredProposalNotFound(ProposalType),
    #[cfg_attr(feature = "std", error("required credential not found"))]
    RequiredCredentialNotFound(CredentialType),
    #[cfg_attr(feature = "std", error("capabilities must describe extensions used"))]
    ExtensionNotInCapabilities(ExtensionType),
    #[cfg_attr(feature = "std", error("expected non-blank node"))]
    ExpectedNode,
    #[cfg_attr(feature = "std", error("node index is out of bounds {0}"))]
    InvalidNodeIndex(NodeIndex),
    #[cfg_attr(feature = "std", error("unexpected empty node found"))]
    UnexpectedEmptyNode,
    #[cfg_attr(
        feature = "std",
        error("duplicate signature key, hpke key or identity found at index {0}")
    )]
    DuplicateLeafData(u32),
    #[cfg_attr(
        feature = "std",
        error("In-use credential type not supported by new leaf at index")
    )]
    InUseCredentialTypeUnsupportedByNewLeaf,
    #[cfg_attr(
        feature = "std",
        error("Not all members support the credential type used by new leaf")
    )]
    CredentialTypeOfNewLeafIsUnsupported,
    #[cfg_attr(
        feature = "std",
        error("the length of the update path is different than the length of the direct path")
    )]
    WrongPathLen,
    #[cfg_attr(
        feature = "std",
        error("same HPKE leaf key before and after applying the update path for leaf {0}")
    )]
    SameHpkeKey(u32),
    #[cfg_attr(feature = "std", error("init key is not valid for cipher suite"))]
    InvalidInitKey,
    #[cfg_attr(
        feature = "std",
        error("init key can not be equal to leaf node public key")
    )]
    InitLeafKeyEquality,
    #[cfg_attr(feature = "std", error("different identity in update for leaf {0}"))]
    DifferentIdentityInUpdate(u32),
    #[cfg_attr(feature = "std", error("update path pub key mismatch"))]
    PubKeyMismatch,
    #[cfg_attr(feature = "std", error("tree hash mismatch"))]
    TreeHashMismatch,
    #[cfg_attr(feature = "std", error("bad update: no suitable secret key"))]
    UpdateErrorNoSecretKey,
    #[cfg_attr(feature = "std", error("invalid lca, not found on direct path"))]
    LcaNotFoundInDirectPath,
    #[cfg_attr(feature = "std", error("update path parent hash mismatch"))]
    ParentHashMismatch,
    #[cfg_attr(feature = "std", error("unexpected pattern of unmerged leaves"))]
    UnmergedLeavesMismatch,
    #[cfg_attr(feature = "std", error("empty tree"))]
    UnexpectedEmptyTree,
    #[cfg_attr(feature = "std", error("trailing blanks"))]
    UnexpectedTrailingBlanks,
    // Proposal Rules errors
    #[cfg_attr(
        feature = "std",
        error("Commiter must not include any update proposals generated by the commiter")
    )]
    InvalidCommitSelfUpdate,
    #[cfg_attr(feature = "std", error("A PreSharedKey proposal must have a PSK of type External or type Resumption and usage Application"))]
    InvalidTypeOrUsageInPreSharedKeyProposal,
    #[cfg_attr(feature = "std", error("psk nonce length does not match cipher suite"))]
    InvalidPskNonceLength,
    #[cfg_attr(
        feature = "std",
        error("ReInit proposal protocol version is less than the version of the original group")
    )]
    InvalidProtocolVersionInReInit,
    #[cfg_attr(feature = "std", error("More than one proposal applying to leaf: {0}"))]
    MoreThanOneProposalForLeaf(u32),
    #[cfg_attr(
        feature = "std",
        error("More than one GroupContextExtensions proposal")
    )]
    MoreThanOneGroupContextExtensionsProposal,
    #[cfg_attr(feature = "std", error("Invalid proposal type for sender"))]
    InvalidProposalTypeForSender,
    #[cfg_attr(
        feature = "std",
        error("External commit must have exactly one ExternalInit proposal")
    )]
    ExternalCommitMustHaveExactlyOneExternalInit,
    #[cfg_attr(feature = "std", error("External commit must have a new leaf"))]
    ExternalCommitMustHaveNewLeaf,
    #[cfg_attr(
        feature = "std",
        error("External commit contains removal of other identity")
    )]
    ExternalCommitRemovesOtherIdentity,
    #[cfg_attr(
        feature = "std",
        error("External commit contains more than one Remove proposal")
    )]
    ExternalCommitWithMoreThanOneRemove,
    #[cfg_attr(feature = "std", error("Duplicate PSK IDs"))]
    DuplicatePskIds,
    #[cfg_attr(
        feature = "std",
        error("Invalid proposal type {0:?} in external commit")
    )]
    InvalidProposalTypeInExternalCommit(ProposalType),
    #[cfg_attr(feature = "std", error("Committer can not remove themselves"))]
    CommitterSelfRemoval,
    #[cfg_attr(
        feature = "std",
        error("Only members can commit proposals by reference")
    )]
    OnlyMembersCanCommitProposalsByRef,
    #[cfg_attr(feature = "std", error("Other proposal with ReInit"))]
    OtherProposalWithReInit,
    #[cfg_attr(feature = "std", error("Unsupported group extension {0:?}"))]
    UnsupportedGroupExtension(ExtensionType),
    #[cfg_attr(feature = "std", error("Unsupported custom proposal type {0:?}"))]
    UnsupportedCustomProposal(ProposalType),
    #[cfg_attr(feature = "std", error("by-ref proposal not found"))]
    ProposalNotFound,
    #[cfg_attr(
        feature = "std",
        error("Removing non-existing member (or removing a member twice)")
    )]
    RemovingNonExistingMember,
    #[cfg_attr(feature = "std", error("Updated identity not a valid successor"))]
    InvalidSuccessor,
    #[cfg_attr(
        feature = "std",
        error("Updating non-existing member (or updating a member twice)")
    )]
    UpdatingNonExistingMember,
    #[cfg_attr(feature = "std", error("Failed generating next path secret"))]
    FailedGeneratingPathSecret,
    #[cfg_attr(feature = "std", error("Invalid group info"))]
    InvalidGroupInfo,
    #[cfg_attr(feature = "std", error("Invalid welcome message"))]
    InvalidWelcomeMessage,
}

impl IntoAnyError for MlsError {
    #[cfg(feature = "std")]
    fn into_dyn_error(self) -> Result<Box<dyn std::error::Error + Send + Sync>, Self> {
        Ok(self.into())
    }
}

impl From<mls_rs_codec::Error> for MlsError {
    #[inline]
    fn from(e: mls_rs_codec::Error) -> Self {
        MlsError::SerializationError(e.into_any_error())
    }
}

impl From<ExtensionError> for MlsError {
    #[inline]
    fn from(e: ExtensionError) -> Self {
        MlsError::ExtensionError(e.into_any_error())
    }
}

/// MLS client used to create key packages and manage groups.
///
/// [`Client::builder`] can be used to instantiate it.
///
/// Clients are able to support multiple protocol versions, ciphersuites
/// and underlying identities used to join groups and generate key packages.
/// Applications may decide to create one or many clients depending on their
/// specific needs.
#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type(opaque))]
#[derive(Clone, Debug)]
pub struct Client<C> {
    pub(crate) config: C,
    pub(crate) signing_identity: Option<(SigningIdentity, CipherSuite)>,
    pub(crate) signer: Option<SignatureSecretKey>,
    pub(crate) version: ProtocolVersion,
}

impl Client<()> {
    /// Returns a [`ClientBuilder`]
    /// used to configure client preferences and providers.
    pub fn builder() -> ClientBuilder<BaseConfig> {
        ClientBuilder::new()
    }
}

#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen)]
impl<C> Client<C>
where
    C: ClientConfig + Clone,
{
    pub(crate) fn new(
        config: C,
        signer: Option<SignatureSecretKey>,
        signing_identity: Option<(SigningIdentity, CipherSuite)>,
        version: ProtocolVersion,
    ) -> Self {
        Client {
            config,
            signer,
            signing_identity,
            version,
        }
    }

    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
    pub fn to_builder(&self) -> ClientBuilder<MakeConfig<C>> {
        ClientBuilder::from_config(recreate_config(
            self.config.clone(),
            self.signer.clone(),
            self.signing_identity.clone(),
            self.version,
        ))
    }

    /// Creates a new key package message that can be used to to add this
    /// client to a [Group](crate::group::Group). Each call to this function
    /// will produce a unique value that is signed by `signing_identity`.
    ///
    /// The secret keys for the resulting key package message will be stored in
    /// the [KeyPackageStorage](crate::KeyPackageStorage)
    /// that was used to configure the client and will
    /// automatically be erased when this key package is used to
    /// [join a group](Client::join_group).
    ///
    /// # Warning
    ///
    /// A key package message may only be used once.
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn generate_key_package_message(&self) -> Result<MlsMessage, MlsError> {
        Ok(self.generate_key_package().await?.key_package_message())
    }

    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    async fn generate_key_package(&self) -> Result<KeyPackageGeneration, MlsError> {
        let (signing_identity, cipher_suite) = self.signing_identity()?;

        let cipher_suite_provider = self
            .config
            .crypto_provider()
            .cipher_suite_provider(cipher_suite)
            .ok_or(MlsError::UnsupportedCipherSuite(cipher_suite))?;

        let key_package_generator = KeyPackageGenerator {
            protocol_version: self.version,
            cipher_suite_provider: &cipher_suite_provider,
            signing_key: self.signer()?,
            signing_identity,
        };

        let key_pkg_gen = key_package_generator
            .generate(
                self.config.lifetime(),
                self.config.capabilities(),
                self.config.key_package_extensions(),
                self.config.leaf_node_extensions(),
            )
            .await?;

        let (id, key_package_data) = key_pkg_gen.to_storage()?;

        self.config
            .key_package_repo()
            .insert(id, key_package_data)
            .await
            .map_err(|e| MlsError::KeyPackageRepoError(e.into_any_error()))?;

        Ok(key_pkg_gen)
    }

    /// Create a group with a specific group_id.
    ///
    /// This function behaves the same way as
    /// [create_group](Client::create_group) except that it
    /// specifies a specific unique group identifier to be used.
    ///
    /// # Warning
    ///
    /// It is recommended to use [create_group](Client::create_group)
    /// instead of this function because it guarantees that group_id values
    /// are globally unique.
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn create_group_with_id(
        &self,
        group_id: Vec<u8>,
        group_context_extensions: ExtensionList,
    ) -> Result<Group<C>, MlsError> {
        let (signing_identity, cipher_suite) = self.signing_identity()?;

        Group::new(
            self.config.clone(),
            Some(group_id),
            cipher_suite,
            self.version,
            signing_identity.clone(),
            group_context_extensions,
            self.signer()?.clone(),
        )
        .await
    }

    /// Create a MLS group.
    ///
    /// The `cipher_suite` provided must be supported by the
    /// [CipherSuiteProvider](crate::CipherSuiteProvider)
    /// that was used to build the client.
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn create_group(
        &self,
        group_context_extensions: ExtensionList,
    ) -> Result<Group<C>, MlsError> {
        let (signing_identity, cipher_suite) = self.signing_identity()?;

        Group::new(
            self.config.clone(),
            None,
            cipher_suite,
            self.version,
            signing_identity.clone(),
            group_context_extensions,
            self.signer()?.clone(),
        )
        .await
    }

    /// Join a MLS group via a welcome message created by a
    /// [Commit](crate::group::CommitOutput).
    ///
    /// `tree_data` is required to be provided out of band if the client that
    /// created `welcome_message` did not use the `ratchet_tree_extension`
    /// according to [`MlsRules::commit_options`](`crate::MlsRules::commit_options`).
    /// at the time the welcome message was created. `tree_data` can
    /// be exported from a group using the
    /// [export tree function](crate::group::Group::export_tree).
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn join_group(
        &self,
        tree_data: Option<ExportedTree<'_>>,
        welcome_message: &MlsMessage,
    ) -> Result<(Group<C>, NewMemberInfo), MlsError> {
        Group::join(
            welcome_message,
            tree_data,
            self.config.clone(),
            self.signer()?.clone(),
        )
        .await
    }

    /// 0-RTT add to an existing [group](crate::group::Group)
    ///
    /// External commits allow for immediate entry into a
    /// [group](crate::group::Group), even if all of the group members
    /// are currently offline and unable to process messages. Sending an
    /// external commit is only allowed for groups that have provided
    /// a public `group_info_message` containing an
    /// [ExternalPubExt](crate::extension::ExternalPubExt), which can be
    /// generated by an existing group member using the
    /// [group_info_message](crate::group::Group::group_info_message)
    /// function.
    ///
    /// `tree_data` may be provided following the same rules as [Client::join_group]
    ///
    /// If PSKs are provided in `external_psks`, the
    /// [PreSharedKeyStorage](crate::PreSharedKeyStorage)
    /// used to configure the client will be searched to resolve their values.
    ///
    /// `to_remove` may be used to remove an existing member provided that the
    /// identity of the existing group member at that [index](crate::group::Member::index)
    /// is a [valid successor](crate::IdentityProvider::valid_successor)
    /// of `signing_identity` as defined by the
    /// [IdentityProvider](crate::IdentityProvider) that this client
    /// was configured with.
    ///
    /// # Warning
    ///
    /// Only one external commit can be performed against a given group info.
    /// There may also be security trade-offs to this approach.
    ///
    // TODO: Add a comment about forward secrecy and a pointer to the future
    // book chapter on this topic
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn commit_external(
        &self,
        group_info_msg: MlsMessage,
    ) -> Result<(Group<C>, MlsMessage), MlsError> {
        ExternalCommitBuilder::new(
            self.signer()?.clone(),
            self.signing_identity()?.0.clone(),
            self.config.clone(),
        )
        .build(group_info_msg)
        .await
    }

    pub fn external_commit_builder(&self) -> Result<ExternalCommitBuilder<C>, MlsError> {
        Ok(ExternalCommitBuilder::new(
            self.signer()?.clone(),
            self.signing_identity()?.0.clone(),
            self.config.clone(),
        ))
    }

    /// Load an existing group state into this client using the
    /// [GroupStateStorage](crate::GroupStateStorage) that
    /// this client was configured to use.
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    #[inline(never)]
    pub async fn load_group(&self, group_id: &[u8]) -> Result<Group<C>, MlsError> {
        let snapshot = self
            .config
            .group_state_storage()
            .state(group_id)
            .await
            .map_err(|e| MlsError::GroupStorageError(e.into_any_error()))?
            .ok_or(MlsError::GroupNotFound)?;

        let snapshot = Snapshot::mls_decode(&mut &*snapshot)?;

        Group::from_snapshot(self.config.clone(), snapshot).await
    }

    /// Request to join an existing [group](crate::group::Group).
    ///
    /// An existing group member will need to perform a
    /// [commit](crate::Group::commit) to complete the add and the resulting
    /// welcome message can be used by [join_group](Client::join_group).
    #[cfg(feature = "by_ref_proposal")]
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn external_add_proposal(
        &self,
        group_info: &MlsMessage,
        tree_data: Option<crate::group::ExportedTree<'_>>,
        authenticated_data: Vec<u8>,
    ) -> Result<MlsMessage, MlsError> {
        let protocol_version = group_info.version;

        if !self.config.version_supported(protocol_version) && protocol_version == self.version {
            return Err(MlsError::UnsupportedProtocolVersion(protocol_version));
        }

        let group_info = group_info
            .as_group_info()
            .ok_or(MlsError::UnexpectedMessageType)?;

        let cipher_suite = group_info.group_context.cipher_suite;

        let cipher_suite_provider = self
            .config
            .crypto_provider()
            .cipher_suite_provider(cipher_suite)
            .ok_or(MlsError::UnsupportedCipherSuite(cipher_suite))?;

        crate::group::validate_group_info_joiner(
            protocol_version,
            group_info,
            tree_data,
            &self.config.identity_provider(),
            &cipher_suite_provider,
        )
        .await?;

        let key_package = self.generate_key_package().await?.key_package;

        (key_package.cipher_suite == cipher_suite)
            .then_some(())
            .ok_or(MlsError::UnsupportedCipherSuite(cipher_suite))?;

        let message = AuthenticatedContent::new_signed(
            &cipher_suite_provider,
            &group_info.group_context,
            Sender::NewMemberProposal,
            Content::Proposal(Box::new(Proposal::Add(Box::new(AddProposal {
                key_package,
            })))),
            self.signer()?,
            WireFormat::PublicMessage,
            authenticated_data,
        )
        .await?;

        let plaintext = PublicMessage {
            content: message.content,
            auth: message.auth,
            membership_tag: None,
        };

        Ok(MlsMessage {
            version: protocol_version,
            payload: MlsMessagePayload::Plain(plaintext),
        })
    }

    fn signer(&self) -> Result<&SignatureSecretKey, MlsError> {
        self.signer.as_ref().ok_or(MlsError::SignerNotFound)
    }

    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
    pub fn signing_identity(&self) -> Result<(&SigningIdentity, CipherSuite), MlsError> {
        self.signing_identity
            .as_ref()
            .map(|(id, cs)| (id, *cs))
            .ok_or(MlsError::SignerNotFound)
    }

    /// Returns key package extensions used by this client
    pub fn key_package_extensions(&self) -> ExtensionList {
        self.config.key_package_extensions()
    }

    /// The [KeyPackageStorage] that this client was configured to use.
    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
    pub fn key_package_store(&self) -> <C as ClientConfig>::KeyPackageRepository {
        self.config.key_package_repo()
    }

    /// The [PreSharedKeyStorage](crate::PreSharedKeyStorage) that
    /// this client was configured to use.
    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
    pub fn secret_store(&self) -> <C as ClientConfig>::PskStore {
        self.config.secret_store()
    }

    /// The [GroupStateStorage] that this client was configured to use.
    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
    pub fn group_state_storage(&self) -> <C as ClientConfig>::GroupStateStorage {
        self.config.group_state_storage()
    }

    /// The [IdentityProvider] that this client was configured to use.
    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
    pub fn identity_provider(&self) -> <C as ClientConfig>::IdentityProvider {
        self.config.identity_provider()
    }
}

#[cfg(test)]
pub(crate) mod test_utils {
    use super::*;
    use crate::identity::test_utils::get_test_signing_identity;

    pub use crate::client_builder::test_utils::{TestClientBuilder, TestClientConfig};

    pub const TEST_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::MLS_10;
    pub const TEST_CIPHER_SUITE: CipherSuite = CipherSuite::P256_AES128;
    pub const TEST_CUSTOM_PROPOSAL_TYPE: ProposalType = ProposalType::new(65001);

    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn test_client_with_key_pkg(
        protocol_version: ProtocolVersion,
        cipher_suite: CipherSuite,
        identity: &str,
    ) -> (Client<TestClientConfig>, MlsMessage) {
        test_client_with_key_pkg_custom(protocol_version, cipher_suite, identity, |_| {}).await
    }

    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    pub async fn test_client_with_key_pkg_custom<F>(
        protocol_version: ProtocolVersion,
        cipher_suite: CipherSuite,
        identity: &str,
        mut config: F,
    ) -> (Client<TestClientConfig>, MlsMessage)
    where
        F: FnMut(&mut TestClientConfig),
    {
        let (identity, secret_key) =
            get_test_signing_identity(cipher_suite, identity.as_bytes()).await;

        let mut client = TestClientBuilder::new_for_test()
            .used_protocol_version(protocol_version)
            .signing_identity(identity.clone(), secret_key, cipher_suite)
            .build();

        config(&mut client.config);

        let key_package = client.generate_key_package_message().await.unwrap();

        (client, key_package)
    }
}

#[cfg(test)]
mod tests {
    use super::test_utils::*;

    use super::*;
    use crate::{
        crypto::test_utils::TestCryptoProvider,
        identity::test_utils::{get_test_basic_credential, get_test_signing_identity},
        tree_kem::leaf_node::LeafNodeSource,
    };
    use assert_matches::assert_matches;

    use crate::{
        group::{
            message_processor::ProposalMessageDescription,
            proposal::Proposal,
            test_utils::{test_group, test_group_custom_config},
            ReceivedMessage,
        },
        psk::{ExternalPskId, PreSharedKey},
    };

    use alloc::vec;

    #[maybe_async::test(not(mls_build_async), async(mls_build_async, crate::futures_test))]
    async fn test_keygen() {
        // This is meant to test the inputs to the internal key package generator
        // See KeyPackageGenerator tests for key generation specific tests
        for (protocol_version, cipher_suite) in ProtocolVersion::all().flat_map(|p| {
            TestCryptoProvider::all_supported_cipher_suites()
                .into_iter()
                .map(move |cs| (p, cs))
        }) {
            let (identity, secret_key) = get_test_signing_identity(cipher_suite, b"foo").await;

            let client = TestClientBuilder::new_for_test()
                .signing_identity(identity.clone(), secret_key, cipher_suite)
                .build();

            // TODO: Tests around extensions
            let key_package = client.generate_key_package_message().await.unwrap();

            assert_eq!(key_package.version, protocol_version);

            let key_package = key_package.into_key_package().unwrap();

            assert_eq!(key_package.cipher_suite, cipher_suite);

            assert_eq!(
                &key_package.leaf_node.signing_identity.credential,
                &get_test_basic_credential(b"foo".to_vec())
            );

            assert_eq!(key_package.leaf_node.signing_identity, identity);

            let capabilities = key_package.leaf_node.ungreased_capabilities();
            assert_eq!(capabilities, client.config.capabilities());

            let client_lifetime = client.config.lifetime();
            assert_matches!(key_package.leaf_node.leaf_node_source, LeafNodeSource::KeyPackage(lifetime) if (lifetime.not_after - lifetime.not_before) == (client_lifetime.not_after - client_lifetime.not_before));
        }
    }

    #[cfg(feature = "by_ref_proposal")]
    #[maybe_async::test(not(mls_build_async), async(mls_build_async, crate::futures_test))]
    async fn new_member_add_proposal_adds_to_group() {
        let mut alice_group = test_group(TEST_PROTOCOL_VERSION, TEST_CIPHER_SUITE).await;

        let (bob_identity, secret_key) = get_test_signing_identity(TEST_CIPHER_SUITE, b"bob").await;

        let bob = TestClientBuilder::new_for_test()
            .signing_identity(bob_identity.clone(), secret_key, TEST_CIPHER_SUITE)
            .build();

        let proposal = bob
            .external_add_proposal(
                &alice_group.group.group_info_message(true).await.unwrap(),
                None,
                vec![],
            )
            .await
            .unwrap();

        let message = alice_group
            .group
            .process_incoming_message(proposal)
            .await
            .unwrap();

        assert_matches!(
            message,
            ReceivedMessage::Proposal(ProposalMessageDescription {
                proposal: Proposal::Add(p), ..}
            ) if p.key_package.leaf_node.signing_identity == bob_identity
        );

        alice_group.group.commit(vec![]).await.unwrap();
        alice_group.group.apply_pending_commit().await.unwrap();

        // Check that the new member is in the group
        assert!(alice_group
            .group
            .roster()
            .members_iter()
            .any(|member| member.signing_identity == bob_identity))
    }

    #[cfg(feature = "psk")]
    #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
    async fn join_via_external_commit(do_remove: bool, with_psk: bool) -> Result<(), MlsError> {
        // An external commit cannot be the first commit in a group as it requires
        // interim_transcript_hash to be computed from the confirmed_transcript_hash and
        // confirmation_tag, which is not the case for the initial interim_transcript_hash.

        let psk = PreSharedKey::from(b"psk".to_vec());
        let psk_id = ExternalPskId::new(b"psk id".to_vec());

        let mut alice_group =
            test_group_custom_config(TEST_PROTOCOL_VERSION, TEST_CIPHER_SUITE, |c| {
                c.psk(psk_id.clone(), psk.clone())
            })
            .await;

        let (mut bob_group, _) = alice_group
            .join_with_custom_config("bob", false, |c| {
                c.0.psk_store.insert(psk_id.clone(), psk.clone());
            })
            .await
            .unwrap();

        let group_info_msg = alice_group
            .group
            .group_info_message_allowing_ext_commit(true)
            .await
            .unwrap();

        let new_client_id = if do_remove { "bob" } else { "charlie" };

        let (new_client_identity, secret_key) =
            get_test_signing_identity(TEST_CIPHER_SUITE, new_client_id.as_bytes()).await;

        let new_client = TestClientBuilder::new_for_test()
            .psk(psk_id.clone(), psk)
            .signing_identity(new_client_identity.clone(), secret_key, TEST_CIPHER_SUITE)
            .build();

        let mut builder = new_client.external_commit_builder().unwrap();

        if do_remove {
            builder = builder.with_removal(1);
        }

        if with_psk {
            builder = builder.with_external_psk(psk_id);
        }

        let (new_group, external_commit) = builder.build(group_info_msg).await?;

        let num_members = if do_remove { 2 } else { 3 };

        assert_eq!(new_group.roster().members_iter().count(), num_members);

        let _ = alice_group
            .group
            .process_incoming_message(external_commit.clone())
            .await
            .unwrap();

        let bob_current_epoch = bob_group.group.current_epoch();

        let message = bob_group
            .group
            .process_incoming_message(external_commit)
            .await
            .unwrap();

        assert!(alice_group.group.roster().members_iter().count() == num_members);

        if !do_remove {
            assert!(bob_group.group.roster().members_iter().count() == num_members);
        } else {
            // Bob was removed so his epoch must stay the same
            assert_eq!(bob_group.group.current_epoch(), bob_current_epoch);

            #[cfg(feature = "state_update")]
            assert_matches!(message, ReceivedMessage::Commit(desc) if !desc.state_update.active);

            #[cfg(not(feature = "state_update"))]
            assert_matches!(message, ReceivedMessage::Commit(_));
        }

        // Comparing epoch authenticators is sufficient to check that members are in sync.
        assert_eq!(
            alice_group.group.epoch_authenticator().unwrap(),
            new_group.epoch_authenticator().unwrap()
        );

        Ok(())
    }

    #[cfg(feature = "psk")]
    #[maybe_async::test(not(mls_build_async), async(mls_build_async, crate::futures_test))]
    async fn test_external_commit() {
        // New member can join
        join_via_external_commit(false, false).await.unwrap();
        // New member can remove an old copy of themselves
        join_via_external_commit(true, false).await.unwrap();
        // New member can inject a PSK
        join_via_external_commit(false, true).await.unwrap();
        // All works together
        join_via_external_commit(true, true).await.unwrap();
    }

    #[maybe_async::test(not(mls_build_async), async(mls_build_async, crate::futures_test))]
    async fn creating_an_external_commit_requires_a_group_info_message() {
        let (alice_identity, secret_key) =
            get_test_signing_identity(TEST_CIPHER_SUITE, b"alice").await;

        let alice = TestClientBuilder::new_for_test()
            .signing_identity(alice_identity.clone(), secret_key, TEST_CIPHER_SUITE)
            .build();

        let msg = alice.generate_key_package_message().await.unwrap();
        let res = alice.commit_external(msg).await.map(|_| ());

        assert_matches!(res, Err(MlsError::UnexpectedMessageType));
    }

    #[maybe_async::test(not(mls_build_async), async(mls_build_async, crate::futures_test))]
    async fn external_commit_with_invalid_group_info_fails() {
        let mut alice_group = test_group(TEST_PROTOCOL_VERSION, TEST_CIPHER_SUITE).await;
        let mut bob_group = test_group(TEST_PROTOCOL_VERSION, TEST_CIPHER_SUITE).await;

        bob_group.group.commit(vec![]).await.unwrap();
        bob_group.group.apply_pending_commit().await.unwrap();

        let group_info_msg = bob_group
            .group
            .group_info_message_allowing_ext_commit(true)
            .await
            .unwrap();

        let (carol_identity, secret_key) =
            get_test_signing_identity(TEST_CIPHER_SUITE, b"carol").await;

        let carol = TestClientBuilder::new_for_test()
            .signing_identity(carol_identity, secret_key, TEST_CIPHER_SUITE)
            .build();

        let (_, external_commit) = carol
            .external_commit_builder()
            .unwrap()
            .build(group_info_msg)
            .await
            .unwrap();

        // If Carol tries to join Alice's group using the group info from Bob's group, that fails.
        let res = alice_group
            .group
            .process_incoming_message(external_commit)
            .await;
        assert_matches!(res, Err(_));
    }

    #[test]
    fn builder_can_be_obtained_from_client_to_edit_properties_for_new_client() {
        let alice = TestClientBuilder::new_for_test()
            .extension_type(33.into())
            .build();
        let bob = alice.to_builder().extension_type(34.into()).build();
        assert_eq!(bob.config.supported_extensions(), [33, 34].map(Into::into));
    }
}
