package helper

import (
	"authentication/models"
	"errors"
	"log"
	"os"
	"strings"

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

func ExtractEmailFromToken(tokenString string) (string, error) {
	// Remove "Bearer " prefix if it exists
	tokenString = strings.TrimPrefix(tokenString, "Bearer ")

	// Handle null/empty token cases
	if tokenString == "" || tokenString == "null" || tokenString == "undefined" {
		return "", errors.New("no valid token provided")
	}

	token, err := jwt.ParseWithClaims(tokenString, &models.AccessToken{}, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("unexpected signing method")
		}
		secretKey := os.Getenv("JWT_SECRET_KEY")
		if secretKey == "" {
			return nil, errors.New("JWT secret key not set")
		}
		return []byte(secretKey), nil
	})

	if err == nil && token.Valid {
		if claims, ok := token.Claims.(*models.AccessToken); ok {
			if claims.Email != "" && strings.Contains(claims.Email, "@") {
				log.Printf("Successfully extracted email from AccessToken: %s", claims.Email)
				return claims.Email, nil
			}
		}
	}

	// If AccessToken parsing failed, try MapClaims for backward compatibility
	log.Printf("AccessToken parsing failed: %v, trying MapClaims fallback", err)
	token, err = jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("unexpected signing method")
		}
		secretKey := os.Getenv("JWT_SECRET_KEY")
		if secretKey == "" {
			return nil, errors.New("JWT secret key not set")
		}
		return []byte(secretKey), nil
	})

	if err != nil {
		log.Printf("MapClaims parsing also failed: %v", err)
		return "", errors.New("invalid token signature")
	}

	// Extract claims from MapClaims
	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok || !token.Valid {
		return "", errors.New("invalid token claims")
	}

	if email, ok := claims["email"].(string); ok && strings.Contains(email, "@") {
		log.Printf("Successfully extracted email from MapClaims: %s", email)
		return email, nil
	}

	return "", errors.New("email not found in token")
}
