from django.views.generic import TemplateView, RedirectView
from django.views.generic.edit import UpdateView
from django.shortcuts import redirect
from django.urls import reverse
from django.dispatch import receiver
from django.contrib.auth import logout as auth_logout
from django.contrib.auth import user_logged_in, user_logged_out, user_login_failed
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import PasswordChangeView
from django.contrib import messages

from urllib.parse import quote as urlquote

from .forms import AccountSettingsForm


class LoginView(TemplateView):
    template_name = "registration/login_switch.html"

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            return redirect(self.get_next_url() or "/")

        return super().dispatch(request, *args, **kwargs)

    def get_next_url(self):
        if self.request.method == "GET":
            req_dict = self.request.GET
        elif self.request.method == "POST":
            req_dict = self.request.POST
        return req_dict.get("next")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        next_url = self.get_next_url()
        if next_url:
            context["pass_url"] = "{}?next={}".format(
                reverse("accounts:password_login"), urlquote(next_url, safe="")
            )
            context["cas_url"] = "{}?next={}".format(
                reverse("accounts:cas_ng_login"), urlquote(next_url, safe="")
            )
        else:
            context["pass_url"] = reverse("accounts:password_login")
            context["cas_url"] = reverse("accounts:cas_ng_login")

        return context


class LogoutView(RedirectView):
    permanent = False

    def get_redirect_url(self, *args, **kwargs):
        CAS_BACKEND_NAME = "accounts.backends.CasBackend"
        if self.request.session["_auth_user_backend"] != CAS_BACKEND_NAME:
            auth_logout(self.request)
            if "next" in self.request.GET:
                return self.request.GET["next"]
            return reverse("website:home")

        if "next" in self.request.GET:
            return "{}?next={}".format(
                reverse("accounts:cas_ng_logout"),
                urlquote(self.request.GET["next"], safe=""),
            )
        return reverse("accounts:cas_ng_logout")


@receiver(user_logged_in)
def on_login(request, user, **kwargs):
    messages.success(request, "Connexion réussie. Bienvenue, {}.".format(user))


@receiver(user_logged_out)
def on_logout(request, **kwargs):
    messages.info(request, "Vous avez bien été déconnecté·e.")


@receiver(user_login_failed)
def on_login_failed(request, **kwargs):
    messages.error(request, "Connexion échouée.")


class PasswordChangeView(PasswordChangeView):
    template_name = "registration/change_password.html"

    def __init__(self):
        self.form_class.error_css_class = "errorfield"

    def get_success_url(self):
        messages.info(self.request, "Mot de passe mis à jour")
        return reverse("accounts:account_settings")


class AccountSettingsView(LoginRequiredMixin, UpdateView):
    template_name = "registration/account_settings.html"
    form_class = AccountSettingsForm

    def get_object(self):
        return self.request.user

    def get_success_url(self):
        return self.request.get_full_path()

    def form_valid(self, form):
        messages.success(self.request, "Paramètres du compte mis à jour")
        return super().form_valid(form)
