from django.db.models import Avg, Count
from rest_framework import viewsets, status, generics
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated, IsAdminUser, AllowAny

from .models import FeedbackEvent, FeedbackCategory, Feedback, FeedbackConfiguration
from .serializers import (
    FeedbackEventSerializer, FeedbackCategorySerializer,
    FeedbackSerializer, PublicFeedbackSerializer, FeedbackConfigSerializer,
)


class FeedbackEventViewSet(viewsets.ModelViewSet):
    serializer_class = FeedbackEventSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        qs = FeedbackEvent.objects.all()
        is_active = self.request.query_params.get('is_active')
        is_archived = self.request.query_params.get('is_archived')
        if is_active is not None:
            qs = qs.filter(is_active=is_active.lower() == 'true')
        if is_archived is not None:
            qs = qs.filter(is_archived=is_archived.lower() == 'true')
        return qs

    def get_permissions(self):
        if self.action in ['list', 'retrieve']:
            return [IsAuthenticated()]
        return [IsAdminUser()]

    @action(detail=True, methods=['post'], permission_classes=[IsAdminUser])
    def archive(self, request, pk=None):
        event = self.get_object()
        event.archive()
        # If this was the active feedback event, clear it
        config = FeedbackConfiguration.get_config()
        if config.active_event == event:
            config.active_event = None
            config.save()
        return Response({'status': 'archived', 'event': FeedbackEventSerializer(event).data})

    @action(detail=True, methods=['post'], permission_classes=[IsAdminUser])
    def unarchive(self, request, pk=None):
        event = self.get_object()
        event.unarchive()
        return Response({'status': 'unarchived', 'event': FeedbackEventSerializer(event).data})

    @action(detail=True, methods=['post'], permission_classes=[IsAdminUser])
    def set_active(self, request, pk=None):
        event = self.get_object()
        config = FeedbackConfiguration.get_config()
        config.active_event = event
        config.feedback_enabled = True
        config.save()
        return Response({'status': 'active event set', 'event': FeedbackEventSerializer(event).data})


class FeedbackCategoryViewSet(viewsets.ModelViewSet):
    queryset = FeedbackCategory.objects.all()
    serializer_class = FeedbackCategorySerializer
    permission_classes = [IsAuthenticated]

    def get_permissions(self):
        if self.action in ['list', 'retrieve']:
            return [AllowAny()]
        return [IsAdminUser()]


class FeedbackViewSet(viewsets.ModelViewSet):
    serializer_class = FeedbackSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        qs = Feedback.objects.select_related('feedback_event', 'category').all()
        event_id = self.request.query_params.get('event_id')
        category_id = self.request.query_params.get('category_id')
        rating = self.request.query_params.get('rating')
        search = self.request.query_params.get('search')
        is_published = self.request.query_params.get('is_published')

        if event_id:
            qs = qs.filter(feedback_event_id=event_id)
        if category_id:
            qs = qs.filter(category_id=category_id)
        if rating:
            qs = qs.filter(rating=rating)
        if search:
            qs = qs.filter(comment__icontains=search)
        if is_published is not None:
            qs = qs.filter(is_published=is_published.lower() == 'true')
        return qs

    def get_permissions(self):
        if self.action in ['list', 'retrieve']:
            return [IsAuthenticated()]
        return [IsAdminUser()]


class PublicEventStatsView(APIView):
    """Public endpoint: live stats for a published event (no comments)."""
    permission_classes = [AllowAny]

    def get(self, request, slug):
        try:
            event = FeedbackEvent.objects.get(slug=slug, is_active=True, is_archived=False)
        except FeedbackEvent.DoesNotExist:
            return Response({'error': 'Event not found.'}, status=status.HTTP_404_NOT_FOUND)

        if not event.is_stats_published:
            return Response({'published': False}, status=status.HTTP_403_FORBIDDEN)

        feedbacks = Feedback.objects.filter(feedback_event=event, is_published=True)
        total = feedbacks.count()
        avg_rating = feedbacks.aggregate(avg=Avg('rating'))['avg'] or 0

        rating_dist = {
            item['rating']: item['count']
            for item in feedbacks.values('rating').annotate(count=Count('rating')).order_by('rating')
        }

        category_breakdown = []
        for cat in FeedbackCategory.objects.filter(is_active=True):
            count = feedbacks.filter(category=cat).count()
            category_breakdown.append({'id': cat.id, 'name': cat.name, 'count': count})

        return Response({
            'published': True,
            'event_name': event.name,
            'event_description': event.description,
            'total_feedback': total,
            'average_rating': round(avg_rating, 1),
            'rating_distribution': rating_dist,
            'category_breakdown': sorted(category_breakdown, key=lambda x: -x['count']),
        })


class PublicEventDetailView(APIView):
    """Public endpoint: get event details by slug for feedback form."""
    permission_classes = [AllowAny]

    def get(self, request, slug):
        try:
            event = FeedbackEvent.objects.get(slug=slug, is_active=True, is_archived=False)
            return Response(FeedbackEventSerializer(event).data)
        except FeedbackEvent.DoesNotExist:
            return Response({'error': 'Event not found or inactive.'}, status=status.HTTP_404_NOT_FOUND)


