package middleware

import (
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

const (
	// TraceIDHeader est le nom du header HTTP pour propager le trace ID
	TraceIDHeader = "X-Trace-ID"
	// TraceIDKey est la clé utilisée pour stocker le trace ID dans le contexte Gin
	TraceIDKey = "trace_id"
	// SpanIDHeader est le nom du header HTTP pour propager le span ID (optionnel)
	SpanIDHeader = "X-Span-ID"
	// SpanIDKey est la clé utilisée pour stocker le span ID dans le contexte Gin
	SpanIDKey = "span_id"
)

// Tracing middleware pour générer et propager trace ID (W3C Trace Context compatible)
// Le trace ID permet de tracer une requête à travers plusieurs services
// Si un trace ID est déjà présent dans le header, il est réutilisé (propagation)
// Sinon, un nouveau trace ID UUID v4 est généré
func Tracing() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Récupérer ou générer le trace ID
		traceID := c.GetHeader(TraceIDHeader)
		if traceID == "" {
			// Générer un nouveau trace ID UUID v4 (compatible W3C Trace Context)
			traceID = uuid.New().String()
		}

		// Récupérer ou générer le span ID (optionnel, pour corrélation fine)
		spanID := c.GetHeader(SpanIDHeader)
		if spanID == "" {
			// Générer un nouveau span ID UUID v4
			spanID = uuid.New().String()
		}

		// Stocker dans le contexte Gin pour utilisation dans les handlers et logs
		c.Set(TraceIDKey, traceID)
		c.Set(SpanIDKey, spanID)

		// Propager via les headers de réponse (pour que les clients puissent le réutiliser)
		c.Header(TraceIDHeader, traceID)
		c.Header(SpanIDHeader, spanID)

		c.Next()
	}
}

// GetTraceID retourne le trace ID du contexte, ou une chaîne vide si non défini
func GetTraceID(c *gin.Context) string {
	if traceID, exists := c.Get(TraceIDKey); exists {
		if id, ok := traceID.(string); ok {
			return id
		}
	}
	return ""
}

// GetSpanID retourne le span ID du contexte, ou une chaîne vide si non défini
func GetSpanID(c *gin.Context) string {
	if spanID, exists := c.Get(SpanIDKey); exists {
		if id, ok := spanID.(string); ok {
			return id
		}
	}
	return ""
}
