"""
Type stubs for the openmls_dave Rust extension module.
Not strictly necessary, but including this feels easier down the road,
especially because this points to Rust's bindings, at least in terms of pointing.
"""

from typing import List, Optional, Tuple

# Constants
DAVE_PROTOCOL_VERSION: int
SFRAME_LABEL: str
MEDIA_KEY_LENGTH: int

class MlsClient:
    """
    MLS client for identity management and key package generation.
    """

    @property
    def identity(self) -> bytes:
        """The client's identity bytes."""
        ...

    @property
    def identity_str(self) -> str:
        """The client's identity as a UTF-8 string."""
        ...

    @property
    def public_key(self) -> bytes:
        """The client's public signature key."""
        ...

    def __init__(self, identity: bytes) -> None:
        """
        Create a new MLS client with the given identity.

        Args:
            identity: The client's identity as bytes.
        """
        ...

    @staticmethod
    def from_string(identity_str: str) -> "MlsClient":
        """
        Create a new MLS client with a string identity.

        Args:
            identity_str: The client's identity as a string.

        Returns:
            A new MlsClient instance.
        """
        ...

    def generate_key_package(self) -> bytes:
        """
        Generate a key package for joining groups.

        Returns:
            Serialized key package bytes.
        """
        ...

    def generate_key_packages(self, count: int) -> List[bytes]:
        """
        Generate multiple key packages.

        Args:
            count: Number of key packages to generate.

        Returns:
            List of serialized key package bytes.
        """
        ...

    def __repr__(self) -> str: ...

class MlsGroupWrapper:
    """
    MLS group for managing encrypted group sessions.
    """

    @property
    def group_id(self) -> bytes:
        """The group's unique identifier."""
        ...

    @property
    def epoch(self) -> int:
        """The current epoch number."""
        ...

    @property
    def member_count(self) -> int:
        """Number of members in the group."""
        ...

    def __init__(self, client: MlsClient, group_id: bytes) -> None:
        """
        Create a new MLS group.

        Args:
            client: The MLS client creating the group.
            group_id: Unique identifier for the group.
        """
        ...

    @staticmethod
    def from_welcome(client: MlsClient, welcome_bytes: bytes) -> "MlsGroupWrapper":
        """
        Join an existing group via a Welcome message.

        Args:
            client: The MLS client joining the group.
            welcome_bytes: Serialized Welcome message.

        Returns:
            A new MlsGroupWrapper instance.
        """
        ...

    def members(self) -> List[bytes]:
        """
        Get the identities of all group members.

        Returns:
            List of member identity bytes.
        """
        ...

    def add_member(self, key_package_bytes: bytes) -> "CommitResult":
        """
        Add a member to the group.

        Args:
            key_package_bytes: The new member's serialized key package.

        Returns:
            CommitResult containing commit and welcome messages.
        """
        ...

    def add_members(self, key_packages: List[bytes]) -> "CommitResult":
        """
        Add multiple members to the group.

        Args:
            key_packages: List of serialized key packages.

        Returns:
            CommitResult containing commit and welcome messages.
        """
        ...

    def remove_member(self, identity: bytes) -> "CommitResult":
        """
        Remove a member from the group.

        Args:
            identity: The identity of the member to remove.

        Returns:
            CommitResult containing the commit message.
        """
        ...

    def self_update(self) -> "CommitResult":
        """
        Perform a self-update to refresh keys.

        Returns:
            CommitResult containing the commit message.
        """
        ...

    def process_message(self, message_bytes: bytes) -> "ProcessedMessage":
        """
        Process an incoming MLS message.

        Args:
            message_bytes: Serialized MLS message.

        Returns:
            ProcessedMessage with message type and sender info.
        """
        ...

    def export_secret(self, label: str, context: bytes, length: int) -> bytes:
        """
        Export a secret from the group's key schedule.

        Args:
            label: The label for the exported secret.
            context: Additional context for derivation.
            length: Desired length of the secret in bytes.

        Returns:
            The derived secret bytes.
        """
        ...

    def derive_media_key(self) -> bytes:
        """
        Derive the media encryption key for DAVE.

        Returns:
            32-byte media key.
        """
        ...

    def derive_sender_key(self, sender_id: int) -> bytes:
        """
        Derive a sender-specific key.

        Args:
            sender_id: The sender's identifier.

        Returns:
            32-byte sender key.
        """
        ...

    def get_epoch_authenticator(self) -> bytes:
        """
        Get the epoch authenticator for verification.

        Returns:
            The epoch authenticator bytes.
        """
        ...

    def merge_pending_commit(self) -> None:
        """
        Merge a pending commit after sending.
        """
        ...

    def export_ratchet_tree(self) -> bytes:
        """
        Export the ratchet tree for out-of-band distribution.

        Returns:
            Serialized ratchet tree bytes.
        """
        ...

    def __repr__(self) -> str: ...

