use tokio_postgres::{Client, NoTls};

const PERSON_SCHEMA_NAME: &str = "public";

use crate::config::GeneralServiceConfig;

pub type DbResult<T> = Result<T, Box<dyn std::error::Error>>;

pub async fn connect_db(config: &GeneralServiceConfig) -> DbResult<Client> {
    let mut pg_config = tokio_postgres::Config::new();
    pg_config.host(&config.postgres_host);
    pg_config.dbname(&config.pg_database);
    pg_config.user(&config.postgres_user);

    let (client, connection) = pg_config.connect(NoTls).await?;
    tokio::spawn(async move {
        if let Err(err) = connection.await {
            eprintln!("postgres connection error: {err}");
        }
    });

    Ok(client)
}

pub async fn init_database(config: &GeneralServiceConfig) -> DbResult<()> {
    let client = connect_db(config).await?;

    let create_sql = format!(
        "CREATE TABLE IF NOT EXISTS \"{}\".person (\
            id SERIAL PRIMARY KEY,\
            name TEXT NOT NULL,\
            passcode TEXT NOT NULL\
        )",
        PERSON_SCHEMA_NAME
    );
    client.execute(create_sql.as_str(), &[]).await?;
    Ok(())
}
