package middleware

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

const (
	// RequestIDHeader is the primary header for request IDs
	RequestIDHeader = "X-Request-ID"
	// CorrelationIDHeader is an alternative header for distributed tracing
	CorrelationIDHeader = "X-Correlation-ID"
	// RequestIDKey is the context key for storing the request ID
	RequestIDKey = "request_id"
)

// RequestID returns a middleware that generates and propagates request IDs.
//
// For each incoming request:
// 1. Check for existing X-Request-ID or X-Correlation-ID header
// 2. If not present, generate a new UUID
// 3. Store in Gin context for use by handlers and logging
// 4. Add to response headers
//
// Usage:
//
//	r.Use(middleware.RequestID())
//
//	func handler(c *gin.Context) {
//	    requestID := middleware.GetRequestID(c)
//	    log.Printf("[%s] Processing request", requestID)
//	}
func RequestID() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Try to get existing request ID from headers
		requestID := c.GetHeader(RequestIDHeader)
		if requestID == "" {
			requestID = c.GetHeader(CorrelationIDHeader)
		}

		// Generate new ID if not provided
		if requestID == "" {
			requestID = uuid.New().String()
		}

		// Store in context for handlers and logging
		c.Set(RequestIDKey, requestID)

		// Add to response headers
		c.Header(RequestIDHeader, requestID)
		c.Header(CorrelationIDHeader, requestID)

		c.Next()
	}
}

// GetRequestID retrieves the request ID from the Gin context.
// Returns empty string if no request ID is set.
//
// Usage:
//
//	requestID := middleware.GetRequestID(c)
func GetRequestID(c *gin.Context) string {
	if id, exists := c.Get(RequestIDKey); exists {
		if idStr, ok := id.(string); ok {
			return idStr
		}
	}
	return ""
}

// RequestIDFromContext is an alias for GetRequestID for API compatibility.
func RequestIDFromContext(c *gin.Context) string {
	return GetRequestID(c)
}
