import json
import ast
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404, render
from django.http.response import Http404, HttpResponse
from django.http.request import HttpRequest
from django.utils.translation import get_language
from django.views.generic import TemplateView, DetailView, ListView, View
from django.db.models import Q
from .models import BlogPost, Category, Keyword

from start.views import SearchableView

import logging
logger = logging.getLogger(__name__)


class Index(TemplateView, SearchableView):
    """
    The index page of the gawa/blog app.

    Utilizes a generic view, because I will do so for all views,
    a regular view function would suffice.
    """

    template_name: str = "blog/index.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['featured_posts'] = BlogPost.objects.filter(
            featured=True, public=True)
        return context


class Post(DetailView):
    """
    Main page of a blog post
    """

    model = BlogPost
    template_name = "blog/blogpost.html"
    context_object_name = "post"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['featured_posts'] = BlogPost.objects.filter(featured=True)
        return context

class Browse(ListView):
    """
    Scroll through a list of blog posts

    There should also be some kind of filter, for category and date.
    Of course, Articles will also show up in the MainSearchView
    """

    model = BlogPost
    template_name = "blog/browse.html"
    context_object_name = "posts"
    paginate_by = 2
    allow_empty = False  # but we have a special get method
    allow_empty = True

    def get_queryset(self):
        objects = BlogPost.objects.all()
        if "category" in self.request.GET and len(
                self.request.GET["category"].strip()) > 0:
            category = self.request.GET["category"]
            try:
                category = Category.objects.get(slug=category)
                objects = objects.filter(category=category)
            except Category.DoesNotExist:
                objects = objects.none()
        if "search" in self.request.GET and len(
                self.request.GET["search"].strip()) > 0:
            search = self.request.GET["search"]
            # __icontains matches those attributes that contain the
            # search string without caring about lower/upper cases
            objects = objects.filter(
                Q(title_en__icontains=search) |
                Q(title_de__icontains=search) |
                Q(subtitle_en__icontains=search) |
                Q(subtitle_de__icontains=search) |
                Q(desc_en__icontains=search) |
                Q(desc_de__icontains=search) |
                # Q(body_en__icontains=search) |
                # Q(body_de__icontains=search) |
                Q(slug__icontains=search)
            )

        if "keywords" in self.request.GET and len(
                self.request.GET["keywords"].strip()) > 0:
            raw_keywords = self.request.GET["keywords"]
            raw_keywords = raw_keywords.split('+')
            keywords: list[Keyword] = []
            for raw_keyword in raw_keywords:
                try:
                    keywords.append(Keyword.objects.get(slug=raw_keyword))
                except Keyword.DoesNotExist:
                    pass
            objects = objects.filter(keywords__in=keywords)
        return objects

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['featured_posts'] = BlogPost.objects.filter(featured=True)
        context['categories'] = Category.objects.all()
        context['keywords'] = Keyword.objects.all()

        context["filters"] = {}
        if "category" in self.request.GET and len(
                self.request.GET["category"].strip()) > 0:
            category = self.request.GET["category"]
            try:
                category = Category.objects.get(slug=category)
                context["filters"]["category"] = category
            except Category.DoesNotExist:
                context["filters"]["category"] = None

        if "search" in self.request.GET and len(
                self.request.GET["search"].strip()) > 0:
            search = self.request.GET["search"]
            context["filters"]["search"] = search

        if "keywords" in self.request.GET and len(
                self.request.GET["keywords"].strip()) > 0:
            keywords = self.request.GET["keywords"]
            keywords = keywords.split('+')
            context["filters"]["keywords"] = keywords
        return context

    def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
        self.object_list = self.get_queryset()
        allow_empty = self.get_allow_empty()

        if not allow_empty:
            # When pagination is enabled and object_list is a queryset,
            # it's better to do a cheap query than to load the unpaginated
            # queryset in memory.
            if self.get_paginate_by(self.object_list) is not None and hasattr(
                    self.object_list, 'exists'):
                is_empty = not self.object_list.exists()
            else:
                is_empty = not self.object_list
        else:
            is_empty = False
        context = self.get_context_data()

        context["is_empty"] = is_empty

        response = self.render_to_response(context)
        if is_empty:
            response.status_code = 404
        return response
