from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth import get_user_model
from dj_waanverse_auth.utils.email_utils import send_auth_code_via_email
from dj_waanverse_auth.models import AccessCode
from django.core.exceptions import ValidationError
from logging import getLogger
from dj_waanverse_auth import settings as auth_config
from rest_framework.permissions import AllowAny
from rest_framework.decorators import permission_classes
from dj_waanverse_auth.utils.login import handle_login

logger = getLogger(__name__)
Account = get_user_model()


@api_view(["POST"])
@permission_classes([AllowAny])
def login_view(request):
    email_address = request.data.get("email_address")
    code = request.data.get("code")

    if email_address is None:
        return Response(
            {"detail": "Email address is required."},
            status=status.HTTP_400_BAD_REQUEST,
        )

    if code is None:
        return _request_code_flow(email_address)

    return _verify_code_flow(request, email_address, code)


def _request_code_flow(email):
    try:
        if email == "johndoe@gmail.com":
            if auth_config.is_testing:
                return Response(
                    {"detail": "Authentication code sent to email."},
                    status=status.HTTP_200_OK,
                )
            else:
                return Response(
                    {"detail": "Something went wrong."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
        account = Account.objects.filter(email_address=email).first()
        if not account:
            return Response(
                {"detail": "Account not found."},
                status=status.HTTP_404_NOT_FOUND,
            )

        send_auth_code_via_email(account)
        return Response(
            {"detail": "Authentication code sent to email."},
            status=status.HTTP_200_OK,
        )
    except ValueError as e:
        return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
    except ValidationError:
        return Response(
            {"detail": "Invalid email address"}, status=status.HTTP_400_BAD_REQUEST
        )
    except Exception as e:
        return Response(
            {"detail": str(e)},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR,
        )


def _verify_code_flow(request, email, code):
    access_instance = AccessCode.objects.filter(code=code, email_address=email).first()
    if email != "johndoe@gmail.com" or not auth_config.is_testing:
        if not access_instance or access_instance.is_expired():
            return Response(
                {"detail": "Invalid or expired code."},
                status=status.HTTP_400_BAD_REQUEST,
            )
    account = Account.objects.filter(email_address=email).first()
    if not account:
        return Response(
            {"detail": "Account not found."},
            status=status.HTTP_404_NOT_FOUND,
        )

    if not account.email_verified or not account.is_active:
        account.email_verified = True
        account.is_active = True
        account.save(update_fields=["email_verified", "is_active"])

    # Login and return response (e.g., tokens or session)
    response = handle_login(request, account)

    # Delete used code
    if email != "johndoe@gmail.com" or not auth_config.is_testing:
        access_instance.delete()

    return response
