from django.contrib.auth import (
    authenticate, login, logout, get_user_model, update_session_auth_hash
)
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import Group
from django.core.exceptions import ValidationError
from django.core.paginator import Paginator
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django.views.generic import DetailView, UpdateView

from .forms import RegisterForm, MyRegisterForm, UserChangeForm, ProfileChangeForm, PasswordChangeForm
from .models import Profile


class LogoutView(View):
    def get(self, request, *args, **kwargs):
        logout(request)
        next = request.GET.get('next')
        if next:
            return redirect(next)
        return redirect('user-login')


class LoginView(View):
    def get(self, request, *args, **kwargs):
        return render(
            request=request,
            template_name='login.html',
        )

    def post(self, request, *args, **kwargs):
        context = {}
        username = request.POST.get("username")
        password = request.POST.get("pass")
        user = authenticate(
            request,
            username=username,
            password=password
        )
        if user:
            login(request, user)
            next = request.GET.get('next')
            if next:
                return redirect(next)
            return redirect('article_list')
        else:
            context['has_error'] = True
        return render(
            request=request,
            template_name='login.html',
            context=context
        )


class RegisterView(View):
    def get(self, request, *args, **kwargs):
        form = MyRegisterForm()
        return render(
            request,
            template_name='register.html',
            context={"form": form})

    def post(self, request, *args, **kwargs):
        try:
            form = MyRegisterForm(data=request.POST)
            if form.is_valid():
                user = form.save()
                Profile.objects.create(user=user)
                group = Group.objects.get(name="Новые пользователи")
                group.user_set.add(user)
                login(request, user)
                return redirect('article_list')
        except ValidationError as e:
            print(e)
        return render(
            request,
            template_name='register.html',
            context={"form": form})


class UserDetailView(LoginRequiredMixin, DetailView):
    model = get_user_model()
    template_name = "user_detail.html"
    context_object_name = "user_obj"
    paginate_related_by = 5
    paginate_related_orphans = 0

    def get_context_data(self, **kwargs):
        articles = self.object.articles.order_by('-created_at')
        paginator = Paginator(articles, self.paginate_related_by, self.paginate_related_orphans)
        page_number = self.request.GET.get('page', 1)
        page = paginator.get_page(page_number)
        kwargs['page_obj'] = page
        kwargs['articles'] = page.object_list
        kwargs['is_paginated'] = page.has_other_pages()
        return super(UserDetailView, self).get_context_data(**kwargs)


class UserChangeView(UserPassesTestMixin, UpdateView):
    model = get_user_model()
    form_class = UserChangeForm
    template_name = 'user_change.html'
    context_object_name = 'user_obj'

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form()
        profile_form = self.get_profile_form()
        if form.is_valid() and profile_form.is_valid():
            return self.form_valid(form, profile_form)
        else:
            return self.form_invalid(form, profile_form)

    def form_valid(self, form, profile_form):
        response = super(UserChangeView, self).form_valid(form=form)
        profile_form.save()
        return response

    def form_invalid(self, form, profile_form):
        context = self.get_context_data(form=form, profile_form=profile_form)
        return self.render_to_response(context)

    def get_context_data(self, **kwargs):
        if 'profile_form' not in kwargs:
            kwargs['profile_form'] = self.get_profile_form()
        return super().get_context_data(**kwargs)

    def get_profile_form(self):
        form_kwargs = {'instance': self.object.profile}
        if self.request.method == "POST":
            form_kwargs['data'] = self.request.POST
            form_kwargs['files'] = self.request.FILES
        return ProfileChangeForm(**form_kwargs)

    def get_success_url(self):
        return reverse('user-detail', kwargs={
            'pk': self.object.pk
        })

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


class UserPasswordChangeView(UserPassesTestMixin, UpdateView):
    model = get_user_model()
    template_name = 'user_password_change.html'
    form_class = PasswordChangeForm
    context_object_name = 'user_obj'

    def form_valid(self, form):
        user = form.save()
        update_session_auth_hash(self.request, user)
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse('user-detail', kwargs={'pk': self.object.pk})

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