package middleware

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

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// Recovery 捕获 panic 并返回 500（ActionState 信封，W1/W2 裁决）。
//
// 响应体：{"success":false,"error":{"code":"GW_INTERNAL_ERROR","message":"..."},"request_id":"<uuid>"}。
// request_id 从 context 取（RequestID 中间件注入），若 Recovery 在 RequestID 之前触发
// 导致 context 无 request_id，则独立生成 uuid 保证可追溯。
func Recovery() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if r := recover(); r != nil {
				stack := debug.Stack()
				// 优先从 context 取 request_id（RequestID 中间件已注入）
				requestID, exists := c.Get(requestIDContextKey)
				if !exists {
					requestID = uuid.New().String()
				}
				slog.Error("panic recovered",
					"request_id", requestID,
					"error", r,
					"stack", string(stack),
				)
				c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
					"success": false,
					"error": gin.H{
						"code":    "GW_INTERNAL_ERROR",
						"message": "internal server error",
					},
					"request_id": requestID,
				})
			}
		}()
		c.Next()
	}
}
