// auth.go
package middleware

import (
	"api_es/internal/utils"
	"api_es/pkg/logger"
	"context"
	"net/http"
	"strings"

	"go.uber.org/zap"
)

type contextKey string

const (
	UserIDKey    contextKey = "userID"
	UserEmailKey contextKey = "userEmail"
	UserRoleKey  contextKey = "userRole"
)

// Cookie конфигурация
const (
	AuthCookieName = "auth_token"
	CookieMaxAge   = 24 * 60 * 60 // 24 часа
)

func AuthMiddleware(next http.Handler) http.Handler {
	zapLogger := logger.Get()
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		zapLogger.Debug("Debug start AuthMiddleware")

		var tokenString string

		// Пробуем получить токен из заголовка Authorization
		authHeader := r.Header.Get("Authorization")
		if authHeader != "" {
			tokenString = strings.Replace(authHeader, "Bearer ", "", 1)
			zapLogger.Debug("Token from Authorization header", zap.String("token", tokenString))
		}

		// Если токена нет в заголовке, пробуем получить из куки
		if tokenString == "" {
			cookie, err := r.Cookie(AuthCookieName)
			if err == nil && cookie.Value != "" {
				tokenString = cookie.Value
				zapLogger.Debug("Token from cookie", zap.String("token", tokenString))
			}
		}

		if tokenString == "" {
			http.Error(w, "Authorization required", http.StatusUnauthorized)
			return
		}

		// Валидируем токен
		jwtUtil := utils.NewJWTUtil("secret")
		claims, err := jwtUtil.ValidateToken(tokenString)
		if err != nil {
			// Если токен невалиден, удаляем куку
			http.SetCookie(w, &http.Cookie{
				Name:     AuthCookieName,
				Value:    "",
				Path:     "/",
				MaxAge:   -1,
				HttpOnly: true,
				Secure:   true,
				SameSite: http.SameSiteStrictMode,
			})
			http.Error(w, "Invalid token", http.StatusUnauthorized)
			return
		}

		ctx := context.WithValue(r.Context(), UserIDKey, claims.UserID)
		ctx = context.WithValue(ctx, UserEmailKey, claims.Email)
		ctx = context.WithValue(ctx, UserRoleKey, claims.Role)

		zapLogger.Debug("Debug end AuthMiddleware")

		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

// Вспомогательная функция для установки auth cookie
func SetAuthCookie(w http.ResponseWriter, token string) {
	http.SetCookie(w, &http.Cookie{
		Name:     AuthCookieName,
		Value:    token,
		Path:     "/",
		MaxAge:   CookieMaxAge,
		HttpOnly: true,
		Secure:   true, // В production должно быть true
		SameSite: http.SameSiteStrictMode,
	})
}

// Вспомогательная функция для удаления auth cookie
func ClearAuthCookie(w http.ResponseWriter) {
	http.SetCookie(w, &http.Cookie{
		Name:     AuthCookieName,
		Value:    "",
		Path:     "/",
		MaxAge:   -1,
		HttpOnly: true,
		Secure:   true,
		SameSite: http.SameSiteStrictMode,
	})
}

func AdminMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		role, ok := r.Context().Value(UserRoleKey).(string)
		if !ok || role != "admin" {
			http.Error(w, "Admin access required", http.StatusForbidden)
			return
		}
		next.ServeHTTP(w, r)
	})
}
