import json
from datetime import datetime
from urllib.parse import urlencode
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.core.serializers import serialize, deserialize
from django.db.models import Q
from django.http import HttpResponse, HttpResponseNotAllowed, JsonResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse, reverse_lazy
from django.views.decorators.csrf import csrf_protect, ensure_csrf_cookie
from django.views.generic import FormView, DeleteView

from articles.forms import SearchForm, ArticleForm, CommentForm
from articles.helpers.views import ListView, CreateView, DetailView, UpdateView
from articles.models import Article


class ArticleListView(ListView):
    form = SearchForm
    search_fields = ('title', 'name')
    template_name = 'articles/list.html'
    model = Article
    context_object_name = 'articles'
    ordering = ['-created_at']
    paginate_by = 5
    paginate_orphans = 1

    def get(self, request, *args, **kwargs):
        request.session['key'] = reverse("author_list")
        print(request.session.items())
        self.form = self.get_search_form()
        self.search_value = self.get_search_value()
        return super().get(request, *args, **kwargs)

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(object_list=object_list, **kwargs)
        context['form'] = self.form
        if self.search_value:
            context['query'] = urlencode({
                'search': self.search_value
            })
        return context

    def get_search_form(self):
        return self.form(self.request.GET)

    def get_search_value(self):
        if self.form.is_valid():
            return self.form.cleaned_data.get('search')

    def get_queryset(self):
        queryset = super().get_queryset()
        if self.search_value:
            query = Q(title__icontains=self.search_value) | \
                    Q(author__name__icontains=self.search_value)
            queryset = queryset.filter(query)
        return queryset


class ArticleCreateView(LoginRequiredMixin, CreateView):
    template_name = 'articles/create.html'
    form_class = ArticleForm
    model = Article

    def get_redirect_url(self):
        return reverse('article_detail', kwargs={'pk': self.object.pk})


class ArticleUpdateView(PermissionRequiredMixin, LoginRequiredMixin, UpdateView):
    model = Article
    template_name = "articles/update.html"
    form_class = ArticleForm
    context_object_name = 'article'
    permission_required = ["articles.change_article", "articles.can_read_article"]

    def get_redirect_url(self):
        return reverse('article_detail', kwargs={
            'pk': self.object.pk
        })


class ArticleDetailView(DetailView):
    template_name = 'articles/detail.html'
    context_object_name = 'article'
    model = Article

    def get(self, request, *args, **kwargs):
        form = CommentForm()
        context = {'form': form, 'article': Article.objects.get(pk=kwargs.get('pk'))}
        return render(request=request, template_name=self.template_name, context=context)


class ArticleDeleteView(DeleteView):
    template_name = 'articles/delete.html'
    model = Article
    context_object_name = 'article'
    confirm_deletion = False
    success_url = reverse_lazy('article_list')

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return redirect('user-login')
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        messages.add_message(self.request, messages.SUCCESS, f"Запись {kwargs.get('pk')} удалена!")
        return self.delete(request, *args, **kwargs)