package middleware

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/stretchr/testify/assert"
)

func TestTracing(t *testing.T) {
	gin.SetMode(gin.TestMode)
	r := gin.New()
	r.Use(Tracing())
	r.GET("/test", func(c *gin.Context) {
		traceparent := c.GetString(string(constants.ContextKeyTraceparent))
		if traceparent == "" {
			t.Error("Traceparent missing from context")
		}
		c.Status(http.StatusOK)
	})

	// Test case 1: No existing traceparent - should generate one
	req := httptest.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	assert.NotEmpty(t, w.Header().Get("traceparent"))

	// Verify W3C format: 00-<32 hex>-<16 hex>-01
	tp := w.Header().Get("traceparent")
	parts := strings.Split(tp, "-")
	assert.Len(t, parts, 4)
	assert.Equal(t, "00", parts[0]) // Version
	assert.Len(t, parts[1], 32)     // Trace ID
	assert.Len(t, parts[2], 16)     // Span ID
	assert.Equal(t, "01", parts[3]) // Flags

	// Test case 2: Existing W3C Traceparent - should preserve
	w3cTraceID := "4bf92f3577b34da6a3ce929d0e0e4736"
	w3cSpanID := "00f067aa0ba902b7"
	existingTraceparent := "00-" + w3cTraceID + "-" + w3cSpanID + "-01"

	req2 := httptest.NewRequest("GET", "/test", nil)
	req2.Header.Set("traceparent", existingTraceparent)
	w2 := httptest.NewRecorder()
	r.ServeHTTP(w2, req2)

	assert.Equal(t, http.StatusOK, w2.Code)
	assert.Equal(t, existingTraceparent, w2.Header().Get("traceparent"))
}

func TestTracing_StoresInStandardContext(t *testing.T) {
	gin.SetMode(gin.TestMode)
	r := gin.New()
	r.Use(Tracing())

	var fromCtx string
	r.GET("/test", func(c *gin.Context) {
		val := c.Request.Context().Value(constants.ContextKeyTraceparent)
		if s, ok := val.(string); ok {
			fromCtx = s
		}
		c.Status(http.StatusOK)
	})

	req := httptest.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)

	assert.NotEmpty(t, fromCtx)
	assert.True(t, strings.HasPrefix(fromCtx, "00-"), "traceparent should start with version 00")
}

func TestTracing_PartialTraceparentGeneratesNewSpan(t *testing.T) {
	gin.SetMode(gin.TestMode)
	r := gin.New()
	r.Use(Tracing())

	r.GET("/test", func(c *gin.Context) {
		c.Status(http.StatusOK)
	})

	req := httptest.NewRequest("GET", "/test", nil)
	req.Header.Set("traceparent", "00-abc123")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	tp := w.Header().Get("traceparent")
	assert.NotEmpty(t, tp)
	parts := strings.Split(tp, "-")
	assert.Len(t, parts, 4)
}

