from django.db.models import F
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

from apps.stores.detail_serializer import (
    StoreDetailSerializer,
    StoreReviewCreateSerializer,
    StoreReviewSerializer,
)
from apps.stores.filters import StoreFilter
from apps.stores.models import Category, Store, StoreBranch, StoreReview
from apps.stores.serializers import (
    CategorySerializer,
    StoreBranchSerializer,
    StoreListSerializer,
)


class CategoryViewSet(viewsets.ViewSet):
    """ViewSet for store categories."""

    permission_classes = [AllowAny]

    def list(self, request):
        """GET /categories/ — list all categories."""
        categories = Category.objects.all()
        serializer = CategorySerializer(categories, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        """GET /categories/{id}/ — retrieve a category."""
        try:
            category = Category.objects.get(pk=pk)
        except Category.DoesNotExist:
            return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
        serializer = CategorySerializer(category)
        return Response(serializer.data)

    @action(detail=True, methods=["get"], url_path="stores")
    def stores(self, request, pk=None):
        """GET /categories/{id}/stores/ — stores in a category."""
        try:
            category = Category.objects.get(pk=pk)
        except Category.DoesNotExist:
            return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
        stores = Store.objects.filter(categories=category)
        serializer = StoreListSerializer(stores, many=True)
        return Response(serializer.data)


class StoreViewSet(viewsets.ViewSet):
    """ViewSet for stores."""

    permission_classes = [AllowAny]

    def list(self, request):
        """GET /stores/ — list stores with filtering."""
        qs = Store.objects.prefetch_related("categories", "payment_methods").all()
        filterset = StoreFilter(request.query_params, queryset=qs)
        if filterset.is_valid():
            qs = filterset.qs

        # Ordering
        ordering = request.query_params.get("ordering", "-created_at")
        allowed_ordering = ["rating", "-rating", "rating_count", "-rating_count",
                           "views", "-views", "created_at", "-created_at"]
        if ordering in allowed_ordering:
            qs = qs.order_by(ordering)

        serializer = StoreListSerializer(qs, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        """GET /stores/{id}/ — store detail."""
        try:
            store = Store.objects.prefetch_related(
                "categories", "payment_methods", "branches"
            ).get(pk=pk)
        except Store.DoesNotExist:
            return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
        # Increment views
        Store.objects.filter(pk=pk).update(views=F("views") + 1)
        serializer = StoreDetailSerializer(store)
        return Response(serializer.data)

    @action(detail=True, methods=["get"])
    def branches(self, request, pk=None):
        """GET /stores/{id}/branches/ — store branches."""
        branches = StoreBranch.objects.filter(store_id=pk)
        serializer = StoreBranchSerializer(branches, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=["get", "post"])
    def reviews(self, request, pk=None):
        """GET/POST /stores/{id}/reviews/ — store reviews."""
        try:
            store = Store.objects.get(pk=pk)
        except Store.DoesNotExist:
            return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)

        if request.method == "GET":
            reviews = StoreReview.objects.filter(store=store).select_related("user")
            serializer = StoreReviewSerializer(reviews, many=True)
            return Response(serializer.data)

        # POST - create review
        if not request.user.is_authenticated:
            return Response(
                {"detail": "Authentication required."},
                status=status.HTTP_401_UNAUTHORIZED,
            )
        serializer = StoreReviewCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(user=request.user, store=store)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    @action(detail=False, methods=["get"])
    def top(self, request):
        """GET /stores/top/ — top stores."""
        stores = Store.objects.filter(is_top=True)
        serializer = StoreListSerializer(stores, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=["get"])
    def recommended(self, request):
        """GET /stores/recommended/ — recommended stores."""
        stores = Store.objects.filter(is_recommended=True)
        serializer = StoreListSerializer(stores, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=["get"], url_path="recently-added")
    def recently_added(self, request):
        """GET /stores/recently-added/ — recently added stores."""
        stores = Store.objects.filter(is_recently_added=True)
        serializer = StoreListSerializer(stores, many=True)
        return Response(serializer.data)