class PublicEventCategoriesView(APIView):
    """Public endpoint: get active categories for an event."""
    permission_classes = [AllowAny]

    def get(self, request, slug):
        try:
            event = FeedbackEvent.objects.get(slug=slug, is_active=True, is_archived=False)
            categories = FeedbackCategory.objects.filter(is_active=True)
            return Response(FeedbackCategorySerializer(categories, many=True).data)
        except FeedbackEvent.DoesNotExist:
            return Response({'error': 'Event not found.'}, status=status.HTTP_404_NOT_FOUND)


class PublicFeedbackSubmitView(APIView):
    """Public endpoint: submit feedback for a specific event by slug."""
    permission_classes = [AllowAny]

    def post(self, request):
        event_slug = request.data.get('event_slug')
        if not event_slug:
            return Response({'error': 'event_slug is required.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            event = FeedbackEvent.objects.get(slug=event_slug, is_active=True, is_archived=False)
        except FeedbackEvent.DoesNotExist:
            return Response({'error': 'Event not found or inactive.'}, status=status.HTTP_404_NOT_FOUND)

        data = request.data.copy()
        data['feedback_event'] = event.id

        serializer = PublicFeedbackSerializer(data=data)
        if serializer.is_valid():
            ip = self._get_client_ip(request)
            feedback = serializer.save(ip_address=ip, feedback_event=event)
            return Response({
                'success': True,
                'message': 'Thank you for your feedback!',
            }, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def _get_client_ip(self, request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            return x_forwarded_for.split(',')[0].strip()
        return request.META.get('REMOTE_ADDR')


class PublicFeedbackView(APIView):
    """Public endpoint: submit feedback (legacy - uses active event from config)."""
    permission_classes = [AllowAny]

    def get(self, request):
        """Return current feedback configuration for the form."""
        config = FeedbackConfiguration.get_config()
        if not config.feedback_enabled:
            return Response({'enabled': False, 'message': config.disabled_message})

        active_event = config.active_event
        if not active_event or not active_event.is_active:
            return Response({'enabled': False, 'message': config.disabled_message})

        categories = FeedbackCategory.objects.filter(is_active=True)
        return Response({
            'enabled': True,
            'welcome_message': config.welcome_message,
            'active_event': FeedbackEventSerializer(active_event).data,
            'categories': FeedbackCategorySerializer(categories, many=True).data,
        })

    def post(self, request):
        config = FeedbackConfiguration.get_config()
        if not config.feedback_enabled:
            return Response({'success': False, 'message': config.disabled_message}, status=status.HTTP_403_FORBIDDEN)

        data = request.data.copy()
        if config.active_event:
            data['feedback_event'] = config.active_event.id

        serializer = PublicFeedbackSerializer(data=data)
        if serializer.is_valid():
            ip = self._get_client_ip(request)
            feedback = serializer.save(ip_address=ip)
            return Response({
                'success': True,
                'message': config.thank_you_message,
            }, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def _get_client_ip(self, request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            return x_forwarded_for.split(',')[0].strip()
        return request.META.get('REMOTE_ADDR')


class FeedbackDashboardView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        event_id = request.query_params.get('event_id')

        feedbacks = Feedback.objects.filter(is_published=True)
        selected_event = None

        if event_id:
            try:
                selected_event = FeedbackEvent.objects.get(id=event_id)
                feedbacks = feedbacks.filter(feedback_event=selected_event)
            except FeedbackEvent.DoesNotExist:
                pass

        total = feedbacks.count()
        avg_rating = feedbacks.aggregate(avg=Avg('rating'))['avg'] or 0

        rating_dist = {
            item['rating']: item['count']
            for item in feedbacks.values('rating').annotate(count=Count('rating')).order_by('rating')
        }

        category_breakdown = []
        for cat in FeedbackCategory.objects.filter(is_active=True):
            count = feedbacks.filter(category=cat).count()
            category_breakdown.append({'id': cat.id, 'name': cat.name, 'count': count})

        recent = FeedbackSerializer(feedbacks.order_by('-created_at')[:10], many=True).data

        available_events = FeedbackEvent.objects.filter(is_archived=False).order_by('-created_at')

        return Response({
            'total_feedback': total,
            'average_rating': round(avg_rating, 1),
            'rating_distribution': rating_dist,
            'category_breakdown': category_breakdown,
            'recent_feedback': recent,
            'selected_event': FeedbackEventSerializer(selected_event).data if selected_event else None,
            'available_events': FeedbackEventSerializer(available_events, many=True).data,
        })


class FeedbackConfigView(generics.RetrieveUpdateAPIView):
    serializer_class = FeedbackConfigSerializer
    permission_classes = [IsAdminUser]

    def get_object(self):
        return FeedbackConfiguration.get_config()
