// src/db.rs

use sqlx::postgres::PgPoolOptions;
pub use sqlx::postgres::PgPool;
use std::time::Duration;
use tracing::info;

#[derive(Debug)]
pub struct DatabaseConfig {
    pub username: String,
    pub password: String,
    pub host: String,
    pub port: u16,
    pub database_name: String,
    pub max_connections: u32,
}

impl DatabaseConfig {
    pub fn from_env() -> Self {
        Self {
            username: std::env::var("RUST_DB_USER").expect("RUST_DB_USER must be set"),
            password: std::env::var("RUST_DB_PASSWORD").expect("RUST_DB_PASSWORD must be set"),
            host: std::env::var("RUST_DB_HOST").expect("RUST_DB_HOST must be set"),
            port: std::env::var("RUST_DB_PORT")
                .expect("RUST_DB_PORT must be set")
                .parse()
                .expect("RUST_DB_PORT must be a valid port number"),
            database_name: std::env::var("RUST_DB_NAME").expect("RUST_DB_NAME must be set"),
            max_connections: 5,
        }
    }

    pub fn connection_string(&self) -> String {
        format!(
            "postgres://{}:{}@{}:{}/{}",
            self.username, self.password, self.host, self.port, self.database_name
        )
    }
}

pub async fn create_pool(config: &DatabaseConfig) -> Result<PgPool, sqlx::Error> {
    let conn_str = config.connection_string();
    info!("Connecting to database: {}", conn_str);
    PgPoolOptions::new()
        .max_connections(config.max_connections)
        .acquire_timeout(Duration::from_secs(3))
        .connect(&conn_str)
        .await
}

pub async fn check_connection(pool: &PgPool) -> Result<(), sqlx::Error> {
    sqlx::query("SELECT 1").execute(pool).await?;
    Ok(())
}
