"""Product app back-office views."""
from django.shortcuts import get_object_or_404
from rest_framework import generics, status, permissions, views
from rest_framework.response import Response

from product import serializers, models
from product.views import ProductBaseView
from utils.serializers import ImageBaseSerializer
from utils.views import CreateDestroyGalleryViewMixin
from utils.permissions import IsLiquorReviewer, IsProductReviewer


class ProductBackOfficeMixinView(ProductBaseView):
    """Product back-office mixin view."""

    permission_classes = (permissions.IsAuthenticated, )

    def get_queryset(self):
        """Override get_queryset method."""
        qs = models.Product.objects.annotate_in_favorites(self.request.user)
        return qs


class ProductTypeBackOfficeMixinView:
    """Product type back-office mixin view."""

    permission_classes = (permissions.IsAuthenticated,)
    queryset = models.ProductType.objects.all()


class ProductSubTypeBackOfficeMixinView:
    """Product sub type back-office mixin view."""

    permission_classes = (permissions.IsAuthenticated,)
    queryset = models.ProductSubType.objects.all()


class BackOfficeListCreateMixin(views.APIView):
    """Back-office list-create mixin view."""

    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        if self.request.method != 'GET':
            super().check_permissions(request)


class ProductBackOfficeGalleryCreateDestroyView(ProductBackOfficeMixinView,
                                                CreateDestroyGalleryViewMixin):
    """Resource for a create gallery for product for back-office users."""
    serializer_class = serializers.ProductBackOfficeGallerySerializer

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

        product = get_object_or_404(product_qs, pk=self.kwargs.get('pk'))
        gallery = get_object_or_404(product.product_gallery, image_id=self.kwargs.get('image_id'))

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

        return gallery


class ProductBackOfficeGalleryListView(ProductBackOfficeMixinView,
                                       generics.ListAPIView):
    """Resource for returning gallery for product for back-office users."""
    serializer_class = ImageBaseSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_object(self):
        """Override get_object method."""
        qs = super(ProductBackOfficeGalleryListView, self).get_queryset()
        product = get_object_or_404(qs, pk=self.kwargs.get('pk'))

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

        return product

    def get_queryset(self):
        """Override get_queryset method."""
        return self.get_object().crop_gallery


class ProductDetailBackOfficeView(ProductBackOfficeMixinView,
                                  generics.RetrieveUpdateDestroyAPIView):
    """Product back-office R/U/D view."""
    serializer_class = serializers.ProductBackOfficeDetailSerializer
    permission_classes = [IsLiquorReviewer | IsProductReviewer]


class ProductListCreateBackOfficeView(BackOfficeListCreateMixin, ProductBackOfficeMixinView,
                                      generics.ListCreateAPIView):
    """Product back-office list-create view."""
    serializer_class = serializers.ProductBackOfficeDetailSerializer
    permission_classes = [IsLiquorReviewer | IsProductReviewer]


class ProductTypeListCreateBackOfficeView(BackOfficeListCreateMixin,
                                          ProductTypeBackOfficeMixinView,
                                          generics.ListCreateAPIView):
    """Product type back-office list-create view."""
    serializer_class = serializers.ProductTypeBackOfficeDetailSerializer


class ProductTypeRUDBackOfficeView(BackOfficeListCreateMixin,
                                   ProductTypeBackOfficeMixinView,
                                   generics.RetrieveUpdateDestroyAPIView):
    """Product type back-office retrieve-update-destroy view."""
    serializer_class = serializers.ProductTypeBackOfficeDetailSerializer


class ProductTypeTagCategoryCreateBackOfficeView(ProductTypeBackOfficeMixinView,
                                                 generics.CreateAPIView):
    """View for attaching tag category to product type."""
    serializer_class = serializers.ProductTypeTagCategorySerializer

    def create(self, request, *args, **kwargs):
        super().create(request, *args, **kwargs)
        return Response(status=status.HTTP_201_CREATED)


class ProductSubTypeListCreateBackOfficeView(BackOfficeListCreateMixin,
                                             ProductSubTypeBackOfficeMixinView,
                                             generics.ListCreateAPIView):
    """Product sub type back-office list-create view."""
    serializer_class = serializers.ProductSubTypeBackOfficeDetailSerializer


class ProductSubTypeRUDBackOfficeView(BackOfficeListCreateMixin,
                                      ProductSubTypeBackOfficeMixinView,
                                      generics.RetrieveUpdateDestroyAPIView):
    """Product sub type back-office retrieve-update-destroy view."""
    serializer_class = serializers.ProductSubTypeBackOfficeDetailSerializer


class ProductNoteListCreateView(ProductBackOfficeMixinView,
                                BackOfficeListCreateMixin,
                                generics.ListCreateAPIView):
    """Retrieve|Update|Destroy product note view."""

    serializer_class = serializers.ProductNoteListCreateSerializer

    def get_object(self):
        """Returns the object the view is displaying."""
        product_qs = models.Product.objects.all()
        filtered_product_qs = self.filter_queryset(product_qs)

        product = get_object_or_404(filtered_product_qs, pk=self.kwargs.get('pk'))

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

        return product

    def get_queryset(self):
        """Overridden get_queryset method."""
        return self.get_object().notes.all()


class ProductNoteRUDView(ProductBackOfficeMixinView,
                         BackOfficeListCreateMixin,
                         generics.RetrieveUpdateDestroyAPIView):
    """Create|Retrieve|Update|Destroy product note view."""

    serializer_class = serializers.ProductNoteBaseSerializer

    def get_object(self):
        """Returns the object the view is displaying."""
        product_qs = models.Product.objects.all()
        filtered_product_qs = self.filter_queryset(product_qs)

        product = get_object_or_404(filtered_product_qs, pk=self.kwargs.get('pk'))
        note = get_object_or_404(product.notes.all(), pk=self.kwargs.get('note_pk'))

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

        return note
