// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use bytes::Bytes;
use iggy::prelude::{
    AutoCommit as RustAutoCommit, Consumer as RustConsumer, IggyClient as RustIggyClient,
    IggyExpiry as RustIggyExpiry, IggyMessage as RustMessage, MaxTopicSize as RustMaxTopicSize,
    PollingStrategy as RustPollingStrategy, *,
};
use pyo3::PyRef;
use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyDelta, PyList, PyType};
use pyo3_async_runtimes::tokio::future_into_py;
use pyo3_stub_gen::define_stub_info_gatherer;
use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods};
use std::collections::BTreeMap;
use std::str::FromStr;
use std::sync::Arc;

use crate::config::PyClientConfig;
use crate::consumer::{
    AutoCommit, Consumer as PyConsumer, ConsumerGroup as PyConsumerGroup,
    ConsumerGroupDetails as PyConsumerGroupDetails, IggyConsumer,
};
use crate::duration::{py_delta_to_iggy_duration, reject_zero};
use crate::identifier::PyIdentifier;
use crate::options::OptionSpec as PyOptionSpec;
use crate::permissions::Permissions as PyPermissions;
use crate::receive_message::{PollingStrategy, ReceiveMessage};
use crate::send_message::{SendMessage, SendMessagesResponse as PySendMessagesResponse};
use crate::stream::{Stream, StreamDetails};
use crate::topic::{IggyExpiry, MaxTopicSize, Topic, TopicDetails};
use crate::user::{
    UserInfo as PyUserInfo, UserInfoDetails as PyUserInfoDetails, UserStatus as PyUserStatus,
};
use tokio::sync::Mutex;

/// A Python class representing the Iggy client.
/// It provides asynchronous functionality through the contained runtime.
#[gen_stub_pyclass]
#[pyclass]
pub struct IggyClient {
    inner: Arc<RustIggyClient>,
}

/// Resolves the shared `create_topic`/`update_topic` parameters, applying
/// server defaults where the caller left them unset.
fn resolve_topic_params(
    compression_algorithm: Option<String>,
    message_expiry: Option<&IggyExpiry>,
    max_topic_size: Option<&MaxTopicSize>,
) -> PyResult<(CompressionAlgorithm, RustIggyExpiry, RustMaxTopicSize)> {
    let compression_algorithm = match compression_algorithm {
        Some(algo) => CompressionAlgorithm::from_str(&algo)
            .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?,
        None => CompressionAlgorithm::default(),
    };

    let expiry = message_expiry
        .map(RustIggyExpiry::try_from)
        .transpose()?
        .unwrap_or(RustIggyExpiry::ServerDefault);

    let max_size = max_topic_size
        .map(RustMaxTopicSize::try_from)
        .transpose()?
        .unwrap_or(RustMaxTopicSize::ServerDefault);

    Ok((compression_algorithm, expiry, max_size))
}

