use crate::app_config::AppConfig;
use diesel::PgConnection;
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
use lazy_static::lazy_static;
use std::sync::Arc;

const MIGRATIONS: EmbeddedMigrations = embed_migrations!();

pub type DBConn = Arc<Pool<ConnectionManager<PgConnection>>>;

fn get_db_connection_pool() -> anyhow::Result<DBConn> {
    log::info!("Connect to PostgresSQL database...");
    let url = AppConfig::get().db_connection_chain();
    let manager = ConnectionManager::<PgConnection>::new(url);
    // Refer to the `r2d2` documentation for more methods to use
    // when building a connection pool
    Ok(Arc::new(
        Pool::builder().test_on_check_out(true).build(manager)?,
    ))
}

lazy_static! {
    static ref DB_POOL: DBConn = get_db_connection_pool().expect("Failed to connect to database");
}

pub fn db() -> anyhow::Result<PooledConnection<ConnectionManager<PgConnection>>> {
    Ok(DB_POOL.clone().get()?)
}

pub fn initialize_conn() -> anyhow::Result<()> {
    // Run pending diesel migrations
    let mut db = db()?;
    db.run_pending_migrations(MIGRATIONS)
        .expect("Failed to run DB migrations");

    Ok(())
}
