package server

import (
	"context"
	"net/http"

	"dance-lessons-coach/pkg/greet"
	"dance-lessons-coach/pkg/user"

	"github.com/rs/zerolog/log"
)

// AuthMiddleware handles JWT authentication and adds user to context
type AuthMiddleware struct {
	authService user.AuthService
}

// NewAuthMiddleware creates a new authentication middleware
func NewAuthMiddleware(authService user.AuthService) *AuthMiddleware {
	return &AuthMiddleware{
		authService: authService,
	}
}

// Middleware returns the authentication middleware function
func (m *AuthMiddleware) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		// Extract Authorization header
		authHeader := r.Header.Get("Authorization")
		if authHeader == "" {
			// No authorization header, pass through with no user
			next.ServeHTTP(w, r)
			return
		}

		// Extract token from "Bearer <token>" format
		const bearerPrefix = "Bearer "
		if len(authHeader) < len(bearerPrefix) || authHeader[:len(bearerPrefix)] != bearerPrefix {
			log.Trace().Ctx(ctx).Str("auth_header", authHeader).Msg("Invalid authorization header format")
			next.ServeHTTP(w, r)
			return
		}

		token := authHeader[len(bearerPrefix):]

		// Validate JWT token
		validatedUser, err := m.authService.ValidateJWT(ctx, token)
		if err != nil {
			log.Trace().Ctx(ctx).Err(err).Msg("JWT validation failed")
			next.ServeHTTP(w, r)
			return
		}

		// Add user to context
		ctxWithUser := context.WithValue(ctx, greet.UserContextKey, validatedUser)
		r = r.WithContext(ctxWithUser)

		// Continue to next handler
		next.ServeHTTP(w, r)
	})
}
