from django.db.models.base import Model as Model
from django.db.models.query import QuerySet
from django.http import HttpRequest
from django.urls import reverse, reverse_lazy
from accounts import forms, models

from django.views import generic
from django.contrib.auth import login, get_user_model, mixins, update_session_auth_hash, views
from django.shortcuts import redirect
from django.core import exceptions
from django.core.paginator import Paginator
from django.contrib.auth.mixins import LoginRequiredMixin


class RegisterView(generic.CreateView):
    model = get_user_model()
    template_name = 'auth/register.html'
    form_class = forms.RegisterForm
    FORM_TYPE_FORMS = {
        'primary': forms.PrimaryRegisterForm,
        'secondary': forms.SecondaryRegisterForm,
    }
    
    def dispatch(self, request, *args, **kwargs):
        self.form_type = self.request.GET.get('form_type', 'primary')

        if self.form_type.lower() not in self.FORM_TYPE_FORMS:
            raise exceptions.BadRequest

        return super().dispatch(request, *args, **kwargs)
    
    def get_form_class(self):
        return self.FORM_TYPE_FORMS.get(self.form_type, self.form_class)
    
    def get_initial(self):
        initial = super().get_initial()
        
        if self.request.method == 'GET' and self.form_type == 'secondary':
            initial |= {'id': self.request.GET.get('id')}
        
        return initial

    def form_valid(self, form):
        if self.form_type == 'primary':
            user = form.save()

            return redirect(reverse('register') + f'?form_type=secondary&id={user.id}')

        elif self.form_type == 'secondary':
            user = get_user_model().objects.get(id=form.cleaned_data['id'])

            user.is_active = True
            user.set_password(form.cleaned_data['password1'])
            user.save()

            login(self.request, user)
            return redirect(self.get_success_url())
    
    def get_success_url(self):
        return self.request.POST.get(
            'next',
            self.request.GET.get('next', 'index')
        )


class UserDetailView(mixins.LoginRequiredMixin, generic.DetailView):
    model = get_user_model()
    template_name = 'auth/user_detail.html'
    context_object_name = 'user_obj'
    pk_url_kwarg = 'id'
    paginate_by = 3
    paginate_orphans = 0
    
    def __get_paginator(self):
        articles = self.object.articles.order_by('-created_at')
        return Paginator(articles, self.paginate_by, self.paginate_orphans)

    def get_context_data(self, **kwargs):
        # Проверяем, если профиль привязанный к нашему юзеру уже есть, то ничего не делать
        # Если нет, то создать пустой профиль
        models.Profile.objects.get_or_create(user=self.object)

        paginator = self.__get_paginator()

        page_number = self.request.GET.get('page', 1)
        page = paginator.get_page(page_number)

        return super().get_context_data(
            **kwargs,
            paginator=paginator,
            page_obj=page,
            is_paginated=page.has_other_pages(),
        )


class UserUpdateView(LoginRequiredMixin, generic.UpdateView):
    model = get_user_model()
    form_class = forms.UserUpdateForm
    template_name = 'auth/user_update.html'
    context_object_name = 'user_obj'
    pk_url_kwarg = 'id'
    
    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):
        kwargs = {'instance': self.object.profile}

        if self.request.method == 'POST':
            kwargs['data'] = self.request.POST
            kwargs['files'] = self.request.FILES
        
        return forms.ProfileUpdateForm(**kwargs)

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

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

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

    def get_success_url(self):
        return reverse('profile', kwargs={'id': self.object.id})
    
    def get_object(self, queryset=None):
        return self.request.user


class ChangePasswordView(views.PasswordChangeView):
    form_class = forms.ChangePasswordForm
    template_name = 'auth/change_password.html'

    def get_success_url(self):
        return reverse_lazy('profile', kwargs={'id': self.request.user.id})
