"""
Custom JWT Token Generation for ThrillWiki

This module provides custom JWT token generation that includes authentication
method claims for enhanced MFA satisfaction logic.

Claims added:
- auth_method: How the user authenticated (password, passkey, totp, google, discord)
- mfa_verified: Whether MFA was verified during this login
- provider_mfa: Whether the OAuth provider (Discord) has MFA enabled
"""

from typing import Literal, TypedDict

from rest_framework_simplejwt.tokens import RefreshToken

# Type definitions for auth methods
AuthMethod = Literal["password", "passkey", "totp", "google", "discord"]


class TokenClaims(TypedDict, total=False):
    """Type definition for custom JWT claims."""

    auth_method: AuthMethod
    mfa_verified: bool
    provider_mfa: bool


def create_tokens_for_user(
    user,
    auth_method: AuthMethod = "password",
    mfa_verified: bool = False,
    provider_mfa: bool = False,
) -> dict[str, str]:
    """
    Generate JWT tokens with custom authentication claims.

    Args:
        user: The Django user object
        auth_method: How the user authenticated
        mfa_verified: True if MFA (TOTP/passkey) was verified at login
        provider_mfa: True if OAuth provider (Discord) has MFA enabled

    Returns:
        Dictionary with 'access' and 'refresh' token strings
    """
    refresh = RefreshToken.for_user(user)

    # Add custom claims to both refresh and access tokens
    refresh["auth_method"] = auth_method
    refresh["mfa_verified"] = mfa_verified
    refresh["provider_mfa"] = provider_mfa

    access = refresh.access_token

    return {
        "access": str(access),
        "refresh": str(refresh),
    }


def get_auth_method_for_provider(provider: str) -> AuthMethod:
    """
    Map OAuth provider name to AuthMethod type.

    Args:
        provider: The provider name (e.g., 'google', 'discord')

    Returns:
        The corresponding AuthMethod
    """
    provider_map: dict[str, AuthMethod] = {
        "google": "google",
        "discord": "discord",
    }
    return provider_map.get(provider, "password")


def get_provider_mfa_status(provider: str, extra_data: dict) -> bool:
    """
    Extract MFA status from OAuth provider extra_data.

    Only Discord exposes mfa_enabled. Google does not share this info.

    Args:
        provider: The OAuth provider name
        extra_data: The extra_data dict from SocialAccount

    Returns:
        True if provider has MFA enabled, False otherwise
    """
    if provider == "discord":
        return extra_data.get("mfa_enabled", False)

    # Google and other providers don't expose MFA status
    return False
