package middleware

import (
	"net/http"
	"runtime/debug"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// Recovery middleware personnalisé avec logging structuré
// Capture les panics et les log avec stack trace et contexte
// MOD-P1-005: Stack traces seulement si includeStackTrace=true (dev/DEBUG mode)
func Recovery(logger *zap.Logger, includeStackTrace bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				requestID, _ := c.Get("request_id")

				// MOD-P1-005: Stack traces seulement en development/debug, pas en prod
				var stack []byte
				if includeStackTrace {
					stack = debug.Stack()
				}

				// Construire les champs de log
				logFields := []zap.Field{
					zap.Any("error", err),
					zap.String("path", c.Request.URL.Path),
					zap.String("method", c.Request.Method),
				}

				if len(stack) > 0 {
					logFields = append(logFields, zap.ByteString("stack", stack))
				}

				// Ajouter request_id si disponible
				if requestID != nil {
					if requestIDStr, ok := requestID.(string); ok {
						logFields = append(logFields, zap.String("request_id", requestIDStr))
					}
				}

				// Ajouter user_id si disponible
				if userID, exists := c.Get("user_id"); exists {
					logFields = append(logFields, zap.Any("user_id", userID))
				}

				logger.Error("Panic recovered", logFields...)

				// Retourner une erreur 500 standardisée
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": gin.H{
						"code":    9000,
						"message": "Internal server error",
					},
				})
				c.Abort()
			}
		}()

		c.Next()
	}
}
