//! Database connection pool and RLS context management.

use std::time::Duration;

use sqlx::{postgres::PgPoolOptions, PgPool};
use uuid::Uuid;

use chattyness_error::AppError;

/// Create a new database connection pool for the owner interface.
///
/// Uses the `chattyness_owner` role which has full database access.
pub async fn create_owner_pool(database_url: &str) -> Result<PgPool, AppError> {
    let pool = PgPoolOptions::new()
        .max_connections(5)
        .acquire_timeout(Duration::from_secs(5))
        .connect(database_url)
        .await?;

    Ok(pool)
}

/// Create a new database connection pool for the public app.
///
/// Uses the `chattyness_app` role which has Row-Level Security (RLS) policies.
pub async fn create_app_pool(database_url: &str) -> Result<PgPool, AppError> {
    let pool = PgPoolOptions::new()
        .max_connections(10)
        .acquire_timeout(Duration::from_secs(5))
        .connect(database_url)
        .await?;

    Ok(pool)
}

/// Set the current user context for Row-Level Security.
///
/// This should be called at the start of each request to enable RLS policies
/// that depend on the current user ID.
pub async fn set_user_context(pool: &PgPool, user_id: Option<Uuid>) -> Result<(), AppError> {
    if let Some(id) = user_id {
        sqlx::query("SELECT public.set_current_user_id($1)")
            .bind(id)
            .execute(pool)
            .await?;
    } else {
        // Clear the user context for anonymous requests
        sqlx::query("SELECT public.clear_current_user_id()")
            .execute(pool)
            .await?;
    }
    Ok(())
}

/// Clear the current user context.
///
/// Called at the end of a request to ensure the connection is clean
/// before returning to the pool.
pub async fn clear_user_context(pool: &PgPool) -> Result<(), AppError> {
    sqlx::query("SELECT public.clear_current_user_id()")
        .execute(pool)
        .await?;
    Ok(())
}

/// Set the current guest session context for Row-Level Security.
///
/// This should be called for guest users to enable RLS policies
/// that depend on the current guest session ID.
pub async fn set_guest_context(pool: &PgPool, guest_session_id: Uuid) -> Result<(), AppError> {
    sqlx::query("SELECT public.set_current_guest_session_id($1)")
        .bind(guest_session_id)
        .execute(pool)
        .await?;
    Ok(())
}

/// Clear the current guest session context.
pub async fn clear_guest_context(pool: &PgPool) -> Result<(), AppError> {
    sqlx::query("SELECT public.set_current_guest_session_id(NULL)")
        .execute(pool)
        .await?;
    Ok(())
}
