package middleware

import (
	"aggios-app/backend/internal/config"
	"aggios-app/backend/internal/domain"
	"context"
	"log"
	"net/http"
	"strings"

	"github.com/golang-jwt/jwt/v5"
)

// UnifiedAuthMiddleware valida JWT unificado e permite múltiplos tipos de usuários
func UnifiedAuthMiddleware(cfg *config.Config, allowedTypes ...domain.UserType) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// Extrair token do header Authorization
			authHeader := r.Header.Get("Authorization")
			if authHeader == "" {
				log.Printf("🚫 UnifiedAuth: Missing Authorization header")
				http.Error(w, "Unauthorized: Missing token", http.StatusUnauthorized)
				return
			}

			// Formato esperado: "Bearer <token>"
			parts := strings.Split(authHeader, " ")
			if len(parts) != 2 || parts[0] != "Bearer" {
				log.Printf("🚫 UnifiedAuth: Invalid Authorization format")
				http.Error(w, "Unauthorized: Invalid token format", http.StatusUnauthorized)
				return
			}

			tokenString := parts[1]

			// Parsear e validar token
			token, err := jwt.ParseWithClaims(tokenString, &domain.UnifiedClaims{}, func(token *jwt.Token) (interface{}, error) {
				return []byte(cfg.JWT.Secret), nil
			})

			if err != nil {
				log.Printf("🚫 UnifiedAuth: Token parse error: %v", err)
				http.Error(w, "Unauthorized: Invalid token", http.StatusUnauthorized)
				return
			}

			claims, ok := token.Claims.(*domain.UnifiedClaims)
			if !ok || !token.Valid {
				log.Printf("🚫 UnifiedAuth: Invalid token claims")
				http.Error(w, "Unauthorized: Invalid token", http.StatusUnauthorized)
				return
			}

			// Verificar se o tipo de usuário é permitido
			if len(allowedTypes) > 0 {
				allowed := false
				for _, allowedType := range allowedTypes {
					if claims.UserType == allowedType {
						allowed = true
						break
					}
				}
				if !allowed {
					log.Printf("🚫 UnifiedAuth: User type %s not allowed (allowed: %v)", claims.UserType, allowedTypes)
					http.Error(w, "Forbidden: Insufficient permissions", http.StatusForbidden)
					return
				}
			}

			// Adicionar informações ao contexto
			ctx := r.Context()
			ctx = context.WithValue(ctx, UserIDKey, claims.UserID)
			ctx = context.WithValue(ctx, TenantIDKey, claims.TenantID)
			ctx = context.WithValue(ctx, "email", claims.Email)
			ctx = context.WithValue(ctx, "user_type", string(claims.UserType))
			ctx = context.WithValue(ctx, "role", claims.Role)

			// Para compatibilidade com handlers de portal que esperam CustomerIDKey
			if claims.UserType == domain.UserTypeCustomer {
				ctx = context.WithValue(ctx, CustomerIDKey, claims.UserID)
			}

			log.Printf("✅ UnifiedAuth: Authenticated user_id=%s, type=%s, role=%s, tenant=%s",
				claims.UserID, claims.UserType, claims.Role, claims.TenantID)

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

// RequireAgencyUser middleware que permite apenas usuários de agência (admin, colaborador)
func RequireAgencyUser(cfg *config.Config) func(http.Handler) http.Handler {
	return UnifiedAuthMiddleware(cfg, domain.UserTypeAgency)
}

// RequireCustomer middleware que permite apenas clientes
func RequireCustomer(cfg *config.Config) func(http.Handler) http.Handler {
	return UnifiedAuthMiddleware(cfg, domain.UserTypeCustomer)
}

// RequireAnyAuthenticated middleware que permite qualquer usuário autenticado
func RequireAnyAuthenticated(cfg *config.Config) func(http.Handler) http.Handler {
	return UnifiedAuthMiddleware(cfg) // Sem filtro de tipo
}
