package middleware_test

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

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

	"veza-backend-api/internal/middleware"
)

func TestRecovery_Production_NoStackTrace(t *testing.T) {
	gin.SetMode(gin.TestMode)

	// Create an observer to capture logs
	core, logged := observer.New(zapcore.InfoLevel)
	logger := zap.New(core)

	router := gin.New()
	// Initialize Recovery middleware without stack traces (production mode)
	router.Use(middleware.Recovery(logger, false))

	router.GET("/panic", func(c *gin.Context) {
		panic("production panic")
	})

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

	// Assertions
	assert.Equal(t, http.StatusInternalServerError, w.Code)

	// Check logs
	entries := logged.All()
	assert.NotEmpty(t, entries, "Should log the panic")

	lastEntry := entries[len(entries)-1]

	// Verify "stack" field is missing in production logs
	fields := lastEntry.ContextMap()
	assert.NotContains(t, fields, "stack", "Stack trace should NOT be present in production logs")

	// Verify error message is present
	assert.Contains(t, fields, "error", "Error should be present in logs")
}

func TestRecovery_Development_HasStackTrace(t *testing.T) {
	gin.SetMode(gin.TestMode)

	// Create an observer to capture logs
	core, logged := observer.New(zapcore.InfoLevel)
	logger := zap.New(core)

	router := gin.New()
	// Initialize Recovery middleware with stack traces (development mode)
	router.Use(middleware.Recovery(logger, true))

	router.GET("/panic", func(c *gin.Context) {
		panic("development panic")
	})

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

	// Assertions
	assert.Equal(t, http.StatusInternalServerError, w.Code)

	// Check logs
	entries := logged.All()
	assert.NotEmpty(t, entries, "Should log the panic")

	lastEntry := entries[len(entries)-1]

	// Verify "stack" field IS present in development logs
	fields := lastEntry.ContextMap()
	assert.Contains(t, fields, "stack", "Stack trace SHOULD be present in development logs")
}
