from django.db.models import Q
from rest_framework import viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser, FileUploadParser
from .models import Event, EventCategory, EventReservation
from .serializers import EventSerializer, EventCategorySerializer, EventReservationSerializer
from users.permissions import IsSuperUser, IsDeltaAdmin, IsPartnerAdmin, IsVisitor
from rest_framework.permissions import IsAuthenticated
from rest_framework.permissions import BasePermission, OR

class EventCategoryViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = EventCategory.objects.all().order_by('name')
    serializer_class = EventCategorySerializer
    permission_classes = [permissions.AllowAny]  # Anyone can view categories
    
    def get_queryset(self):
        # Make sure we're returning all categories
        queryset = EventCategory.objects.all().order_by('name')
        print(f"Returning {queryset.count()} categories")
        return queryset


# Create a custom permission class that combines our permissions
class IsAdminUser(BasePermission):
    def has_permission(self, request, view):
        return (
            IsSuperUser().has_permission(request, view) or
            IsDeltaAdmin().has_permission(request, view) or
            IsPartnerAdmin().has_permission(request, view)
        )

class IsAdminOrVisitorUser(BasePermission):
    def has_permission(self, request, view):
        return (
            IsSuperUser().has_permission(request, view) or
            IsDeltaAdmin().has_permission(request, view) or
            IsPartnerAdmin().has_permission(request, view) or
            IsVisitor().has_permission(request, view)
        )

