from django.db.models import Prefetch

from rest_framework import status
from rest_framework.generics import (
    GenericAPIView,
    ListAPIView,
    RetrieveUpdateAPIView,
    RetrieveUpdateDestroyAPIView,
    get_object_or_404,
)
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from newsreader.accounts.permissions import IsPostOwner
from newsreader.core.pagination import CursorPagination
from newsreader.news.collection.models import CollectionRule
from newsreader.news.collection.serializers import RuleSerializer
from newsreader.news.core.filters import SavedFilter
from newsreader.news.core.models import Category, Post
from newsreader.news.core.serializers import CategorySerializer, PostSerializer


class ListPostView(ListAPIView):
    queryset = Post.objects.filter(read=False)
    serializer_class = PostSerializer
    permission_classes = (IsAuthenticated, IsPostOwner)
    pagination_class = CursorPagination
    filter_backends = [SavedFilter]


class DetailPostView(RetrieveUpdateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = (IsAuthenticated, IsPostOwner)


class ListCategoryView(ListAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

    def get_queryset(self):
        user = self.request.user
        return self.queryset.filter(user=user).order_by("-created", "-modified")


class DetailCategoryView(RetrieveUpdateDestroyAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer


class NestedRuleCategoryView(ListAPIView):
    queryset = Category.objects.prefetch_related("rules").all()
    serializer_class = RuleSerializer

    def get_queryset(self):
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

        # Default permission is IsOwner, therefore there shouldn't have to be
        # filtered on the user.
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}

        category = get_object_or_404(self.queryset, **filter_kwargs)
        self.check_object_permissions(self.request, category)

        return category.rules.order_by("name")


class NestedPostCategoryView(ListAPIView):
    serializer_class = PostSerializer
    pagination_class = CursorPagination

    def get_queryset(self):
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

        # Default permission is IsOwner, therefore there shouldn't have to be
        # filtered on the user.
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}

        rules_queryset = CollectionRule.objects.filter(user=self.request.user)
        prefetch = Prefetch("rules", queryset=rules_queryset, to_attr="user_rules")
        category_queryset = Category.objects.prefetch_related(prefetch).filter(
            user=self.request.user
        )
        category = get_object_or_404(category_queryset, **filter_kwargs)

        self.check_object_permissions(self.request, category)

        return Post.objects.filter(rule__in=category.user_rules, read=False)


class CategoryReadView(GenericAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

    def post(self, request, *args, **kwargs):
        category = self.get_object()

        (
            Post.objects.filter(
                rule__in=category.rules.values_list("pk", flat=True)
            ).update(read=True)
        )

        category.refresh_from_db()
        serializer_class = self.get_serializer_class()
        serializer = serializer_class(category)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
