package middleware

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

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/zap/zaptest"
)

func TestRequestLogger(t *testing.T) {
	// Créer un logger de test
	logger := zaptest.NewLogger(t)

	// Créer un router Gin
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.Use(RequestLogger(logger))
	router.GET("/test", func(c *gin.Context) {
		c.JSON(200, gin.H{"status": "ok"})
	})

	// Faire une requête
	req := httptest.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	// Vérifier que la requête a réussi
	assert.Equal(t, http.StatusOK, w.Code)
}

func TestRequestLogger_WithRequestID(t *testing.T) {
	logger := zaptest.NewLogger(t)

	router := gin.New()
	router.Use(RequestLogger(logger))
	router.GET("/test", func(c *gin.Context) {
		c.Set("request_id", "req-123")
		c.JSON(200, gin.H{"status": "ok"})
	})

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

	assert.Equal(t, http.StatusOK, w.Code)
}

func TestRequestLogger_WithUserID(t *testing.T) {
	logger := zaptest.NewLogger(t)

	router := gin.New()
	router.Use(RequestLogger(logger))
	router.GET("/test", func(c *gin.Context) {
		c.Set("user_id", int64(42))
		c.JSON(200, gin.H{"status": "ok"})
	})

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

	assert.Equal(t, http.StatusOK, w.Code)
}

func TestRequestLogger_WithErrors(t *testing.T) {
	logger := zaptest.NewLogger(t)

	router := gin.New()
	router.Use(RequestLogger(logger))
	router.GET("/test", func(c *gin.Context) {
		c.Error(gin.Error{Type: gin.ErrorTypePublic, Err: assert.AnError, Meta: "test error"})
		c.JSON(400, gin.H{"error": "bad request"})
	})

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

	assert.Equal(t, http.StatusBadRequest, w.Code)
}

func TestRequestLogger_ErrorStatus(t *testing.T) {
	logger := zaptest.NewLogger(t)

	router := gin.New()
	router.Use(RequestLogger(logger))
	router.GET("/test", func(c *gin.Context) {
		c.JSON(500, gin.H{"error": "internal server error"})
	})

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

	assert.Equal(t, http.StatusInternalServerError, w.Code)
}

func TestRequestLogger_AllFields(t *testing.T) {
	logger := zaptest.NewLogger(t)

	router := gin.New()
	router.Use(RequestLogger(logger))
	// La route ne doit pas inclure le query string - Gin le gère automatiquement
	router.GET("/test", func(c *gin.Context) {
		c.Set("request_id", "req-123")
		c.Set("user_id", int64(42))
		c.JSON(200, gin.H{"status": "ok"})
	})

	req := httptest.NewRequest("GET", "/test?foo=bar", nil)
	req.Header.Set("User-Agent", "test-agent")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	require.Equal(t, http.StatusOK, w.Code)
}
