from django.core.paginator import Paginator
from rest_framework.views import APIView
from .models import *
from .serializers import *
from rest_framework import status
from rest_framework.response import Response
from django.db.models import Q
from django.shortcuts import get_object_or_404
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from utils.pagination import StructurePagination
from drf_spectacular.utils import extend_schema, OpenApiParameter
from drf_spectacular.types import OpenApiTypes


class AllCategories(APIView):
    serializer_class = CategorySerializer
    def get(self, request):
        categories = CategoryModel.objects.all()
        categories_ser = self.serializer_class(instance=categories, many=True)
        return Response({"categories": categories_ser.data}, status=status.HTTP_200_OK)

class ProductView(APIView):
    serializer_class = ProductModel
    def get(self, request, pk):
        product = get_object_or_404(ProductModel, id=pk)
        product_ser = self.serializer_class(instance=product, many=False)
        return Response({"product": product_ser.data}, status=status.HTTP_200_OK)

class AllProductsView(APIView):
    serializer_class = ProductSerializer
    pagination_class = StructurePagination

    @extend_schema(
        parameters=[
            OpenApiParameter(
                name="search",
                description="Search by product name or description.",
                required=False,
                type=OpenApiTypes.STR,
            ),
            OpenApiParameter(
                name="category",
                description="Filter by category ID.",
                required=False,
                type=OpenApiTypes.INT,
            ),
            OpenApiParameter(
                name="price_gte",
                description="Filter products with price greater than or equal to this value.",
                required=False,
                type=OpenApiTypes.FLOAT,
            ),
            OpenApiParameter(
                name="price_lte",
                description="Filter products with price less than or equal to this value.",
                required=False,
                type=OpenApiTypes.FLOAT,
            ),
            OpenApiParameter(
                name="sort",
                description=(
                    "Sort results by one of the following fields:\n"
                    "`name`, `-name`, `price`, `-price`, `discount`, `-discount`."
                    "\nPrefix with `-` for descending order."
                ),
                required=False,
                type=OpenApiTypes.STR,
            ),
            OpenApiParameter(
                name="limit",
                description="Number of results to return per page (pagination).",
                required=False,
                type=OpenApiTypes.INT,
            ),
            OpenApiParameter(
                name="offset",
                description="The starting position of the results (pagination).",
                required=False,
                type=OpenApiTypes.INT,
            ),
        ],
        description=(
            "Retrieve products with optional filters and sorting. "
            "Provide a category ID to filter products in that category and its subcategories."
        ),
        responses={
            200: ProductSerializer(many=True),
            404: OpenApiTypes.OBJECT,
        },
    )
    def get(self, request, pk=None):
        try:
            if pk:
                category = Category.objects.get(pk=pk)
                products = ProductModel.objects.filter(category__in=category.get_descendants(include_self=True))
            else:
                products = ProductModel.objects.all()

            search_query = request.query_params.get('search', None)
            if search_query:
                products = products.filter(Q(name__icontains=search_query) | Q(description__icontains=search_query))

            category_filter = request.query_params.get('category', None)
            if category_filter:
                products = products.filter(category__id=category_filter)

            price_gte = request.query_params.get('price_gte', None)
            price_lte = request.query_params.get('price_lte', None)
            if price_gte:
                products = products.filter(price__gte=price_gte)
            if price_lte:
                products = products.filter(price__lte=price_lte)

            sort_by = request.query_params.get('sort', None)
            if sort_by in ['name', '-name', 'price', '-price', 'discount', '-discount']:
                products = products.order_by(sort_by)
            else:
                products = products.order_by('name')

            paginator = self.pagination_class()
            paginated_products = paginator.paginate_queryset(products, request)
            serializer = self.serializer_class(paginated_products, many=True)
            return paginator.get_paginated_response(serializer.data)

        except Category.DoesNotExist:
            return Response({"detail": "Category not found."}, status=status.HTTP_404_NOT_FOUND)


class CommentView(APIView):
    serializer_class = CommentSerializer
    permission_classes = [IsAuthenticatedOrReadOnly]
    def get(self, request, pk):
        product = get_object_or_404(ProductModel, id=pk)
        comments = product.comments.filter(show=True)
        comments_ser = self.serializer_class(instance=comments, many=True)
        return Response({'comments': comments_ser.data}, status=status.HTTP_200_OK)

    def post(self, request, pk):
        comment_ser = CommentSerializer(data=request.data)
        product = get_object_or_404(ProductModel, id=pk)
        if comment_ser.is_valid():
            comment_ser.save(product=product, user=request.user)
            return Response(comment_ser.data, status=status.HTTP_201_CREATED)
        return Response(comment_ser.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        comment = get_object_or_404(CommentModel, pk=pk)
        if comment.user == request.user:
            comment.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            return Response({"detail": "شما اجازه ی پاک کردن این کامنت را ندارید"}, status=status.HTTP_403_FORBIDDEN) 
            

