from rest_framework import generics, status, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.pagination import PageNumberPagination
from django.db.models import Q, Count, Case, When, IntegerField, Exists, OuterRef, Value
from django.utils import timezone
from .models import Service, ServiceLike, ServiceSave
from .serializers import (
    ServiceSerializer, ServiceDetailSerializer,
    ServiceCreateSerializer, ServiceUpdateSerializer,
)


class IsVendor(permissions.BasePermission):
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.user_type == 'vendor' and
            hasattr(request.user, 'vendor_profile')
        )


class IsAdmin(permissions.BasePermission):
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.user_type == 'admin'
        )


class ServicePagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 50


# ============== PUBLIC ==============

class ServiceListView(generics.ListAPIView):
    """List all active services (public)"""
    serializer_class = ServiceSerializer
    permission_classes = [permissions.AllowAny]
    pagination_class = ServicePagination

    def get_queryset(self):
        queryset = Service.objects.filter(status='active').select_related('vendor', 'vendor__user')

        # Filter by vendor ID
        vendor = self.request.query_params.get('vendor')
        if vendor:
            queryset = queryset.filter(vendor_id=vendor)

        # Filter by vendor slug
        vendor_slug = self.request.query_params.get('vendor_slug')
        if vendor_slug:
            queryset = queryset.filter(vendor__slug=vendor_slug)

        # Filter by service slug (for single service lookup)
        slug = self.request.query_params.get('slug')
        if slug:
            queryset = queryset.filter(slug=slug)

        category = self.request.query_params.get('category')
        if category:
            queryset = queryset.filter(category=category)

        search = self.request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) |
                Q(description__icontains=search)
            )

        county = self.request.query_params.get('county')
        if county:
            queryset = queryset.filter(vendor__user__county__iexact=county)

        price_type = self.request.query_params.get('price_type')
        if price_type:
            queryset = queryset.filter(price_type=price_type)

        min_price = self.request.query_params.get('min_price')
        max_price = self.request.query_params.get('max_price')
        if min_price:
            queryset = queryset.filter(price__gte=min_price)
        if max_price:
            queryset = queryset.filter(price__lte=max_price)

        service_type = self.request.query_params.get('service_type')
        if service_type:
            queryset = queryset.filter(service_type=service_type)

        # Priority annotation: sponsored > verified > pro > default
        from promotions.utils import annotate_priority
        queryset = annotate_priority(queryset, 'service')

        sort = self.request.query_params.get('sort')
        if sort == 'popular':
            queryset = queryset.annotate(total_likes=Count('likes')).order_by('-priority', '-total_likes')
        elif sort == 'views':
            queryset = queryset.order_by('-priority', '-views')
        elif sort == 'price_low':
            queryset = queryset.order_by('-priority', 'price')
        elif sort == 'price_high':
            queryset = queryset.order_by('-priority', '-price')
        else:
            queryset = queryset.order_by('-priority', '-created_at')

        return queryset


class ServiceDetailView(APIView):
    """Get service detail (public)"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, pk):
        try:
            service = Service.objects.select_related('vendor', 'vendor__user').get(pk=pk, status='active')
        except Service.DoesNotExist:
            return Response({'success': False, 'message': 'Service not found'}, status=status.HTTP_404_NOT_FOUND)

        service.views += 1
        service.save(update_fields=['views'])

        serializer = ServiceDetailSerializer(service, context={'request': request})
        return Response({'success': True, 'data': serializer.data}, status=status.HTTP_200_OK)


class VendorServicesPublicView(generics.ListAPIView):
    """List services by a specific vendor (public)"""
    serializer_class = ServiceSerializer
    permission_classes = [permissions.AllowAny]
    pagination_class = ServicePagination

    def get_queryset(self):
        vendor_id = self.kwargs.get('vendor_id')
        return Service.objects.filter(
            vendor_id=vendor_id,
            status='active'
        ).select_related('vendor', 'vendor__user')


class VendorServicesPublicBySlugView(generics.ListAPIView):
    """List services by vendor slug (public)"""
    serializer_class = ServiceSerializer
    permission_classes = [permissions.AllowAny]
    pagination_class = ServicePagination

    def get_queryset(self):
        vendor_slug = self.kwargs.get('vendor_slug')
        return Service.objects.filter(
            vendor__slug=vendor_slug,
            status='active'
        ).select_related('vendor', 'vendor__user')


# ============== VENDOR MANAGEMENT ==============

class VendorMyServicesView(APIView):
    """List vendor's own services"""
    permission_classes = [IsVendor]

    def get(self, request):
        services = Service.objects.filter(
            vendor=request.user.vendor_profile
        ).exclude(status='deleted')
        serializer = ServiceSerializer(services, many=True, context={'request': request})
        return Response({'success': True, 'data': serializer.data}, status=status.HTTP_200_OK)


