from django.contrib import messages
from django.contrib.auth import update_session_auth_hash, views as auth_views
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import Count, Q
from django.shortcuts import redirect, render
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views import View

from apps.core.crud import BaseCreateView, BaseDeleteView, BaseUpdateView
from apps.core.mixins import AdminRequiredMixin, BackofficeMixin
from apps.core.ratelimit import ratelimit

from . import permissions as perms
from .forms import (
    LoginForm, ProfileForm, StyledPasswordChangeForm, StyledPasswordResetForm, StyledSetPasswordForm, UserForm,
)
from .models import Role, User

# --- Authentification ---------------------------------------------------------


@method_decorator(ratelimit("login", 10), name="dispatch")
class LoginView(auth_views.LoginView):
    template_name = "accounts/login.html"
    authentication_form = LoginForm
    redirect_authenticated_user = True

    def form_valid(self, form):
        if not form.cleaned_data.get("remember"):
            self.request.session.set_expiry(0)
        return super().form_valid(form)


class PasswordResetView(auth_views.PasswordResetView):
    template_name = "accounts/password_reset.html"
    form_class = StyledPasswordResetForm
    email_template_name = "accounts/email/password_reset.txt"
    subject_template_name = "accounts/email/password_reset_subject.txt"
    success_url = reverse_lazy("accounts:password_reset_done")


class PasswordResetConfirmView(auth_views.PasswordResetConfirmView):
    template_name = "accounts/password_reset_confirm.html"
    form_class = StyledSetPasswordForm
    success_url = reverse_lazy("accounts:login")

    def form_valid(self, form):
        messages.success(self.request, "Mot de passe modifié. Vous pouvez vous connecter.")
        return super().form_valid(form)


@login_required
def dashboard_redirect(request):
    """/dashboard : même comportement que Laravel."""
    if perms.can_access_backoffice(request.user):
        return redirect("backoffice:dashboard")
    return redirect("public:home")


# --- Profil -------------------------------------------------------------------

class ProfileView(BackofficeMixin, View):
    def get(self, request):
        return self.render(ProfileForm(instance=request.user), StyledPasswordChangeForm(request.user))

    def post(self, request):
        pform, pwform = ProfileForm(instance=request.user), StyledPasswordChangeForm(request.user)
        if "change_password" in request.POST:
            pwform = StyledPasswordChangeForm(request.user, request.POST)
            if pwform.is_valid():
                pwform.save()
                update_session_auth_hash(request, pwform.user)
                messages.success(request, "Mot de passe modifié.")
                return redirect("users:profile")
        else:
            pform = ProfileForm(request.POST, instance=request.user)
            if pform.is_valid():
                pform.save()
                messages.success(request, "Profil mis à jour.")
                return redirect("users:profile")
        return self.render(pform, pwform, status=400)

    def render(self, pform, pwform, status=200):
        return render(self.request, "backoffice/accounts/profile.html", {"form": pform, "pwform": pwform}, status=status)


# --- Gestion des utilisateurs (administrateurs) --------------------------------

class UserListView(AdminRequiredMixin, View):
    def get(self, request):
        qs = User.objects.annotate(nb_articles=Count("articles", distinct=True))
        if q := request.GET.get("q"):
            qs = qs.filter(Q(name__icontains=q) | Q(email__icontains=q))
        if (role := request.GET.get("role")) in Role.values:
            qs = qs.filter(role=role)
        page = Paginator(qs.order_by("-is_active", "name"), 20).get_page(request.GET.get("page"))
        return render(request, "backoffice/accounts/users.html", {"page_obj": page, "roles": Role.choices})


class UserFormMixin(AdminRequiredMixin):
    model = User
    form_class = UserForm
    back_url = reverse_lazy("users:list")
    wide_fields = ("bio", "email")

    def get_form_kwargs(self):
        return {**super().get_form_kwargs(), "current_user": self.request.user}


class UserCreateView(UserFormMixin, BaseCreateView):
    page_title = "Nouvel utilisateur"
    success_message = "Compte de %(name)s créé."


class UserUpdateView(UserFormMixin, BaseUpdateView):
    success_message = "Compte de %(name)s mis à jour."


class UserDeleteView(AdminRequiredMixin, BaseDeleteView):
    model = User
    success_url = reverse_lazy("users:list")
    success_message = "Utilisateur supprimé."

    def check(self, obj):
        if obj.pk == self.request.user.pk:
            return "Vous ne pouvez pas supprimer votre propre compte."
        if obj.articles.exists() or obj.annonces.exists():
            return f"{obj} est l'auteur de contenus : désactivez plutôt le compte pour conserver l'historique."
