"""
Authentication backends for CustomUser.
"""
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.db.models import Q


class EmailOrUsernameModelBackend(ModelBackend):
    """Allow login with username OR email (case-insensitive for email)."""

    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        if not username or password is None:
            return None

        login = username.strip()
        try:
            user = UserModel.objects.get(
                Q(username__iexact=login) | Q(email__iexact=login)
            )
        except UserModel.DoesNotExist:
            # Run default password hasher to mitigate timing attacks
            UserModel().set_password(password)
            return None
        except UserModel.MultipleObjectsReturned:
            # Prefer exact username match if both somehow collide
            user = (
                UserModel.objects.filter(username__iexact=login).first()
                or UserModel.objects.filter(email__iexact=login).first()
            )
            if user is None:
                return None

        if user.check_password(password) and self.user_can_authenticate(user):
            return user
        return None
