use axum::body::Body;
use axum::http::Request;
use axum::middleware::Next;
use axum::response::Response;
use erp_core::types::TenantContext;
use sea_orm::{ConnectionTrait, DatabaseBackend, Statement};

/// Tenant RLS 中间件。
///
/// 从 request extensions 中提取 `TenantContext`，在数据库连接上设置
/// `app.current_tenant_id`，使 PostgreSQL RLS 策略自动按租户过滤。
///
/// 请求处理完成后自动 RESET 设置，防止连接池复用时泄漏。
///
/// SET 失败时仅 warn 不阻断请求（RLS 是安全网，主隔离仍在应用层）。
pub async fn tenant_rls_middleware(
    db: sea_orm::DatabaseConnection,
    req: Request<Body>,
    next: Next,
) -> Response {
    let tenant_id = req
        .extensions()
        .get::<TenantContext>()
        .map(|ctx| ctx.tenant_id);

    if let Some(tid) = tenant_id {
        // SET app.current_tenant_id — RLS 策略读取此值（参数化查询防止注入）
        if let Err(e) = db
            .execute(Statement::from_sql_and_values(
                DatabaseBackend::Postgres,
                "SET app.current_tenant_id = $1",
                [tid.into()],
            ))
            .await
        {
            tracing::warn!(tenant_id = %tid, error = %e, "SET app.current_tenant_id 失败（RLS 未激活）");
        }
    }

    let response = next.run(req).await;

    // RESET — 防止连接池复用时泄漏租户上下文
    if tenant_id.is_some()
        && let Err(e) = db.execute_unprepared("RESET app.current_tenant_id").await
    {
        tracing::debug!(error = %e, "RESET app.current_tenant_id 失败（非致命）");
    }

    response
}
