// file: kb_lib/src/db/sqlite.rs

//! SQLite backend helpers.

/// Returns a displayable SQLite database URL-like string.
pub(crate) fn sqlite_database_url_from_config(
    config: &crate::DatabaseConfig,
) -> Result<std::string::String, crate::Error> {
    let path = config.sqlite.path.trim();
    if path.is_empty() {
        return Err(crate::Error::Config("database.sqlite.path must not be empty".to_string()));
    }
    let database_path = config.sqlite.path_buf();
    return Ok(format!("sqlite://{}", database_path.display()));
}

/// Opens a SQLite pool according to configuration.
pub(crate) async fn connect_sqlite(
    config: &crate::DatabaseConfig,
) -> Result<sqlx::SqlitePool, crate::Error> {
    let path = config.sqlite.path.trim();
    if path.is_empty() {
        return Err(crate::Error::Config("database.sqlite.path must not be empty".to_string()));
    }
    if config.sqlite.max_connections == 0 {
        return Err(crate::Error::Config(
            "database.sqlite.max_connections must be > 0".to_string(),
        ));
    }
    let database_path = config.sqlite.path_buf();
    let parent_option = database_path.parent();
    if let Some(parent) = parent_option {
        if !parent.as_os_str().is_empty() {
            let create_result = std::fs::create_dir_all(parent);
            if let Err(error) = create_result {
                return Err(crate::Error::Db(format!(
                    "cannot create sqlite parent directory '{}': {}",
                    parent.display(),
                    error
                )));
            }
        }
    }
    let mut connect_options = sqlx::sqlite::SqliteConnectOptions::new()
        .filename(&database_path)
        .create_if_missing(config.sqlite.create_if_missing)
        .foreign_keys(true)
        .busy_timeout(std::time::Duration::from_millis(config.sqlite.busy_timeout_ms));
    if config.sqlite.use_wal {
        connect_options = connect_options.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal);
    }
    let pool_options =
        sqlx::sqlite::SqlitePoolOptions::new().max_connections(config.sqlite.max_connections);
    let connect_result = pool_options.connect_with(connect_options).await;
    match connect_result {
        Ok(pool) => return Ok(pool),
        Err(error) => {
            return Err(crate::Error::Db(format!(
                "cannot open sqlite database '{}': {}",
                database_path.display(),
                error
            )));
        },
    }
}
