//! Channel factory abstraction for durable AMQP channel management.
//!
//! Provides the [`ChannelFactory`] trait, which allows metrics collectors and
//! command executors to obtain fresh AMQP channels on demand — enabling
//! automatic recovery after connection drops.

use async_trait::async_trait;

/// Provides AMQP channels on demand, supporting reconnection.
///
/// Implement this trait to give the metrics collector and command executor
/// the ability to recover from channel/connection failures. When a channel
/// becomes stale (e.g. after a RabbitMQ restart), the collector will call
/// `create_channel()` again to obtain a fresh one.
///
/// # Example
///
/// ```no_run
/// use async_trait::async_trait;
/// use queuerious_lapin::ChannelFactory;
///
/// struct MyConnectionPool { /* ... */ }
///
/// #[async_trait]
/// impl ChannelFactory for MyConnectionPool {
///     async fn create_channel(&self) -> Result<lapin::Channel, lapin::Error> {
///         // Return a channel from your managed connection
///         todo!()
///     }
/// }
/// ```
#[async_trait]
pub trait ChannelFactory: Send + Sync + 'static {
    /// Create a new AMQP channel.
    ///
    /// Implementations should handle reconnection internally if the
    /// underlying connection has dropped.
    async fn create_channel(&self) -> Result<lapin::Channel, lapin::Error>;
}

/// A simple factory that creates channels from a static [`lapin::Connection`].
///
/// Does **not** handle reconnection — if the connection drops, channel
/// creation will fail until the connection is re-established externally.
///
/// For applications with their own connection management (e.g. connection pools
/// or reconnect loops), implement [`ChannelFactory`] directly to integrate
/// with your reconnection logic.
pub struct StaticConnectionFactory {
    connection: lapin::Connection,
}

impl StaticConnectionFactory {
    /// Create a factory backed by the given connection.
    pub fn new(connection: lapin::Connection) -> Self {
        Self { connection }
    }
}

#[async_trait]
impl ChannelFactory for StaticConnectionFactory {
    async fn create_channel(&self) -> Result<lapin::Channel, lapin::Error> {
        self.connection.create_channel().await
    }
}
