"""Sign in with a username, a verified mobile number, or the legacy personnel code."""
from __future__ import annotations

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

from domain.value_objects import normalize_iran_mobile


def find_user_by_identifier(raw: str):
    User = get_user_model()
    identifier = str(raw).strip()
    if not identifier:
        return None

    user = User.objects.filter(username__iexact=identifier).first()
    if user:
        return user

    user = User.objects.filter(personnel_code=identifier).first()
    if user:
        return user

    mobile = normalize_iran_mobile(identifier)
    if mobile:
        return User.objects.filter(mobile=mobile, mobile_verified_at__isnull=False).first()
    return None


class IdentifierBackend(ModelBackend):
    def authenticate(self, request, identifier=None, password=None, personnel_code=None, username=None, **kwargs):
        raw = identifier or personnel_code or username
        if not raw or password is None:
            return None
        user = find_user_by_identifier(raw)
        if user is None:
            # Burn comparable time so unknown identifiers are not distinguishable by latency.
            get_user_model()().set_password(password)
            return None
        if user.check_password(password) and self.user_can_authenticate(user):
            return user
        return None
