from django.utils.translation import gettext_lazy as _
from django.conf import settings
from django.contrib.auth import login, logout
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.throttling import AnonRateThrottle
from ..models import Member
from ..drf.views import Endpoint
from ..settings import saas_settings
from ..security import check_security_rules
from ..serializers.auth import (
    EmailCode,
    SignupRequestCodeSerializer,
    SignupCreateUserSerializer,
    SignupConfirmCodeSerializer,
    SignupConfirmPasswordSerializer,
)
from ..serializers.password import PasswordLoginSerializer
from ..signals import after_signup_user, after_login_user
from .._notification import send_mail


class SignupRequestEndpoint(Endpoint):
    email_template_id = "signup_code"
    email_subject = _("Signup Request")
    authentication_classes = []
    permission_classes = []
    throttle_classes = [AnonRateThrottle]

    def get_serializer_class(self):
        if saas_settings.SIGNUP_REQUEST_CREATE_USER:
            return SignupCreateUserSerializer
        return SignupRequestCodeSerializer

    def post(self, request: Request):
        """Send a sign-up code to user's email address."""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        obj: EmailCode = serializer.save()

        # check bad request rules
        check_security_rules(saas_settings.SIGNUP_SECURITY_RULES, request)

        send_mail(
            self.__class__,
            self.email_subject,
            self.email_template_id,
            recipients=[obj.recipient()],
            code=obj.code,
        )
        return Response(status=204)


class AuthEndpoint(Endpoint):
    authentication_classes = []
    permission_classes = []
    throttle_classes = [AnonRateThrottle]

    def login_user(self, request: Request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        login(request._request, user, 'django.contrib.auth.backends.ModelBackend')
        return user


class SignupConfirmEndpoint(AuthEndpoint):
    def get_serializer_class(self):
        if saas_settings.SIGNUP_REQUEST_CREATE_USER:
            return SignupConfirmCodeSerializer
        return SignupConfirmPasswordSerializer

    def post(self, request: Request):
        """Register a new user and login."""
        user = self.login_user(request)
        # update related membership
        Member.objects.filter(invite_email=user.email).update(
            user=user,
            status=Member.InviteStatus.WAITING
        )
        after_signup_user.send(
            self.__class__,
            user=user,
            request=request,
            strategy="password",
        )
        return Response({"next": settings.LOGIN_REDIRECT_URL})


class PasswordLogInEndpoint(AuthEndpoint):
    serializer_class = PasswordLoginSerializer

    def post(self, request: Request):
        """Login a user with the given username and password."""
        user = self.login_user(request)
        after_login_user.send(
            self.__class__,
            user=user,
            request=request,
            strategy="password",
        )
        return Response({"next": settings.LOGIN_REDIRECT_URL})


class LogoutEndpoint(AuthEndpoint):
    def post(self, request: Request):
        """Clear the user session and log the user out."""
        logout(request._request)
        return Response({"next": settings.LOGIN_URL})