class ServiceCreateView(generics.CreateAPIView):
    """Create a new service"""
    serializer_class = ServiceCreateSerializer
    permission_classes = [IsVendor]
    parser_classes = [MultiPartParser, FormParser]

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        service = serializer.save()
        output = ServiceSerializer(service, context={'request': request})
        return Response({'success': True, 'data': output.data}, status=status.HTTP_201_CREATED)


class ServiceUpdateView(APIView):
    """Update a service"""
    permission_classes = [IsVendor]
    parser_classes = [MultiPartParser, FormParser]

    def put(self, request, pk):
        try:
            service = Service.objects.get(pk=pk, vendor=request.user.vendor_profile)
        except Service.DoesNotExist:
            return Response({'success': False, 'message': 'Service not found'}, status=status.HTTP_404_NOT_FOUND)

        serializer = ServiceUpdateSerializer(service, data=request.data, partial=True, context={'request': request})
        serializer.is_valid(raise_exception=True)
        service = serializer.save()
        output = ServiceSerializer(service, context={'request': request})
        return Response({'success': True, 'data': output.data}, status=status.HTTP_200_OK)

    def patch(self, request, pk):
        return self.put(request, pk)


class ServiceDeleteView(APIView):
    """Soft delete a service"""
    permission_classes = [IsVendor]

    def delete(self, request, pk):
        try:
            service = Service.objects.get(pk=pk, vendor=request.user.vendor_profile)
        except Service.DoesNotExist:
            return Response({'success': False, 'message': 'Service not found'}, status=status.HTTP_404_NOT_FOUND)

        service.status = 'deleted'
        service.save(update_fields=['status'])

        vendor_profile = request.user.vendor_profile
        vendor_profile.total_services = Service.objects.filter(
            vendor=vendor_profile
        ).exclude(status='deleted').count()
        vendor_profile.save()

        return Response({'success': True, 'message': 'Service deleted'}, status=status.HTTP_200_OK)


# ============== SOCIAL ==============

class ServiceLikeToggleView(APIView):
    """Toggle like on a service"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, service_id):
        try:
            service = Service.objects.get(id=service_id, status='active')
        except Service.DoesNotExist:
            return Response({'success': False, 'message': 'Service not found'}, status=status.HTTP_404_NOT_FOUND)

        like, created = ServiceLike.objects.get_or_create(user=request.user, service=service)
        if not created:
            like.delete()
            return Response({'success': True, 'liked': False, 'likes_count': service.likes.count()})
        return Response({'success': True, 'liked': True, 'likes_count': service.likes.count()})


class ServiceLikeStatusView(APIView):
    """Check if user liked a service"""
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, service_id):
        is_liked = ServiceLike.objects.filter(user=request.user, service_id=service_id).exists()
        return Response({'success': True, 'is_liked': is_liked})


class ServiceSaveToggleView(APIView):
    """Toggle save on a service"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, service_id):
        try:
            service = Service.objects.get(id=service_id, status='active')
        except Service.DoesNotExist:
            return Response({'success': False, 'message': 'Service not found'}, status=status.HTTP_404_NOT_FOUND)

        save, created = ServiceSave.objects.get_or_create(user=request.user, service=service)
        if not created:
            save.delete()
            return Response({'success': True, 'saved': False})
        return Response({'success': True, 'saved': True})


# ============== SERVICE PROVIDERS ==============