class EventViewSet(viewsets.ModelViewSet):
    queryset = Event.objects.all()
    serializer_class = EventSerializer
    parser_classes = (MultiPartParser, FormParser, FileUploadParser)
    print("XXXX")
    
    def get_permissions(self):
        if self.action in ['list', 'retrieve']:
            return [permissions.AllowAny()]
        else:
            # Use our custom permission class
            return [permissions.IsAuthenticated(), IsAdminUser()]
    
    # Add a custom create method to handle file uploads
    def create(self, request, *args, **kwargs):
        print("CREATE EVENT DATA:", request.data)
        print("CREATE EVENT FILES:", request.FILES)
        
        # Create a mutable copy of the request data
        data = request.data.copy()
        
        # Handle the image file if present
        if 'image' in request.FILES:
            data['image'] = request.FILES['image']
            print("Image file received:", request.FILES['image'].name)
        elif 'image' in data and (data['image'] == {} or data['image'] == ''):
            # Remove empty image data to prevent validation errors
            data.pop('image')
            print("Removed empty image data")
        
        # Create the serializer with the modified data
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    
    # Also update the update method to handle file uploads
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        
        print("UPDATE EVENT DATA:", request.data)
        print("UPDATE EVENT FILES:", request.FILES)
        
        # Create a mutable copy of the request data
        data = request.data.copy()
        
        # Handle the image file if present
        if 'image' in request.FILES:
            data['image'] = request.FILES['image']
            print("Image file received:", request.FILES['image'].name)
        elif 'image' in data and (data['image'] == {} or data['image'] == ''):
            # Remove empty image data to prevent validation errors
            data.pop('image')
            print("Removed empty image data")
        
        serializer = self.get_serializer(instance, data=data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        
        return Response(serializer.data)
        
    # Add a dedicated endpoint for image uploads
    @action(detail=True, methods=['PUT'], parser_classes=[FileUploadParser])
    def upload_image(self, request, pk=None):
        event = self.get_object()
        
        if 'file' not in request.data:
            return Response({"error": "No image file provided"}, status=status.HTTP_400_BAD_REQUEST)
            
        event.image = request.data['file']
        event.save()
        
        serializer = self.get_serializer(event)
        return Response(serializer.data)
    
    def get_queryset(self):
        user = self.request.user
        queryset = Event.objects.all()

        # If it's a partner admin, only show events for their partner
        if user.is_authenticated and user.is_partner_admin():
            try:
                partner = user.partner_profile.partner
                queryset = queryset.filter(partner=partner)
            except:
                pass
                
        # Filter by featured if requested
        featured = self.request.query_params.get('featured', None)
        if featured is not None and featured.lower() == 'true':
            queryset = queryset.filter(is_featured=True)
            
        # Filter by upcoming if requested
        upcoming = self.request.query_params.get('upcoming', None)
        if upcoming is not None and upcoming.lower() == 'true':
            from django.utils import timezone
            queryset = queryset.filter(date__gt=timezone.now())
            
        # Filter by partner if specified
        partner_id = self.request.query_params.get('partner', None)
        if partner_id:
            if partner_id == 'delta':
                # For "delta", filter events with no partner (Delta Trae's own events)
                queryset = queryset.filter(partner__isnull=True)
            else:
                try:
                    # Try to convert to integer for normal partner IDs
                    partner_id = int(partner_id)
                    queryset = queryset.filter(partner_id=partner_id)
                except ValueError:
                    # If conversion fails, return empty queryset
                    queryset = queryset.none()
        
        # Other filters you might already have
        category_id = self.request.query_params.get('category', None)
        print("CCCCCCCCCCCCCCCC",category_id)
        if category_id:
            queryset = queryset.filter(category_id=category_id)
            
        featured = self.request.query_params.get('featured', None)
        if featured and featured.lower() == 'true':
            queryset = queryset.filter(is_featured=True)
            
        upcoming = self.request.query_params.get('upcoming', None)
        if upcoming and upcoming.lower() == 'true':
            queryset = queryset.filter(date__gte=timezone.now().date())
            
        # Search functionality
        search = self.request.query_params.get('search', None)
        if search:
            queryset = queryset.filter(
                Q(title__icontains=search) | 
                Q(description__icontains=search) | 
                Q(location__icontains=search)
            )
        
        # Filter by wilaya
        wilaya = self.request.query_params.get('wilaya', None)
        if wilaya:
            queryset = queryset.filter(wilaya=wilaya)
        
        return queryset
    
    def perform_create(self, serializer):
        print("CREATE EVENT", serializer)
        # If partner admin, automatically set the partner
        user = self.request.user
        print("CREATE EVENT", serializer)
        if user.is_authenticated and user.is_partner_admin():
            try:
                partner = user.partner_profile.partner
                serializer.save(partner=partner)
            except:
                serializer.save()
        else:
            serializer.save()


class EventReservationViewSet(viewsets.ModelViewSet):
    print("VIEWSSS")
    queryset = EventReservation.objects.all()
    serializer_class = EventReservationSerializer
    print("VIEWSSS")
    def get_permissions(self):
        if self.action == 'create':
            return [permissions.IsAuthenticated()]
        elif self.action in ['update', 'partial_update', 'destroy']:
            # Use our custom permission class
            return [permissions.IsAuthenticated(), IsAdminOrVisitorUser()]
        elif self.action == 'user':  # Add permission for the user action
            return [permissions.IsAuthenticated()]
        else:
            # Use our custom permission class
            return [permissions.IsAuthenticated(), IsAdminUser()]
    
    # Add a custom action for user reservations
    @action(detail=False, methods=['get'])
    def user(self, request):
        """
        Get reservations for the currently authenticated user
        """
        user = request.user
        if not user.is_authenticated:
            return Response(
                {"error": "Authentication required"},
                status=status.HTTP_401_UNAUTHORIZED
            )
            
        # Get reservations for the current user
        reservations = EventReservation.objects.filter(user=user)
        serializer = self.get_serializer(reservations, many=True)
        return Response(serializer.data)
    
    def get_queryset(self):
        user = self.request.user
        print('USER ',user)
        
        if not user.is_authenticated:
            return EventReservation.objects.none()
            
        # Superusers and Delta admins can see all reservations
        if user.is_superuser or user.is_superuser_role() or user.is_delta_admin():
            return EventReservation.objects.all()
            
        # Partner admins can see reservations for their events
        if user.is_partner_admin():
            try:
                partner = user.partner_profile.partner
                return EventReservation.objects.filter(event__partner=partner)
            except:
                return EventReservation.objects.none()
                
        # Regular users can only see their own reservations
        return EventReservation.objects.filter(user=user)
    
    def create(self, request, *args, **kwargs):
        
        # Ensure event_id is properly handled
        if 'event_id' in request.data and not 'event' in request.data:
            request.data._mutable = True
            request.data['event'] = request.data['event_id']
            request.data._mutable = False
  
            
        return super().create(request, *args, **kwargs)
    
    def perform_create(self, serializer):
        # Set the user to the current user for new reservations
        serializer.save(user=self.request.user)

    @action(detail=True, methods=['patch'])
    def update_payment_proof(self, request, pk=None):
        reservation = self.get_object()
        
        if 'payment_proof' not in request.FILES:
            return Response(
                {'error': 'Payment proof file is required'},
                status=status.HTTP_400_BAD_REQUEST
            )

        reservation.payment_proof = request.FILES['payment_proof']
        reservation.status = 'payment_submitted'  # Update status
        reservation.save()

        serializer = self.get_serializer(reservation)
        return Response(serializer.data)

    def partial_update(self, request, *args, **kwargs):
        if 'payment_proof' in request.FILES:
            return self.update_payment_proof(request)
        return super().partial_update(request, *args, **kwargs)
