//! Telemetry-layer implementation for [`ConnectionPool`].
//!
//! Snapshotting is something you *do* to a live [`ConnectionPool`]; this file
//! hosts the [`snapshot`](ConnectionPool::snapshot) method on the pool that
//! produces a read-only [`ConnectionPoolSnapshot`] of its current occupancy.
//!
//! # Contract
//!
//! - **No I/O.** Snapshotting only reads in-process counters exposed by sqlx.
//! - **No mutation.** The live pool is untouched.
//! - **No allocation beyond the returned struct.** A single heap `String` for
//!   `client_name` plus a few `u32`s.
//! - **Consistent at the sqlx boundary.** Individual fields are each atomic
//!   reads from the pool; the composite view is a best-effort "recent past".
//!   `active_connections` is derived as `pool_size - idle_connections` with
//!   `saturating_sub` to tolerate the rare case where idle advances between
//!   the two reads.
//!
//! # Intended consumers
//!
//! - `/metrics` Prometheus exporter (via
//!   [`ConnectionPoolSnapshot::write_prometheus`](crate::features::connection_pooler::prometheus))
//! - `client_connections` persistence (`insert_connection_snapshot`)
//! - Structured logging (`tracing::info!(?snapshot, …)`)

use chrono::Utc;

use crate::features::connection_pooler::{ConnectionPool, ConnectionPoolSnapshot};

impl ConnectionPool {
    /// Capture a point-in-time [`ConnectionPoolSnapshot`] of this pool's
    /// size/idle/active/max occupancy plus its `is_closed` flag, tagged with
    /// `recorded_at = Utc::now()`.
    ///
    /// Runs in microseconds and never blocks. Safe to call on every metrics
    /// scrape or daemon tick.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use athena_rs::features::connection_pooler::ConnectionPool;
    /// # fn demo(pool: &ConnectionPool) {
    /// let snap = pool.snapshot();
    /// if snap.pool_size == snap.max_connections && snap.active_connections > 0 {
    ///     tracing::warn!(?snap, "pool saturated");
    /// }
    /// # }
    /// ```
    pub fn snapshot(&self) -> ConnectionPoolSnapshot {
        let pg_pool: &sqlx::Pool<sqlx::Postgres> = self.pg_pool();
        let pool_size: u32 = pg_pool.size();
        let idle_connections: u32 = pg_pool.num_idle().try_into().unwrap_or_default();
        let max_connections: u32 = pg_pool.options().get_max_connections();
        let active_connections: u32 = pool_size.saturating_sub(idle_connections);
        let is_closed: bool = pg_pool.is_closed();

        ConnectionPoolSnapshot {
            client_name: self.client_name().to_string(),
            pool_size,
            idle_connections,
            active_connections,
            max_connections,
            is_closed,
            recorded_at: Utc::now(),
        }
    }
}
