//! Configuration models shared across AthenaClient pipelines.
use crate::client::backend::BackendType;
use std::time::Duration;

/// ## `ClientConfig`
/// High level configuration for Athena clients.
///
/// # Arguments
///
/// * `backend_type` - The backend type.
/// * `client_name` - The client name.
/// * `connection` - The connection configuration.
/// * `pool` - The pool configuration.
/// * `health` - The health configuration.
///
/// # Returns
///
/// A `ClientConfig` containing the client configuration.
///
#[derive(Clone, Debug)]
pub struct ClientConfig {
    pub backend_type: BackendType,
    pub client_name: Option<String>,
    pub connection: ConnectionConfig,
    pub pool: PoolConfig,
    pub health: HealthConfig,
}

impl ClientConfig {
    /// ## `new`
    /// Create a new client configuration.
    ///
    /// # Arguments
    ///
    /// * `backend_type` - The backend type.
    /// * `client_name` - The client name.
    /// * `connection` - The connection configuration.
    /// * `pool` - The pool configuration.
    /// * `health` - The health configuration.
    ///
    /// # Returns
    ///
    /// A `ClientConfig` containing the client configuration.
    ///
    pub fn new(
        backend_type: BackendType,
        client_name: Option<String>,
        connection: ConnectionConfig,
        pool: PoolConfig,
        health: HealthConfig,
    ) -> Self {
        Self {
            backend_type,
            client_name,
            connection,
            pool,
            health,
        }
    }
}

/// ## `ConnectionConfig`
/// Connection-specific options.
///
/// # Arguments
///
/// * `url` - The connection URL.
/// * `key` - The connection key.
/// * `ssl` - Whether to use SSL.
/// * `port` - The port.
/// * `database` - The database.
///
/// # Returns
///
/// A `ConnectionConfig` containing the connection configuration.
///
#[derive(Clone, Debug)]
pub struct ConnectionConfig {
    pub url: String,
    pub key: Option<String>,
    pub ssl: bool,
    pub port: Option<u16>,
    pub database: Option<String>,
}

impl ConnectionConfig {
    /// ## `new`
    /// Create a new connection configuration.
    ///
    /// # Arguments
    ///
    /// * `url` - The connection URL.
    ///
    /// # Returns
    ///
    /// A `ConnectionConfig` containing the connection configuration.
    ///
    pub fn new(url: impl Into<String>) -> Self {
        Self {
            url: url.into(),
            key: None,
            ssl: true,
            port: None,
            database: None,
        }
    }

    /// ## `with_key`
    /// Set the connection key.
    ///
    /// # Arguments
    ///
    /// * `key` - The connection key.
    ///
    /// # Returns
    ///
    /// A `ConnectionConfig` containing the connection configuration.
    ///
    pub fn with_key(mut self, key: impl Into<String>) -> Self {
        self.key = Some(key.into());
        self
    }
}

/// ## `PoolConfig`
/// Pool configuration shared by JDBC/Postgres backends.
///
/// # Arguments
///
/// * `max_connections` - The maximum number of connections.
/// * `min_connections` - The minimum number of connections.
/// * `connection_timeout` - The connection timeout.
/// * `idle_timeout` - The idle timeout.
///
/// # Returns
///
/// A `PoolConfig` containing the pool configuration.
///
#[derive(Clone, Debug)]
pub struct PoolConfig {
    pub max_connections: u32,
    pub min_connections: u32,
    pub connection_timeout: Duration,
    pub idle_timeout: Duration,
}

impl Default for PoolConfig {
    /// ## `default`
    /// Create a new pool configuration.
    ///
    /// # Arguments
    ///
    /// # Returns
    ///
    /// A `PoolConfig` containing the pool configuration.
    ///
    fn default() -> Self {
        Self {
            max_connections: 50,
            min_connections: 0,
            connection_timeout: Duration::from_secs(5),
            idle_timeout: Duration::from_secs(300),
        }
    }
}

/// ## `HealthConfig`
/// Health tracking configuration (circuit breaker, probes).
///
/// # Arguments
///
/// * `enabled` - Whether to enable health tracking.
/// * `check_interval` - The health check interval.
/// * `circuit_breaker_threshold` - The circuit breaker threshold.
/// * `circuit_breaker_timeout` - The circuit breaker timeout.
///
/// # Returns
///
/// A `HealthConfig` containing the health configuration.
///
#[derive(Clone, Debug)]
pub struct HealthConfig {
    pub enabled: bool,
    pub check_interval: Duration,
    pub circuit_breaker_threshold: u32,
    pub circuit_breaker_timeout: Duration,
}

impl Default for HealthConfig {
    /// ## `default`
    /// Create a new health configuration.
    ///
    /// # Arguments
    ///
    /// # Returns
    ///
    /// A `HealthConfig` containing the health configuration.
    ///
    fn default() -> Self {
        Self {
            enabled: true,
            check_interval: Duration::from_secs(30),
            circuit_breaker_threshold: 5,
            circuit_breaker_timeout: Duration::from_secs(60),
        }
    }
}
