"""
Park review API views for ThrillWiki API v1.

This module contains park review ViewSet following the reviews pattern.
Provides CRUD operations for park reviews nested under parks/{slug}/reviews/
"""

import logging

from django.core.exceptions import PermissionDenied
from django.db.models import Avg
from django.utils import timezone
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound, ValidationError
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from apps.api.v1.serializers.park_reviews import (
    ParkReviewCreateInputSerializer,
    ParkReviewListOutputSerializer,
    ParkReviewOutputSerializer,
    ParkReviewStatsOutputSerializer,
    ParkReviewUpdateInputSerializer,
)
from apps.parks.models import Park, ParkReview

logger = logging.getLogger(__name__)


@extend_schema_view(
    list=extend_schema(
        summary="List park reviews",
        tags=["Park Reviews"],
    ),
    create=extend_schema(
        summary="Create park review",
        tags=["Park Reviews"],
    ),
    retrieve=extend_schema(
        summary="Get park review details",
        tags=["Park Reviews"],
    ),
    update=extend_schema(
        summary="Update park review",
        tags=["Park Reviews"],
    ),
    partial_update=extend_schema(
        summary="Partially update park review",
        tags=["Park Reviews"],
    ),
    destroy=extend_schema(
        summary="Delete park review",
        tags=["Park Reviews"],
    ),
)
class ParkReviewViewSet(ModelViewSet):
    """
    ViewSet for managing park reviews with full CRUD operations.
    """

    lookup_field = "id"

    def get_permissions(self):
        """Set permissions based on action."""
        permission_classes = [AllowAny] if self.action in ["list", "retrieve", "stats"] else [IsAuthenticated]
        return [permission() for permission in permission_classes]

    def get_queryset(self):
        """Get reviews for the current park."""
        queryset = ParkReview.objects.select_related("park", "user", "user__profile")

        park_slug = self.kwargs.get("park_slug")
        if park_slug:
            try:
                park, _ = Park.get_by_slug(park_slug)
                queryset = queryset.filter(park=park)
            except Park.DoesNotExist:
                return queryset.none()

        if not (hasattr(self.request, "user") and getattr(self.request.user, "is_staff", False)):
            queryset = queryset.filter(is_published=True)

        return queryset.order_by("-created_at")

    def get_serializer_class(self):
        if self.action == "list":
            return ParkReviewListOutputSerializer
        elif self.action == "create":
            return ParkReviewCreateInputSerializer
        elif self.action in ["update", "partial_update"]:
            return ParkReviewUpdateInputSerializer
        else:
            return ParkReviewOutputSerializer

    def perform_create(self, serializer):
        park_slug = self.kwargs.get("park_slug")
        try:
            park, _ = Park.get_by_slug(park_slug)
        except Park.DoesNotExist:
            raise NotFound("Park not found") from None

        if ParkReview.objects.filter(park=park, user=self.request.user).exists():
            raise ValidationError("You have already reviewed this park")

        serializer.save(park=park, user=self.request.user, is_published=True)

    def perform_update(self, serializer):
        instance = self.get_object()
        if not (self.request.user == instance.user or getattr(self.request.user, "is_staff", False)):
            raise PermissionDenied("You can only edit your own reviews.")
        serializer.save()

    def perform_destroy(self, instance):
        if not (self.request.user == instance.user or getattr(self.request.user, "is_staff", False)):
            raise PermissionDenied("You can only delete your own reviews.")
        instance.delete()

    @extend_schema(
        summary="Get park review statistics",
        responses={200: ParkReviewStatsOutputSerializer},
        tags=["Park Reviews"],
    )
    @action(detail=False, methods=["get"])
    def stats(self, request, park_slug=None):
        try:
            park, _ = Park.get_by_slug(park_slug)
        except Park.DoesNotExist:
            return Response({"detail": "Park not found"}, status=status.HTTP_404_NOT_FOUND)

        reviews = ParkReview.objects.filter(park=park, is_published=True)
        total_reviews = reviews.count()
        avg_rating = reviews.aggregate(avg=Avg("rating"))["avg"]

        rating_distribution = {}
        for i in range(1, 11):
            rating_distribution[str(i)] = reviews.filter(rating=i).count()

        from datetime import timedelta

        recent_reviews = reviews.filter(created_at__gte=timezone.now() - timedelta(days=30)).count()

        stats = {
            "total_reviews": total_reviews,
            "published_reviews": total_reviews,
            "pending_reviews": ParkReview.objects.filter(park=park, is_published=False).count(),
            "average_rating": avg_rating,
            "rating_distribution": rating_distribution,
            "recent_reviews": recent_reviews,
        }
        return Response(ParkReviewStatsOutputSerializer(stats).data)
