package logger

import (
	"time"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"
)

const (
	// MaxBodyLogSize 限制记录的请求/响应 body 大小为 50KB
	MaxBodyLogSize = 50 * 1024
)

// truncateBody 截断 body 到指定大小
func truncateBody(body []byte, maxSize int) string {
	if len(body) == 0 {
		return ""
	}

	if len(body) <= maxSize {
		return string(body)
	}

	// 超过限制，截断并添加提示
	return string(body[:maxSize]) + "... (truncated)"
}

// Middleware 创建 Fiber 日志中间件
// 记录所有 HTTP 请求到访问日志（包括请求和响应 body）
func Middleware() fiber.Handler {
	return func(c *fiber.Ctx) error {
		// 记录请求开始时间
		startTime := time.Now()
		c.Locals(constants.ContextKeyStartTime, startTime)

		// 获取请求 body（在 c.Next() 之前读取）
		requestBody := truncateBody(c.Body(), MaxBodyLogSize)

		// 获取 query 参数
		queryParams := string(c.Request().URI().QueryString())

		// 处理请求
		err := c.Next()

		// 计算请求持续时间
		duration := time.Since(startTime)

		// 获取请求 ID（由 requestid 中间件设置）
		requestID := ""
		if rid := c.Locals(constants.ContextKeyRequestID); rid != nil {
			requestID = rid.(string)
		}

		// 获取用户 ID（由 auth 中间件设置）
		var userID uint
		if uid := c.Locals(constants.ContextKeyUserID); uid != nil {
			if id, ok := uid.(uint); ok {
				userID = id
			}
		}

		// 获取响应 body
		responseBody := truncateBody(c.Response().Body(), MaxBodyLogSize)

		// 记录访问日志
		accessLogger := GetAccessLogger()
		accessLogger.Info("",
			zap.String("method", c.Method()),
			zap.String("path", c.Path()),
			zap.String("query", queryParams),
			zap.Int("status", c.Response().StatusCode()),
			zap.Float64("duration_ms", float64(duration.Microseconds())/1000.0),
			zap.String("request_id", requestID),
			zap.String("ip", c.IP()),
			zap.String("user_agent", c.Get("User-Agent")),
			zap.Uint("user_id", userID),
			zap.String("request_body", requestBody),
			zap.String("response_body", responseBody),
		)

		return err
	}
}