class CommitResult:
    """
    Result of an MLS commit operation.
    """

    @property
    def commit_message(self) -> bytes:
        """The serialized commit message."""
        ...

    @property
    def welcome_message(self) -> Optional[bytes]:
        """The serialized Welcome message, if any."""
        ...

    @property
    def group_info(self) -> Optional[bytes]:
        """The serialized GroupInfo, if any."""
        ...

class ProcessedMessage:
    """
    Result of processing an MLS message.
    """

    @property
    def message_type(self) -> str:
        """
        The type of message: "application", "proposal", "commit", or "external_join".
        """
        ...

    @property
    def sender_identity(self) -> Optional[bytes]:
        """The sender's identity, if available."""
        ...

    @property
    def epoch(self) -> int:
        """The epoch after processing the message."""
        ...

class SFrameHeader:
    """
    SFrame header containing key ID and counter.
    """

    @property
    def key_id(self) -> int:
        """The key identifier."""
        ...

    @property
    def counter(self) -> int:
        """The frame counter."""
        ...

    def __init__(self, key_id: int, counter: int) -> None:
        """
        Create a new SFrame header.

        Args:
            key_id: The key identifier.
            counter: The frame counter.
        """
        ...

    def serialize(self) -> bytes:
        """
        Serialize the header to bytes.

        Returns:
            Serialized header bytes.
        """
        ...

    @staticmethod
    def parse(data: bytes) -> Tuple["SFrameHeader", int]:
        """
        Parse an SFrame header from bytes.

        Args:
            data: The data containing the header.

        Returns:
            Tuple of (parsed header, bytes consumed).
        """
        ...

class SFrameContext:
    """
    SFrame encryption context for a single key.
    """

    @property
    def key_id(self) -> int:
        """The key identifier for this context."""
        ...

    @property
    def current_counter(self) -> int:
        """The current frame counter."""
        ...

    def __init__(self, base_key: bytes, key_id: int) -> None:
        """
        Create a new SFrame context.

        Args:
            base_key: The base key for encryption (minimum 16 bytes).
            key_id: The key identifier.
        """
        ...

    def encrypt(self, plaintext: bytes) -> bytes:
        """
        Encrypt a frame, auto-incrementing the counter.

        Args:
            plaintext: The plaintext frame data.

        Returns:
            Encrypted frame with header.
        """
        ...

    def encrypt_with_counter(self, plaintext: bytes, counter: int) -> bytes:
        """
        Encrypt a frame with a specific counter.

        Args:
            plaintext: The plaintext frame data.
            counter: The counter value to use.

        Returns:
            Encrypted frame with header.
        """
        ...

    def decrypt(self, ciphertext: bytes) -> Tuple[bytes, SFrameHeader]:
        """
        Decrypt a frame.

        Args:
            ciphertext: The encrypted frame with header.

        Returns:
            Tuple of (plaintext, header).

        Raises:
            ValueError: If the key ID doesn't match or decryption fails.
        """
        ...

    def set_counter(self, counter: int) -> None:
        """
        Set the current counter value.

        Args:
            counter: The new counter value.
        """
        ...

    def __repr__(self) -> str: ...

