"""Product app views."""
from django.conf import settings
from django.shortcuts import get_object_or_404
from rest_framework import generics, permissions

from comment.models import Comment
from comment.serializers import CommentRUDSerializer
from product import filters, serializers
from product.models import Product
from utils.views import FavoritesCreateDestroyMixinView
from utils.pagination import PortionPagination
from django.conf import settings


class ProductBaseView(generics.GenericAPIView):
    """Product base view"""
    permission_classes = (permissions.AllowAny,)

    def get_queryset(self):
        """Override get_queryset method."""
        return Product.objects.published() \
            .with_base_related() \
            .annotate_in_favorites(self.request.user) \
            .order_by('-created')


class ProductListView(ProductBaseView, generics.ListAPIView):
    """List view for model Product."""
    serializer_class = serializers.ProductBaseSerializer
    filter_class = filters.ProductFilterSet

    def get_queryset(self):
        qs = super().get_queryset().with_extended_related() \
                                   .by_country_code(self.request.country_code)
        return qs


class ProductSimilarView(ProductListView):
    """Resource for getting a list of similar product."""
    serializer_class = serializers.ProductBaseSerializer
    pagination_class = None

    def get_base_object(self):
        """
        Return base product instance for a getting list of similar products.
        """
        product = get_object_or_404(Product.objects.all(),
                                    slug=self.kwargs.get('slug'))
        return product


class ProductDetailView(ProductBaseView, generics.RetrieveAPIView):
    """Detail view fro model Product."""
    lookup_field = 'slug'
    serializer_class = serializers.ProductDetailSerializer


class CreateFavoriteProductView(FavoritesCreateDestroyMixinView):
    """View for create/destroy product in favorites."""

    _model = Product
    serializer_class = serializers.ProductFavoritesCreateSerializer


class ProductCommentCreateView(generics.CreateAPIView):
    """View for create new comment."""
    lookup_field = 'slug'
    serializer_class = serializers.ProductCommentCreateSerializer
    queryset = Comment.objects.all()


class ProductCommentListView(generics.ListAPIView):
    """View for return list of product comments."""

    permission_classes = (permissions.AllowAny,)
    serializer_class = serializers.ProductCommentCreateSerializer

    def get_queryset(self):
        """Override get_queryset method"""
        product = get_object_or_404(Product, slug=self.kwargs['slug'])
        return product.comments.order_by('-created')


class ProductCommentRUDView(generics.RetrieveUpdateDestroyAPIView):
    """View for retrieve/update/destroy product comment."""
    serializer_class = CommentRUDSerializer
    queryset = Product.objects.all()

    def get_object(self):
        """Returns the object the view is displaying."""
        queryset = self.filter_queryset(self.get_queryset())

        product_obj = get_object_or_404(queryset,
                                        slug=self.kwargs['slug'])
        comment_obj = get_object_or_404(product_obj.comments.by_user(self.request.user),
                                        pk=self.kwargs['comment_id'])

        # May raise a permission denied
        self.check_object_permissions(self.request, comment_obj)

        return comment_obj


class SimilarListView(ProductSimilarView):
    """Return similar products."""

    def get_queryset(self):
        """Overridden get_queryset method."""
        qs = super(SimilarListView, self).get_queryset()
        base_product = self.get_base_object()

        if base_product:
            return qs.has_location().similar(slug=self.kwargs.get('slug'))[:settings.QUERY_OUTPUT_OBJECTS]
        else:
            return qs.none()
