package middleware

import (
	"bytes"
	"io"
	"net/http"
	"time"

	"api_yal/internal/logger"

	"github.com/go-chi/chi/v5/middleware"
	"go.uber.org/zap"
)

// RequestLoggerMiddleware логирует все HTTP запросы
func RequestLoggerMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		l := logger.Get()

		start := time.Now()

		// Создаем кастомный ResponseWriter для захвата статуса
		ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)

		// Логируем тело запроса только для определенных методов (опционально)
		var body []byte
		if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" {
			body, _ = io.ReadAll(r.Body)
			r.Body = io.NopCloser(bytes.NewBuffer(body))
		}

		// Обрабатываем запрос
		next.ServeHTTP(ww, r)

		// Логируем результат
		duration := time.Since(start)

		logFields := []zap.Field{
			zap.String("method", r.Method),
			zap.String("path", r.URL.Path),
			zap.Int("status", ww.Status()),
			zap.Duration("duration", duration),
			zap.String("remote_addr", r.RemoteAddr),
			zap.String("user_agent", r.UserAgent()),
		}

		// Добавляем ID пользователя, если есть
		if userID, ok := GetUserID(r.Context()); ok {
			logFields = append(logFields, zap.Uint("user_id", userID))
		}

		// Логируем тело запроса для ошибок
		if ww.Status() >= 400 && len(body) > 0 {
			logFields = append(logFields, zap.ByteString("request_body", body))
		}

		// Выбираем уровень логирования в зависимости от статуса
		switch {
		case ww.Status() >= 500:
			l.Error("Request failed", logFields...)
		case ww.Status() >= 400:
			l.Warn("Request error", logFields...)
		default:
			l.Info("Request completed", logFields...)
		}
	})
}