class SFrameMultiContext:
    """
    Multi-sender SFrame context for handling multiple keys.
    """

    def __init__(self, local_key_id: int) -> None:
        """
        Create a new multi-sender SFrame context.

        Args:
            local_key_id: The local sender's key ID.
        """
        ...

    def add_sender(self, key_id: int, base_key: bytes) -> None:
        """
        Add a sender's key.

        Args:
            key_id: The sender's key ID.
            base_key: The sender's base key.
        """
        ...

    def remove_sender(self, key_id: int) -> None:
        """
        Remove a sender's key.

        Args:
            key_id: The sender's key ID to remove.
        """
        ...

    def encrypt(self, plaintext: bytes) -> bytes:
        """
        Encrypt a frame using the local key.

        Args:
            plaintext: The plaintext frame data.

        Returns:
            Encrypted frame with header.
        """
        ...

    def decrypt(self, ciphertext: bytes) -> Tuple[bytes, SFrameHeader]:
        """
        Decrypt a frame from any registered sender.

        Args:
            ciphertext: The encrypted frame with header.

        Returns:
            Tuple of (plaintext, header).

        Raises:
            ValueError: If the sender is unknown or decryption fails.
        """
        ...

    def has_sender(self, key_id: int) -> bool:
        """
        Check if a sender is registered.

        Args:
            key_id: The sender's key ID.

        Returns:
            True if the sender is registered.
        """
        ...

    def sender_count(self) -> int:
        """
        Get the number of registered senders.

        Returns:
            Number of senders.
        """
        ...

class KeyRatchet:
    """
    Key ratchet for forward-secure key derivation.
    """

    @property
    def generation(self) -> int:
        """The current generation number."""
        ...

    def __init__(self, base_key: bytes, max_cached: int = 16) -> None:
        """
        Create a new key ratchet.

        Args:
            base_key: The base key (minimum 32 bytes).
            max_cached: Maximum number of keys to cache.
        """
        ...

    def get_key(self, generation: int) -> bytes:
        """
        Get the key for a specific generation.

        Args:
            generation: The generation number.

        Returns:
            32-byte key for the generation.
        """
        ...

    def current_key(self) -> bytes:
        """
        Get the key for the current generation.

        Returns:
            32-byte key.
        """
        ...

    def ratchet(self) -> bytes:
        """
        Advance to the next generation and return its key.

        Returns:
            32-byte key for the new generation.
        """
        ...

    def ratchet_to(self, generation: int) -> bytes:
        """
        Advance to a specific generation.

        Args:
            generation: The target generation (must be >= current).

        Returns:
            32-byte key for the target generation.

        Raises:
            RuntimeError: If generation is in the past or too far ahead.
        """
        ...

    def truncate_cache(self, min_generation: int) -> None:
        """
        Remove cached keys older than the given generation.

        Args:
            min_generation: Minimum generation to keep.
        """
        ...

    def clear_cache(self) -> None:
        """
        Clear all cached keys.
        """
        ...

class SenderKeyRatchet:
    """
    Per-sender key ratchet.
    """

    @property
    def sender_id(self) -> int:
        """The sender's identifier."""
        ...

    @property
    def generation(self) -> int:
        """The current generation number."""
        ...

    def __init__(self, sender_id: int, base_key: bytes) -> None:
        """
        Create a new sender key ratchet.

        Args:
            sender_id: The sender's identifier.
            base_key: The base key (minimum 32 bytes).
        """
        ...

    def get_key(self, generation: int) -> bytes:
        """
        Get the key for a specific generation.

        Args:
            generation: The generation number.

        Returns:
            32-byte key.
        """
        ...

    def ratchet(self) -> bytes:
        """
        Advance to the next generation.

        Returns:
            32-byte key for the new generation.
        """
        ...

class KeyRatchetManager:
    """
    Manager for multiple sender key ratchets.
    """

    def __init__(self, epoch_base_key: bytes) -> None:
        """
        Create a new key ratchet manager.

        Args:
            epoch_base_key: The base key for the epoch.
        """
        ...

    def get_or_create_ratchet(self, sender_id: int) -> None:
        """
        Ensure a ratchet exists for the given sender.

        Args:
            sender_id: The sender's identifier.
        """
        ...

    def get_key(self, sender_id: int, generation: int) -> bytes:
        """
        Get a key for a specific sender and generation.

        Args:
            sender_id: The sender's identifier.
            generation: The generation number.

        Returns:
            32-byte key.
        """
        ...

    def remove_sender(self, sender_id: int) -> None:
        """
        Remove a sender's ratchet.

        Args:
            sender_id: The sender's identifier.
        """
        ...

    def clear(self) -> None:
        """
        Remove all sender ratchets.
        """
        ...
