//! Middleware pour extraire et propager le request_id
//! FIX #23: Corrélation avec le backend Go

use axum::{
    extract::Request,
    http::{HeaderMap, HeaderName, StatusCode},
    middleware::Next,
    response::Response,
};
use tracing::{info_span, Instrument};
use uuid::Uuid;

/// Middleware pour extraire le request_id depuis les headers et l'utiliser dans les spans
pub async fn request_id_middleware(
    mut request: Request,
    next: Next,
) -> Response {
    let headers = request.headers().clone();
    
    // FIX #23: Extraire le request_id depuis les headers (propagé depuis le backend Go)
    // Si X-Request-ID est présent, l'utiliser, sinon générer un nouveau UUID
    let request_id = extract_request_id_from_headers(&headers);
    
    // Extraire aussi le trace_id si présent
    let trace_id = extract_trace_id_from_headers(&headers);
    
    // FIX #13: Ajouter le request_id aux extensions pour utilisation dans les handlers (y compris WebSocket)
    request.extensions_mut().insert(request_id.clone());
    if let Some(ref tid) = trace_id {
        request.extensions_mut().insert(tid.clone());
    }
    
    // Ajouter le request_id aux headers de réponse
    request.headers_mut().insert(
        HeaderName::from_static("x-request-id"),
        request_id.to_string().parse().unwrap(),
    );
    
    // Créer un span avec le request_id pour la corrélation
    let span = info_span!(
        "request",
        request_id = %request_id,
        trace_id = ?trace_id,
    );
    
    // Exécuter la requête dans le span
    next.run(request).instrument(span).await
}

/// Extraire le request_id depuis les headers HTTP
fn extract_request_id_from_headers(headers: &HeaderMap) -> Uuid {
    // Chercher X-Request-ID dans les headers
    if let Some(request_id_header) = headers.get("x-request-id") {
        if let Ok(request_id_str) = request_id_header.to_str() {
            if let Ok(uuid) = Uuid::parse_str(request_id_str) {
                return uuid;
            }
        }
    }
    
    // Si aucun request_id valide n'est trouvé, générer un nouveau UUID
    Uuid::new_v4()
}

/// Extraire le trace_id depuis les headers HTTP
fn extract_trace_id_from_headers(headers: &HeaderMap) -> Option<String> {
    // Chercher X-Trace-ID dans les headers
    if let Some(trace_id_header) = headers.get("x-trace-id") {
        if let Ok(trace_id_str) = trace_id_header.to_str() {
            return Some(trace_id_str.to_string());
        }
    }
    
    None
}

