"""
Magic Link (Login by Code) API views.

Provides API endpoints for passwordless login via email code.
Uses django-allauth's built-in login-by-code functionality.
"""

from django.conf import settings
from drf_spectacular.utils import OpenApiExample, extend_schema
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

try:
    from allauth.account.internal.flows.login_by_code import perform_login_by_code, request_login_code
    from allauth.account.models import EmailAddress
    from allauth.account.utils import user_email  # noqa: F401 - imported to verify availability

    HAS_LOGIN_BY_CODE = True
except ImportError:
    HAS_LOGIN_BY_CODE = False


@extend_schema(
    summary="Request magic link login code",
    description="Send a one-time login code to the user's email address.",
    request={
        "application/json": {
            "type": "object",
            "properties": {"email": {"type": "string", "format": "email"}},
            "required": ["email"],
        }
    },
    responses={
        200: {"description": "Login code sent successfully"},
        400: {"description": "Invalid email or feature disabled"},
    },
    examples=[OpenApiExample("Request login code", value={"email": "user@example.com"}, request_only=True)],
)
@api_view(["POST"])
@permission_classes([AllowAny])
def request_magic_link(request):
    """
    Request a login code to be sent to the user's email.

    This is the first step of the magic link flow:
    1. User enters their email
    2. If the email exists, a code is sent
    3. User enters the code to complete login
    """
    if not getattr(settings, "ACCOUNT_LOGIN_BY_CODE_ENABLED", False):
        return Response({"detail": "Magic link login is not enabled"}, status=status.HTTP_400_BAD_REQUEST)

    if not HAS_LOGIN_BY_CODE:
        return Response(
            {"detail": "Login by code is not available in this version of allauth"}, status=status.HTTP_400_BAD_REQUEST
        )

    email = request.data.get("email", "").lower().strip()

    if not email:
        return Response({"detail": "Email is required"}, status=status.HTTP_400_BAD_REQUEST)

    # Check if email exists (don't reveal if it doesn't for security)
    try:
        email_address = EmailAddress.objects.get(email__iexact=email, verified=True)
        user = email_address.user

        # Request the login code
        request_login_code(request._request, user)

        return Response(
            {
                "detail": "If an account exists with this email, a login code has been sent.",
                "timeout": getattr(settings, "ACCOUNT_LOGIN_BY_CODE_TIMEOUT", 300),
            }
        )

    except EmailAddress.DoesNotExist:
        # Don't reveal that the email doesn't exist
        return Response(
            {
                "detail": "If an account exists with this email, a login code has been sent.",
                "timeout": getattr(settings, "ACCOUNT_LOGIN_BY_CODE_TIMEOUT", 300),
            }
        )


@extend_schema(
    summary="Verify magic link code",
    description="Verify the login code and complete the login process.",
    request={
        "application/json": {
            "type": "object",
            "properties": {"email": {"type": "string", "format": "email"}, "code": {"type": "string"}},
            "required": ["email", "code"],
        }
    },
    responses={
        200: {"description": "Login successful"},
        400: {"description": "Invalid or expired code"},
    },
)
@api_view(["POST"])
@permission_classes([AllowAny])
def verify_magic_link(request):
    """
    Verify the login code and complete the login.

    This is the second step of the magic link flow.
    """
    if not getattr(settings, "ACCOUNT_LOGIN_BY_CODE_ENABLED", False):
        return Response({"detail": "Magic link login is not enabled"}, status=status.HTTP_400_BAD_REQUEST)

    if not HAS_LOGIN_BY_CODE:
        return Response({"detail": "Login by code is not available"}, status=status.HTTP_400_BAD_REQUEST)

    email = request.data.get("email", "").lower().strip()
    code = request.data.get("code", "").strip()

    if not email or not code:
        return Response({"detail": "Email and code are required"}, status=status.HTTP_400_BAD_REQUEST)

    try:
        email_address = EmailAddress.objects.get(email__iexact=email, verified=True)
        user = email_address.user

        # Attempt to verify the code and log in
        success = perform_login_by_code(request._request, user, code)

        if success:
            return Response(
                {
                    "detail": "Login successful",
                    "user": {"id": user.id, "username": user.username, "email": user.email},
                }
            )
        else:
            return Response(
                {"detail": "Invalid or expired code. Please request a new one."}, status=status.HTTP_400_BAD_REQUEST
            )

    except EmailAddress.DoesNotExist:
        return Response({"detail": "Invalid email or code"}, status=status.HTTP_400_BAD_REQUEST)
    except Exception:
        return Response(
            {"detail": "Invalid or expired code. Please request a new one."}, status=status.HTTP_400_BAD_REQUEST
        )
