package middleware

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

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

const (
	CustomerIDKey contextKey = "customer_id"
)

// CustomerAuthMiddleware valida tokens JWT de clientes do portal
func CustomerAuthMiddleware(cfg *config.Config) 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 == "" {
				http.Error(w, "Authorization header required", http.StatusUnauthorized)
				return
			}

			// Remover "Bearer " prefix
			tokenString := strings.TrimPrefix(authHeader, "Bearer ")
			if tokenString == authHeader {
				http.Error(w, "Invalid authorization format", http.StatusUnauthorized)
				return
			}

			// Parse e validar token
			token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
				// Verificar método de assinatura
				if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
					return nil, jwt.ErrSignatureInvalid
				}
				return []byte(cfg.JWT.Secret), nil
			})

			if err != nil || !token.Valid {
				log.Printf("Invalid token: %v", err)
				http.Error(w, "Invalid or expired token", http.StatusUnauthorized)
				return
			}

			// Extrair claims
			claims, ok := token.Claims.(jwt.MapClaims)
			if !ok {
				http.Error(w, "Invalid token claims", http.StatusUnauthorized)
				return
			}

			// Verificar se é token de customer
			tokenType, _ := claims["type"].(string)
			if tokenType != "customer_portal" {
				http.Error(w, "Invalid token type", http.StatusUnauthorized)
				return
			}

			// Extrair customer_id e tenant_id
			customerID, ok := claims["customer_id"].(string)
			if !ok {
				http.Error(w, "Invalid customer_id in token", http.StatusUnauthorized)
				return
			}

			tenantID, ok := claims["tenant_id"].(string)
			if !ok {
				http.Error(w, "Invalid tenant_id in token", http.StatusUnauthorized)
				return
			}

			// Adicionar ao contexto
			ctx := context.WithValue(r.Context(), CustomerIDKey, customerID)
			ctx = context.WithValue(ctx, TenantIDKey, tenantID)

			// Prosseguir com a requisição
			next.ServeHTTP(w, r.WithContext(ctx))
		})
	}
}
