package middleware

import (
	"context"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/nexuscrm/shared/pkg/constants"
)

const (
	HeaderXRequestID       = "X-Request-ID"
	HeaderXReplayRequestID = "X-Replay-RequestId"
	ContextKeyRequestID    = "request_id"
)

// RequestID adds a unique ID to every request. Accepts either the standard
// `X-Request-ID` header or the replay-specific `X-Replay-RequestId` header
// (emitted by `cmd/replay` when reissuing captured traffic against a target
// backend — §14.5 audit-trail equivalence requires the target's AuditLog.
// RequestId to equal the source capture's RequestId for correlation).
// Falls back to a fresh UUID when neither header is supplied.
func RequestID() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Prefer the replay header (it's the more specific intent); fall
		// back to X-Request-ID for generic external callers.
		requestID := c.GetHeader(HeaderXReplayRequestID)
		if requestID == "" {
			requestID = c.GetHeader(HeaderXRequestID)
		}

		// If neither header supplied, generate a new UUID.
		if requestID == "" {
			requestID = uuid.New().String()
		}

		// Set it in the Gin context (for middleware/handler access)
		c.Set(ContextKeyRequestID, requestID)

		// Set it in the response header
		c.Writer.Header().Set(HeaderXRequestID, requestID)

		// Store in standard context.Context (for service/repository layer access)
		ctx := c.Request.Context()
		ctx = context.WithValue(ctx, constants.ContextKeyRequestID, requestID)
		c.Request = c.Request.WithContext(ctx)

		c.Next()
	}
}

// GetRequestID returns the request ID from the Gin context
func GetRequestID(c *gin.Context) string {
	if id, exists := c.Get(ContextKeyRequestID); exists {
		if s, ok := id.(string); ok {
			return s
		}
	}
	return ""
}
