use crate::{DATABASE_URL, RingspaceError};
use std::env;
#[macro_use]
pub mod migrations;
use sqlx::{Connection, Row, SqliteConnection, query};

///
/// Returns a database connection. If the environment variable
/// `RINGSPACE_DATABASE_URL` is set, it honors that value. Otherwise, it falls back
/// to the built-in default [DATABASE_URL].
///
pub async fn get_db_connection() -> Result<SqliteConnection, RingspaceError> {
    let database_url = env::var("RINGSPACE_DATABASE_URL").unwrap_or(DATABASE_URL.to_string());
    let conn = SqliteConnection::connect(&database_url).await?;
    Ok(conn)
}

///
/// Performs migration connections
///
pub async fn migrate() -> Result<(), RingspaceError> {
    let mut conn = get_db_connection().await?;
    match sqlx::migrate!("db/migrations").run(&mut conn).await {
        Ok(_) => {
            println!("Database migrated successfully!");
            post_migration(&mut conn).await?
        }
        Err(e) => {
            return Err(RingspaceError::from(e));
        }
    };
    Ok(())
}

/// Perform all registered post-migration operations for the given latest migration
/// Each migration is a separate function in [migrations].
pub async fn post_migration(conn: &mut SqliteConnection) -> Result<(), RingspaceError> {
    println!("Running post-migration actions");

    let last_migration = query("SELECT * FROM _sqlx_migrations ORDER BY version DESC LIMIT 1")
        .fetch_one(&mut *conn)
        .await?;

    let last_migration_id: i64 = last_migration.get("version");

    match last_migration_id {
        2 => migrations::post_migration_002(&mut *conn).await,
        _ => {
            println!("No post-migration operations required");
            Ok(())
        }
    }
}