#[gen_stub_pymethods]
#[pymethods]
impl IggyClient {
    /// Constructs a new IggyClient from a TCP server address or a `TcpConfig`.
    /// This initializes a new runtime for asynchronous operations.
    /// Future versions might utilize asyncio for more Pythonic async.
    ///
    /// Args:
    ///     conn: Either a `host:port` address, or a `TcpConfig` carrying the full
    ///         transport configuration. Defaults to `127.0.0.1:8090` with auto-login
    ///         disabled. A malformed address is reported differently by the two
    ///         forms: the string form raises `RuntimeError` here, while `TcpConfig`
    ///         raises `ValueError` when it is constructed, before it ever reaches
    ///         this call. Neither exception is a subclass of the other.
    ///
    /// Raises:
    ///     RuntimeError: If the address passed as a string is not a valid
    ///         `host:port` pair.
    #[new]
    #[pyo3(signature = (conn=None))]
    fn new(
        #[gen_stub(override_type(type_repr = "TcpConfig | builtins.str | None"))] conn: Option<
            PyClientConfig,
        >,
    ) -> PyResult<Self> {
        let config = match conn {
            Some(PyClientConfig::Config(config)) => config.client_config(),
            Some(PyClientConfig::ServerAddress(server_address)) => Arc::new(
                TcpClientConfigBuilder::new()
                    .with_server_address(server_address)
                    .build()
                    .map_err(|e| {
                        PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string())
                    })?,
            ),
            None => Arc::new(TcpClientConfig::default()),
        };
        let tcp_client = TcpClient::create(config)
            .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
        Ok(IggyClient {
            inner: Arc::new(RustIggyClient::new(ClientWrapper::Tcp(tcp_client))),
        })
    }

    /// Constructs a new IggyClient from a connection string.
    /// Returns an error if the connection string provided is invalid.
    // TODO: add examples for connection strings or at least a link to the doc page where
    // connection strings are explained.
    #[classmethod]
    #[pyo3(signature = (connection_string))]
    fn from_connection_string(
        _cls: &Bound<'_, PyType>,
        connection_string: String,
    ) -> PyResult<Self> {
        let client = RustIggyClient::from_connection_string(&connection_string)
            .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
        Ok(Self {
            inner: Arc::new(client),
        })
    }

    /// Sends a ping request to the server to check connectivity.
    /// Raises `RuntimeError` if the connection fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn ping<'a>(&self, py: Python<'a>) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();
        future_into_py(py, async move {
            inner
                .ping()
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))
        })
    }

    /// Describe the option catalog for a resource scope.
    ///
    /// This is the discovery surface for the `options` argument on
    /// `create_topic`/`update_topic`: a key outside the catalog is refused at
    /// create, and the binary transports carry only the error code back.
    ///
    /// Args:
    ///     scope: One of `"topic"`, `"stream"`, `"user"`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `list[OptionSpec]`, empty for a scope
    ///     with no keys yet.
    ///
    /// Raises:
    ///     ValueError: If the scope name is not one of the three above.
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[list[OptionSpec]]", imports=("collections.abc")))]
    fn describe_options<'a>(&self, py: Python<'a>, scope: &str) -> PyResult<Bound<'a, PyAny>> {
        let scope = crate::options::options_scope_from_str(scope)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let specs = inner
                .describe_options(scope)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(specs
                .into_iter()
                .map(PyOptionSpec::from)
                .collect::<Vec<_>>())
        })
    }

    /// Logs in the user with the given credentials.
    /// Raises `RuntimeError` on failure.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn login_user<'a>(
        &self,
        py: Python<'a>,
        username: String,
        password: String,
    ) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();
        future_into_py(py, async move {
            inner
                .login_user(&username, &password)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Get the info about a specific user by unique ID or username.
    ///
    /// Args:
    ///     user_id: User identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `UserInfoDetails` if the user exists,
    ///     or `None` otherwise.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[UserInfoDetails | None]", imports=("collections.abc")))]
    fn get_user<'a>(&self, py: Python<'a>, user_id: PyIdentifier) -> PyResult<Bound<'a, PyAny>> {
        let user_id = Identifier::try_from(user_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let user = inner
                .get_user(&user_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(user.map(PyUserInfoDetails::from))
        })
    }

    /// Get the info about all the users.
    ///
    /// Returns:
    ///     An awaitable that resolves to `list[UserInfo]`.
    ///
    /// Raises:
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[list[UserInfo]]", imports=("collections.abc")))]
    fn get_users<'a>(&self, py: Python<'a>) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let users = inner
                .get_users()
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(users.into_iter().map(PyUserInfo::from).collect::<Vec<_>>())
        })
    }

    /// Create a new user.
    ///
    /// Args:
    ///     username: Username as `str`.
    ///     password: Password as `str`.
    ///     status: User status as `UserStatus | None`; defaults to `UserStatus.Active`.
    ///     permissions: Permissions as `Permissions | None`; the user has none when `None`.
    ///
    /// Returns:
    ///     An awaitable that resolves to the created `UserInfoDetails`.
    ///
    /// Raises:
    ///     RuntimeError: If an argument is invalid or the request fails.
    #[pyo3(signature = (username, password, status=None, permissions=None))]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[UserInfoDetails]", imports=("collections.abc")))]
    fn create_user<'a>(
        &self,
        py: Python<'a>,
        username: String,
        password: String,
        #[gen_stub(override_type(type_repr = "UserStatus | None"))] status: Option<PyUserStatus>,
        #[gen_stub(override_type(type_repr = "Permissions | None"))] permissions: Option<
            PyPermissions,
        >,
    ) -> PyResult<Bound<'a, PyAny>> {
        let status = status.map_or(UserStatus::Active, UserStatus::from);
        let permissions = permissions.map(|permissions| permissions.inner);
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let user = inner
                .create_user(&username, &password, status, permissions)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(PyUserInfoDetails::from(user))
        })
    }

    /// Update a user by unique ID or username.
    ///
    /// Args:
    ///     user_id: User identifier as `str | int`.
    ///     username: New username as `str | None`; unchanged when `None`.
    ///     status: New status as `UserStatus | None`; unchanged when `None`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the user is updated.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[pyo3(signature = (user_id, username=None, status=None))]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn update_user<'a>(
        &self,
        py: Python<'a>,
        user_id: PyIdentifier,
        #[gen_stub(override_type(type_repr = "builtins.str | None"))] username: Option<String>,
        #[gen_stub(override_type(type_repr = "UserStatus | None"))] status: Option<PyUserStatus>,
    ) -> PyResult<Bound<'a, PyAny>> {
        let user_id = Identifier::try_from(user_id)?;
        let status = status.map(UserStatus::from);
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .update_user(
                    &user_id,
                    username.as_deref(),
                    status,
                    // Users have no option keys yet.
                    &UserUpdateOptions::default(),
                )
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Delete a user by unique ID or username.
    ///
    /// Args:
    ///     user_id: User identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the user is deleted.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn delete_user<'a>(&self, py: Python<'a>, user_id: PyIdentifier) -> PyResult<Bound<'a, PyAny>> {
        let user_id = Identifier::try_from(user_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .delete_user(&user_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Update the permissions of a user by unique ID or username.
    ///
    /// This is a full replacement: the given permissions overwrite the previous
    /// ones, and `None` removes them entirely.
    ///
    /// Args:
    ///     user_id: User identifier as `str | int`.
    ///     permissions: New permissions as `Permissions | None`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the permissions are updated.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[pyo3(signature = (user_id, permissions))]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn update_permissions<'a>(
        &self,
        py: Python<'a>,
        user_id: PyIdentifier,
        #[gen_stub(override_type(type_repr = "Permissions | None"))] permissions: Option<
            PyPermissions,
        >,
    ) -> PyResult<Bound<'a, PyAny>> {
        let user_id = Identifier::try_from(user_id)?;
        let permissions = permissions.map(|permissions| permissions.inner);
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .update_permissions(&user_id, permissions)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Change the password of a user by unique ID or username.
    ///
    /// Args:
    ///     user_id: User identifier as `str | int`.
    ///     current_password: Current password as `str`.
    ///     new_password: New password as `str`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the password is changed.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the current password is wrong or the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn change_password<'a>(
        &self,
        py: Python<'a>,
        user_id: PyIdentifier,
        current_password: String,
        new_password: String,
    ) -> PyResult<Bound<'a, PyAny>> {
        let user_id = Identifier::try_from(user_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .change_password(&user_id, &current_password, &new_password)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Log out the currently authenticated user.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the user is logged out.
    ///
    /// Raises:
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn logout_user<'a>(&self, py: Python<'a>) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .logout_user()
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Connects the IggyClient to its service.
    /// Raises `RuntimeError` if the connection fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn connect<'a>(&self, py: Python<'a>) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();
        future_into_py(py, async move {
            inner
                .connect()
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Creates a new stream with the provided ID and name.
    /// Raises `RuntimeError` if the stream cannot be created.
    #[pyo3(signature = (name))]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn create_stream<'a>(&self, py: Python<'a>, name: String) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();
        future_into_py(py, async move {
            inner
                .create_stream(&name)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Gets stream by id.
    /// Returns the stream details, or `None` if the stream does not exist.
    /// Raises `RuntimeError` on failure.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[StreamDetails | None]", imports=("collections.abc")))]
    fn get_stream<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let stream = inner
                .get_stream(&stream_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(stream.map(StreamDetails::from))
        })
    }

    /// Return all streams.
    ///
    /// Returns:
    ///     A list of `Stream` summaries.
    ///
    /// Raises:
    ///     RuntimeError: If the client is not authenticated, the user lacks global
    ///         `read_streams` or `manage_streams` permission, or the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[list[Stream]]", imports=("collections.abc")))]
    fn get_streams<'a>(&self, py: Python<'a>) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();
        future_into_py(py, async move {
            let streams = inner
                .get_streams()
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(streams.into_iter().map(Stream::from).collect::<Vec<_>>())
        })
    }

    /// Rename a stream selected by name or numeric ID.
    ///
    /// `stream_id` accepts a stream name as `str` or numeric ID as `int`. A
    /// decimal-only string is interpreted as a numeric ID. `name` must be unique
    /// and contain between 1 and 255 UTF-8 bytes. Renaming a stream to its current
    /// name succeeds without changing it.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     name: New stream name as `str`.
    ///     options: Additional option keys as `dict[str, str] | None`, forwarded
    ///         to the server. Current server versions reject all stream update
    ///         option keys.
    ///
    /// Returns:
    ///     None.
    ///
    /// Raises:
    ///     TypeError: If `stream_id` is not `str` or an integer in
    ///         `0..=2**32 - 1`, or `name` is not `str`.
    ///     ValueError: If a string identifier is empty or exceeds 255 UTF-8 bytes.
    ///     RuntimeError: If the client is not authenticated, the user lacks global
    ///         `manage_streams` or per-stream `manage_stream` permission, the
    ///         stream does not exist, the new name is invalid or already used, or
    ///         the request fails.
    #[pyo3(signature = (stream_id, name, options = None))]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn update_stream<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        name: String,
        #[gen_stub(override_type(type_repr = "builtins.dict[builtins.str, builtins.str] | None"))]
        options: Option<BTreeMap<String, String>>,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let update_options = StreamUpdateOptions {
            raw: options.unwrap_or_default(),
        };
        let inner = self.inner.clone();
        future_into_py(py, async move {
            inner
                .update_stream(&stream_id, &name, &update_options)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Delete a stream selected by name or numeric ID.
    ///
    /// Deletion removes the stream and all of its topics, partitions, and messages.
    /// `stream_id` accepts a stream name as `str` or numeric ID as `int`. A
    /// decimal-only string is interpreted as a numeric ID.
    ///
    /// Returns:
    ///     None.
    ///
    /// Raises:
    ///     TypeError: If `stream_id` is not `str` or an integer in
    ///         `0..=2**32 - 1`.
    ///     ValueError: If a string identifier is empty or exceeds 255 UTF-8 bytes.
    ///     RuntimeError: If the client is not authenticated, the user lacks global
    ///         `manage_streams` or per-stream `manage_stream` permission, the
    ///         stream does not exist, or the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn delete_stream<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let inner = self.inner.clone();
        future_into_py(py, async move {
            inner
                .delete_stream(&stream_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Delete all messages from every topic in a stream.
    ///
    /// The stream, topics, and partitions remain available. Repeated purges of an
    /// existing empty stream succeed. `stream_id` accepts a stream name as `str`
    /// or numeric ID as `int`. A decimal-only string is interpreted as a numeric
    /// ID.
    ///
    /// Returns:
    ///     None.
    ///
    /// Raises:
    ///     TypeError: If `stream_id` is not `str` or an integer in
    ///         `0..=2**32 - 1`.
    ///     ValueError: If a string identifier is empty or exceeds 255 UTF-8 bytes.
    ///     RuntimeError: If the client is not authenticated, the user lacks global
    ///         `manage_streams` or per-stream `manage_stream` permission, the
    ///         stream does not exist, or the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn purge_stream<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let inner = self.inner.clone();
        future_into_py(py, async move {
            inner
                .purge_stream(&stream_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Creates a new topic with the given parameters.
    ///
    /// Args:
    ///     stream: Stream identifier as `str | int`.
    ///     name: Topic name as `str`.
    ///     partitions_count: Number of partitions as `int`.
    ///     compression_algorithm: Compression algorithm as `str | None`.
    ///     message_expiry: Message expiry as `IggyExpiry | None`.
    ///     max_topic_size: Maximum topic size as `MaxTopicSize | None`.
    ///     segment_size: Per-topic segment size in bytes as `int | None`.
    ///     enforce_fsync: Per-topic fsync enforcement as `bool | None`.
    ///     messages_required_to_save: Message-count flush threshold as `int | None`.
    ///     size_of_messages_required_to_save: Byte flush threshold as `int | None`.
    ///     preallocate_segments: Reserve segment bytes on open as `bool | None`.
    ///     options: Additional option keys as `dict[str, str] | None`, sent
    ///         verbatim so a newer server key can be set from this build.
    ///
    /// Every option left as `None` resolves against the server default at
    /// admission.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the topic is created.
    ///
    /// Raises:
    ///     ValueError: If `message_expiry` or `max_topic_size` is out of range.
    ///     PyRuntimeError: If another argument is invalid or the request fails.
    #[pyo3(
        signature = (stream, name, partitions_count, compression_algorithm = None, message_expiry = None, max_topic_size = None, segment_size = None, enforce_fsync = None, messages_required_to_save = None, size_of_messages_required_to_save = None, preallocate_segments = None, options = None)
    )]
    #[allow(clippy::too_many_arguments)]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn create_topic<'a>(
        &self,
        py: Python<'a>,
        stream: PyIdentifier,
        name: String,
        partitions_count: u32,
        #[gen_stub(override_type(type_repr = "builtins.str | None"))] compression_algorithm: Option<
            String,
        >,
        #[gen_stub(override_type(type_repr = "IggyExpiry | None"))] message_expiry: Option<
            &IggyExpiry,
        >,
        #[gen_stub(override_type(type_repr = "MaxTopicSize | None"))] max_topic_size: Option<
            &MaxTopicSize,
        >,
        #[gen_stub(override_type(type_repr = "builtins.int | None"))] segment_size: Option<u64>,
        #[gen_stub(override_type(type_repr = "builtins.bool | None"))] enforce_fsync: Option<bool>,
        #[gen_stub(override_type(type_repr = "builtins.int | None"))]
        messages_required_to_save: Option<u32>,
        #[gen_stub(override_type(type_repr = "builtins.int | None"))]
        size_of_messages_required_to_save: Option<u64>,
        #[gen_stub(override_type(type_repr = "builtins.bool | None"))] preallocate_segments: Option<
            bool,
        >,
        #[gen_stub(override_type(type_repr = "builtins.dict[builtins.str, builtins.str] | None"))]
        options: Option<BTreeMap<String, String>>,
    ) -> PyResult<Bound<'a, PyAny>> {
        let (compression_algorithm, expiry, max_size) =
            resolve_topic_params(compression_algorithm, message_expiry, max_topic_size)?;

        let topic_options = TopicCreateOptions {
            partitions_count: Some(partitions_count),
            // `None` is what tells admission to resolve the server default, so
            // the sentinels the resolver returns must collapse back to it.
            compression_algorithm: (compression_algorithm != CompressionAlgorithm::default())
                .then_some(compression_algorithm),
            message_expiry: (expiry != RustIggyExpiry::ServerDefault).then_some(expiry),
            max_topic_size: (max_size != RustMaxTopicSize::ServerDefault).then_some(max_size),
            segment_size: segment_size.map(IggyByteSize::from),
            enforce_fsync,
            messages_required_to_save,
            size_of_messages_required_to_save: size_of_messages_required_to_save
                .map(IggyByteSize::from),
            preallocate_segments,
            raw: options.unwrap_or_default(),
        };

        let stream = Identifier::try_from(stream)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .create_topic(&stream, &name, &topic_options)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Gets topic by stream and id.
    /// Returns the topic details, or `None` if the topic does not exist.
    /// Raises `RuntimeError` on failure.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[TopicDetails | None]", imports=("collections.abc")))]
    fn get_topic<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let topic = inner
                .get_topic(&stream_id, &topic_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(topic.map(TopicDetails::from))
        })
    }

    /// Get all topics in a stream.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `list[Topic]`.
    ///
    /// Raises:
    ///     RuntimeError: If the identifier is invalid or the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[list[Topic]]", imports=("collections.abc")))]
    fn get_topics<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let topics = inner
                .get_topics(&stream_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(topics.into_iter().map(Topic::from).collect::<Vec<_>>())
        })
    }

    /// Update an existing topic.
    ///
    /// A patch, not a replacement: every setting rides the options block, so a
    /// field left unset keeps the topic's current value rather than resetting
    /// it to a server default.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///     name: New topic name as `str`.
    ///     compression_algorithm: Compression algorithm as `str | None`.
    ///     message_expiry: Message expiry as `IggyExpiry | None`.
    ///     max_topic_size: Maximum topic size as `MaxTopicSize | None`.
    ///     options: Additional option keys as `dict[str, str] | None`, sent
    ///         verbatim so an updatable server key can be set from this build.
    ///         A create-only key is refused by name.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the topic is updated.
    ///
    /// Raises:
    ///     ValueError: If `message_expiry` or `max_topic_size` is out of range.
    ///     PyRuntimeError: If another argument is invalid or the request fails.
    #[pyo3(
        signature = (stream_id, topic_id, name, compression_algorithm = None, message_expiry = None, max_topic_size = None, options = None)
    )]
    #[allow(clippy::too_many_arguments)]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn update_topic<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
        name: String,
        #[gen_stub(override_type(type_repr = "builtins.str | None"))] compression_algorithm: Option<
            String,
        >,
        #[gen_stub(override_type(type_repr = "IggyExpiry | None"))] message_expiry: Option<
            &IggyExpiry,
        >,
        #[gen_stub(override_type(type_repr = "MaxTopicSize | None"))] max_topic_size: Option<
            &MaxTopicSize,
        >,
        #[gen_stub(override_type(type_repr = "builtins.dict[builtins.str, builtins.str] | None"))]
        options: Option<BTreeMap<String, String>>,
    ) -> PyResult<Bound<'a, PyAny>> {
        // Absent stays absent: a key the caller did not pass is left alone
        // server-side rather than reset to a default.
        let compression_algorithm = compression_algorithm
            .map(|algo| {
                CompressionAlgorithm::from_str(&algo)
                    .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))
            })
            .transpose()?;
        let update_options = TopicUpdateOptions {
            compression_algorithm,
            message_expiry: message_expiry.map(RustIggyExpiry::try_from).transpose()?,
            max_topic_size: max_topic_size.map(RustMaxTopicSize::try_from).transpose()?,
            raw: options.unwrap_or_default(),
        };

        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .update_topic(&stream_id, &topic_id, &name, &update_options)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Delete a topic from a stream.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the topic is deleted.
    ///
    /// Raises:
    ///     RuntimeError: If an identifier is invalid or the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn delete_topic<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .delete_topic(&stream_id, &topic_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Purge all messages from a topic.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the topic is purged.
    ///
    /// Raises:
    ///     RuntimeError: If an identifier is invalid or the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn purge_topic<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .purge_topic(&stream_id, &topic_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Create a consumer group for a stream and topic.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///     name: Consumer group name as `str`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the consumer group is created.
    ///
    /// Raises:
    ///     ValueError: If an identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn create_consumer_group<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
        name: String,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .create_consumer_group(&stream_id, &topic_id, &name)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Retrieve details for a consumer group from the specified stream and topic.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///     group_id: Consumer group identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `ConsumerGroupDetails` if the consumer group exists,
    ///     or `None` otherwise.
    ///
    /// Raises:
    ///     ValueError: If an identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[ConsumerGroupDetails | None]", imports=("collections.abc")))]
    fn get_consumer_group<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
        group_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let group_id = Identifier::try_from(group_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let group = inner
                .get_consumer_group(&stream_id, &topic_id, &group_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(group.map(PyConsumerGroupDetails::from))
        })
    }

    /// Get all consumer groups for the specified stream and topic.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `list[ConsumerGroup]`.
    ///
    /// Raises:
    ///     ValueError: If an identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[list[ConsumerGroup]]", imports=("collections.abc")))]
    fn get_consumer_groups<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let groups = inner
                .get_consumer_groups(&stream_id, &topic_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(groups
                .into_iter()
                .map(PyConsumerGroup::from)
                .collect::<Vec<_>>())
        })
    }

    /// Delete a consumer group for a stream and topic.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///     group_id: Consumer group identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the consumer group is deleted.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the request fails.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn delete_consumer_group<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
        group_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let group_id = Identifier::try_from(group_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .delete_consumer_group(&stream_id, &topic_id, &group_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Join a consumer group for a stream and topic.
    ///
    /// This method only registers the current client as a group member. To consume messages
    /// as a group, use `consumer_group()`, which enables auto-join by default.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///     group_id: Consumer group identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the client joins the consumer group.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the request fails, including `Feature is unavailable` on HTTP transport.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn join_consumer_group<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
        group_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let group_id = Identifier::try_from(group_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .join_consumer_group(&stream_id, &topic_id, &group_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Leave a consumer group for a stream and topic.
    ///
    /// Args:
    ///     stream_id: Stream identifier as `str | int`.
    ///     topic_id: Topic identifier as `str | int`.
    ///     group_id: Consumer group identifier as `str | int`.
    ///
    /// Returns:
    ///     An awaitable that resolves to `None` when the client leaves the consumer group.
    ///
    /// Note:
    ///     Consumers created from this client for the same group share one server-side
    ///     membership. Leaving revokes that membership. Consumers with auto-join enabled
    ///     rejoin on their next poll.
    ///
    /// Raises:
    ///     ValueError: If a string identifier is invalid.
    ///     RuntimeError: If the request fails, including `Feature is unavailable` on HTTP transport.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[None]", imports=("collections.abc")))]
    fn leave_consumer_group<'a>(
        &self,
        py: Python<'a>,
        stream_id: PyIdentifier,
        topic_id: PyIdentifier,
        group_id: PyIdentifier,
    ) -> PyResult<Bound<'a, PyAny>> {
        let stream_id = Identifier::try_from(stream_id)?;
        let topic_id = Identifier::try_from(topic_id)?;
        let group_id = Identifier::try_from(group_id)?;
        let inner = self.inner.clone();

        future_into_py(py, async move {
            inner
                .leave_consumer_group(&stream_id, &topic_id, &group_id)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(())
        })
    }

    /// Sends a list of messages to the specified topic.
    /// Returns a SendMessagesResponse carrying the per-partition commit
    /// confirmations, or a PyRuntimeError on failure. The confirmation list is
    /// empty when the server reports no offsets, and the legacy server never
    /// reports any.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[SendMessagesResponse]", imports=("collections.abc")))]
    fn send_messages<'a>(
        &self,
        py: Python<'a>,
        stream: PyIdentifier,
        topic: PyIdentifier,
        partitioning: u32,
        #[gen_stub(override_type(type_repr = "list[SendMessage]"))] messages: &Bound<'_, PyList>,
    ) -> PyResult<Bound<'a, PyAny>> {
        let messages: Vec<SendMessage> = messages
            .iter()
            .map(|item| {
                let msg: PyRef<'_, SendMessage> = item.extract()?;
                Ok::<_, PyErr>(msg.clone())
            })
            .collect::<Result<Vec<_>, _>>()?;
        let mut messages: Vec<RustMessage> = messages
            .into_iter()
            .map(|message| message.inner)
            .collect::<Vec<_>>();

        let stream = Identifier::try_from(stream)?;
        let topic = Identifier::try_from(topic)?;
        let partitioning = Partitioning::partition_id(partitioning);
        let inner = self.inner.clone();

        future_into_py(py, async move {
            let response = inner
                .send_messages(&stream, &topic, &partitioning, messages.as_mut())
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(PySendMessagesResponse::from(response))
        })
    }

    /// Polls for messages from the specified topic on behalf of the given consumer.
    /// Omitting `partition_id` reads partition 0 for a regular consumer, and
    /// polls the member's assigned partitions for a consumer group.
    /// Returns a list of received messages or a RuntimeError on failure.
    #[allow(clippy::too_many_arguments)]
    #[pyo3(signature = (stream, topic, *, consumer, polling_strategy, count, auto_commit, partition_id = None))]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[list[ReceiveMessage]]", imports=("collections.abc")))]
    fn poll_messages<'a>(
        &self,
        py: Python<'a>,
        stream: PyIdentifier,
        topic: PyIdentifier,
        consumer: &PyConsumer,
        polling_strategy: &PollingStrategy,
        count: u32,
        auto_commit: bool,
        partition_id: Option<u32>,
    ) -> PyResult<Bound<'a, PyAny>> {
        let consumer = RustConsumer::try_from(consumer)?;
        let stream = Identifier::try_from(stream)?;
        let topic = Identifier::try_from(topic)?;
        let strategy: RustPollingStrategy = polling_strategy.into();

        let inner = self.inner.clone();

        future_into_py(py, async move {
            let polled_messages = inner
                .poll_messages(
                    &stream,
                    &topic,
                    partition_id,
                    &consumer,
                    &strategy,
                    count,
                    auto_commit,
                )
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            let partition_id = polled_messages.partition_id;
            let messages = polled_messages
                .messages
                .into_iter()
                .map(|m| ReceiveMessage {
                    inner: m,
                    partition_id,
                })
                .collect::<Vec<_>>();
            Ok(messages)
        })
    }

    /// Creates a new consumer group consumer.
    /// `partition_id` is ignored for a consumer group: the member reads the partitions
    /// the server assigns to it.
    /// Returns the consumer or a RuntimeError on failure. Raises `ValueError` if
    /// `poll_interval`, `polling_retry_interval`, `init_retry_interval` or an
    /// `AutoCommit` interval is negative, or if any of those except `poll_interval`
    /// is zero.
    #[allow(clippy::too_many_arguments)]
    #[pyo3(signature = (
        name,
        stream,
        topic,
        partition_id=None,
        polling_strategy=None,
        batch_length=None,
        auto_commit=None,
        create_consumer_group_if_not_exists=true,
        auto_join_consumer_group=true,
        poll_interval=None,
        polling_retry_interval=None,
        init_retries=None,
        init_retry_interval=None,
        allow_replay=false,
    ))]
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[IggyConsumer]", imports=("collections.abc")))]
    fn consumer_group<'a>(
        &self,
        py: Python<'a>,
        name: &str,
        stream: &str,
        topic: &str,
        #[gen_stub(override_type(type_repr = "builtins.int | None"))] partition_id: Option<u32>,
        #[gen_stub(override_type(type_repr = "PollingStrategy | None"))] polling_strategy: Option<
            &PollingStrategy,
        >,
        #[gen_stub(override_type(type_repr = "builtins.int | None"))] batch_length: Option<u32>,
        #[gen_stub(override_type(type_repr = "AutoCommit | None"))] auto_commit: Option<
            &AutoCommit,
        >,
        create_consumer_group_if_not_exists: bool,
        auto_join_consumer_group: bool,
        #[gen_stub(override_type(type_repr = "datetime.timedelta | None", imports=("datetime")))]
        poll_interval: Option<Py<PyDelta>>,
        #[gen_stub(override_type(type_repr = "datetime.timedelta | None", imports=("datetime")))]
        polling_retry_interval: Option<Py<PyDelta>>,
        #[gen_stub(override_type(type_repr = "builtins.int | None"))] init_retries: Option<u32>,
        #[gen_stub(override_type(type_repr = "datetime.timedelta | None", imports=("datetime")))]
        init_retry_interval: Option<Py<PyDelta>>,
        allow_replay: bool,
    ) -> PyResult<Bound<'a, PyAny>> {
        let mut builder = self
            .inner
            .consumer_group(name, stream, topic)
            .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?
            .without_encryptor()
            .partition(partition_id);

        if create_consumer_group_if_not_exists {
            builder = builder.create_consumer_group_if_not_exists()
        } else {
            builder = builder.do_not_create_consumer_group_if_not_exists()
        };
        if auto_join_consumer_group {
            builder = builder.auto_join_consumer_group()
        } else {
            builder = builder.do_not_auto_join_consumer_group()
        };
        if let Some(polling_strategy) = polling_strategy {
            builder = builder.polling_strategy(polling_strategy.into())
        };
        if let Some(batch_length) = batch_length {
            builder = builder.batch_length(batch_length)
        };
        if let Some(auto_commit) = auto_commit {
            builder = builder.auto_commit(RustAutoCommit::try_from(auto_commit)?)
        };
        if let Some(poll_interval) = poll_interval {
            builder = builder.poll_interval(py_delta_to_iggy_duration(&poll_interval)?)
        } else {
            builder = builder.without_poll_interval()
        };
        if let Some(polling_retry_interval) = polling_retry_interval {
            builder = builder.polling_retry_interval(reject_zero(
                py_delta_to_iggy_duration(&polling_retry_interval)?,
                "polling_retry_interval",
            )?)
        }
        if init_retries.is_some() && init_retry_interval.is_none() {
            return Err(PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(
                "'init_retry_interval' is required if 'init_retries' is set",
            ));
        }
        if init_retries.is_none() && init_retry_interval.is_some() {
            return Err(PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(
                "'init_retries' is required if 'init_retry_interval' is set",
            ));
        }
        if let (Some(init_retries), Some(init_retry_interval)) = (init_retries, init_retry_interval)
        {
            builder = builder.init_retries(
                init_retries,
                reject_zero(
                    py_delta_to_iggy_duration(&init_retry_interval)?,
                    "init_retry_interval",
                )?,
            );
        }
        if allow_replay {
            builder = builder.allow_replay()
        }
        let mut consumer = builder.build();

        future_into_py(py, async move {
            consumer
                .init()
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            let state = consumer.state();
            let name = consumer.name().to_string();
            let stream = PyIdentifier::try_from(consumer.stream())?;
            let topic = PyIdentifier::try_from(consumer.topic())?;
            Ok(IggyConsumer {
                inner: Arc::new(Mutex::new(consumer)),
                state,
                name,
                stream,
                topic,
            })
        })
    }

    /// Send a command code with a payload and return the raw response bytes.
    ///
    /// Session-control codes are rejected client-side. HTTP transport does not
    /// support raw binary commands.
    ///
    /// Args:
    ///     code: Command code as `int`.
    ///     payload: Request payload as `bytes`.
    ///
    /// Returns:
    ///     An awaitable that resolves to the raw response `bytes`.
    ///
    /// Raises:
    ///     RuntimeError: If the command cannot be sent or the server returns an error.
    #[gen_stub(override_return_type(type_repr="collections.abc.Awaitable[bytes]", imports=("collections.abc")))]
    fn send_binary_request<'a>(
        &self,
        py: Python<'a>,
        code: u32,
        #[gen_stub(override_type(type_repr = "builtins.bytes"))] payload: Vec<u8>,
    ) -> PyResult<Bound<'a, PyAny>> {
        let inner = self.inner.clone();
        future_into_py(py, async move {
            let response = inner
                .send_binary_request(code, Bytes::from(payload))
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
            Ok(Python::attach(|py| PyBytes::new(py, &response).unbind()))
        })
    }
}

define_stub_info_gatherer!(stub_info);
