from datetime import date

from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import gettext_lazy

from core.extensions import ValidationError
from core.models import UsernameLoginAuthCheck
from core.services.authentication import create_authentication_log_message, handle_login_attempt
from users.models import UserInfo


class ConsoleAuthSystem(BaseBackend):
    def authenticate(self, request, username=None, password=None):
        if request.META.get("HTTP_X_FORWARDED_FOR"):
            ip_address = request.META.get("HTTP_X_FORWARDED_FOR")
        elif request.META.get("REMOTE_ADDR"):
            ip_address = request.META.get("REMOTE_ADDR")
        else:
            ip_address = None
        try:
            logging_user = User.objects.get(username=username)
            if self.check_user_expire_date(logging_user):
                logging_user.is_active = False
                logging_user.save()
                raise ValidationError(gettext_lazy("The credentials have expired"))
        except User.DoesNotExist:
            create_authentication_log_message('attempt', f'[{username}] does not exist', ip_address)
            return None
        attempt_username_data = UsernameLoginAuthCheck.objects.get_or_create(user=logging_user)[0]
        if logging_user.check_password(password):
            login_allowed, message = handle_login_attempt(attempt_username_data, True, ip_address)
            if login_allowed:
                return logging_user
            else:
                raise ValidationError(message)
        else:
            _, message = handle_login_attempt(attempt_username_data, False, ip_address)
            raise ValidationError(message)

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

    def check_user_expire_date(self, user):
        """We check whether the user's expiration date has not expired.
        If expired, we return False , if not True. Superuser passed
        """
        if user.is_superuser:
            return False
        try:
            user_info = UserInfo.objects.get(user=user)
            if user_info.expire_date < date.today():
                return True
            else:
                return False
        except ObjectDoesNotExist:
            UserInfo.objects.create(user=user, expire_date=date.today())
            return False
        except TypeError:
            return False