class ServiceProvidersView(APIView):
    """List vendors who have active services, prioritized: verified > upgraded > rest"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        from accounts.models import VendorProfile
        from django.db.models import Case, When, IntegerField, Value

        queryset = VendorProfile.objects.filter(
            services__status='active'
        ).distinct().select_related('user')

        search = request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                Q(shop_name__icontains=search) |
                Q(user__county__icontains=search) |
                Q(town_area__icontains=search)
            )

        county = request.query_params.get('county')
        if county:
            queryset = queryset.filter(user__county__iexact=county)

        # Priority: verified first, then upgraded (pro), then rest
        queryset = queryset.annotate(
            priority=Case(
                When(is_verified_vendor=True, then=Value(0)),
                When(is_upgraded=True, then=Value(1)),
                default=Value(2),
                output_field=IntegerField(),
            ),
            active_services_count=Count('services', filter=Q(services__status='active'))
        ).order_by('priority', '-total_followers')

        limit = int(request.query_params.get('limit', 20))
        page = int(request.query_params.get('page', 1))
        start = (page - 1) * limit
        end = start + limit
        total = queryset.count()
        vendors = queryset[start:end]

        data = []
        for v in vendors:
            data.append({
                'id': v.id,
                'vendor_id': v.id,
                'shop_name': v.shop_name,
                'slug': v.slug,
                'shop_logo': v.shop_logo.url if v.shop_logo else None,
                'county': v.user.county if hasattr(v.user, 'county') else None,
                'town_area': v.town_area,
                'total_followers': v.total_followers,
                'total_services': v.active_services_count,
                'rating': float(v.rating),
                'is_verified_vendor': v.is_verified_vendor,
                'is_upgraded': v.is_upgraded,
            })

        return Response({
            'success': True,
            'data': data,
            'count': total,
            'has_more': end < total,
        })


# ============== DISCOVERY ==============

class ServiceCategoriesView(APIView):
    """Get service categories with counts"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        categories = Service.objects.filter(status='active').values('category').annotate(
            count=Count('id')
        ).order_by('-count')

        category_labels = dict(Service.SERVICE_CATEGORY_CHOICES)
        data = [
            {
                'key': cat['category'],
                'label': category_labels.get(cat['category'], cat['category']),
                'count': cat['count'],
            }
            for cat in categories
        ]
        return Response({'success': True, 'data': data})


class TopServicesView(APIView):
    """Get top services by likes/views"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        limit = int(request.query_params.get('limit', 10))
        services = Service.objects.filter(status='active').annotate(
            total_likes=Count('likes')
        ).order_by('-total_likes', '-views').select_related('vendor', 'vendor__user')[:limit]

        serializer = ServiceSerializer(services, many=True, context={'request': request})
        return Response({'success': True, 'data': serializer.data})


class NearMeServicesView(APIView):
    """Get services near user by county"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        county = request.query_params.get('county')
        if not county and request.user.is_authenticated:
            county = request.user.county

        if not county:
            return Response({'success': False, 'message': 'County is required'}, status=status.HTTP_400_BAD_REQUEST)

        services = Service.objects.filter(
            status='active',
            vendor__user__county__iexact=county
        ).select_related('vendor', 'vendor__user').order_by('-created_at')[:50]

        serializer = ServiceSerializer(services, many=True, context={'request': request})
        return Response({'success': True, 'data': serializer.data, 'county': county})


# ============== ADMIN ==============

class AdminServicesListView(APIView):
    """Admin: list all services"""
    permission_classes = [IsAdmin]

    def get(self, request):
        queryset = Service.objects.all().select_related('vendor', 'vendor__user')

        search = request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) |
                Q(vendor__shop_name__icontains=search)
            )

        category = request.query_params.get('category')
        if category:
            queryset = queryset.filter(category=category)

        status_filter = request.query_params.get('status')
        if status_filter:
            queryset = queryset.filter(status=status_filter)

        paginator = ServicePagination()
        page = paginator.paginate_queryset(queryset, request)
        if page is not None:
            serializer = ServiceSerializer(page, many=True, context={'request': request})
            paginated = paginator.get_paginated_response(serializer.data)
            return Response({
                'success': True,
                'data': paginated.data['results'],
                'count': paginated.data['count'],
                'next': paginated.data['next'],
                'previous': paginated.data['previous'],
            })
        serializer = ServiceSerializer(queryset, many=True, context={'request': request})
        return Response({'success': True, 'data': serializer.data})


class AdminServiceToggleView(APIView):
    """Admin: toggle service status"""
    permission_classes = [IsAdmin]

    def post(self, request, pk):
        try:
            service = Service.objects.get(pk=pk)
        except Service.DoesNotExist:
            return Response({'success': False, 'message': 'Service not found'}, status=status.HTTP_404_NOT_FOUND)

        new_status = request.data.get('status', 'active' if service.status == 'paused' else 'paused')
        service.status = new_status
        service.save(update_fields=['status'])
        return Response({'success': True, 'message': f'Service status changed to {new_status}', 'status': new_status})


class AdminServiceDeleteView(APIView):
    """Admin: delete a service"""
    permission_classes = [IsAdmin]

    def delete(self, request, pk):
        try:
            service = Service.objects.get(pk=pk)
        except Service.DoesNotExist:
            return Response({'success': False, 'message': 'Service not found'}, status=status.HTTP_404_NOT_FOUND)

        service.status = 'deleted'
        service.save(update_fields=['status'])

        vendor_profile = service.vendor
        vendor_profile.total_services = Service.objects.filter(
            vendor=vendor_profile
        ).exclude(status='deleted').count()
        vendor_profile.save()

        return Response({'success': True, 'message': 'Service deleted'})
