from django.db import transaction
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework import filters, permissions, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

from apps.api.v1.serializers.ride_credits import RideCreditSerializer
from apps.rides.models.credits import RideCredit


class RideCreditViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing Ride Credits.
    Allows users to track rides they have ridden.
    """

    serializer_class = RideCreditSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["user__username", "ride__park__slug", "ride__manufacturer__slug"]
    ordering_fields = ["first_ridden_at", "last_ridden_at", "created_at", "count", "rating", "display_order"]
    ordering = ["display_order", "-last_ridden_at"]

    def get_queryset(self):
        """
        Return ride credits.
        Optionally filter by user via query param ?user=username
        """
        queryset = RideCredit.objects.all().select_related("ride", "ride__park", "user")

        # Filter by user if provided
        username = self.request.query_params.get("user")
        if username:
            queryset = queryset.filter(user__username=username)

        return queryset

    def perform_create(self, serializer):
        """Associate the current user with the ride credit."""
        serializer.save(user=self.request.user)

    @action(detail=False, methods=["post"], permission_classes=[permissions.IsAuthenticated])
    @extend_schema(
        summary="Reorder ride credits",
        description="Bulk update the display order of ride credits. Send a list of {id, order} objects.",
        request={
            "application/json": {
                "type": "object",
                "properties": {
                    "order": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {"id": {"type": "integer"}, "order": {"type": "integer"}},
                            "required": ["id", "order"],
                        },
                    }
                },
            }
        },
    )
    def reorder(self, request):
        """
        Bulk update display_order for multiple credits.
        Expects: {"order": [{"id": 1, "order": 0}, {"id": 2, "order": 1}, ...]}
        """
        order_data = request.data.get("order", [])

        if not order_data:
            return Response({"detail": "No order data provided"}, status=status.HTTP_400_BAD_REQUEST)

        # Validate that all credits belong to the current user
        credit_ids = [item["id"] for item in order_data]
        user_credits = RideCredit.objects.filter(id__in=credit_ids, user=request.user).values_list("id", flat=True)

        if set(credit_ids) != set(user_credits):
            return Response({"detail": "You can only reorder your own credits"}, status=status.HTTP_403_FORBIDDEN)

        # Bulk update in a transaction
        with transaction.atomic():
            for item in order_data:
                RideCredit.objects.filter(id=item["id"], user=request.user).update(display_order=item["order"])

        return Response({"status": "reordered", "count": len(order_data)})

    @extend_schema(
        summary="List ride credits",
        description="List ride credits. filter by user username.",
        parameters=[
            OpenApiParameter(
                name="user",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
                description="Filter by username",
            ),
        ],
    )
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)
