from django.views.generic import DetailView, ListView, CreateView
from django.shortcuts import get_object_or_404
from django.core.serializers.json import DjangoJSONEncoder
from django.urls import reverse
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.http import JsonResponse, HttpResponseRedirect
from .models import Ride, RollerCoasterStats
from parks.models import Park
from core.views import SlugRedirectMixin
from moderation.mixins import EditSubmissionMixin, PhotoSubmissionMixin, InlineEditMixin, HistoryMixin
from moderation.models import EditSubmission

class RideCreateView(LoginRequiredMixin, CreateView):
    model = Ride
    template_name = 'rides/ride_form.html'
    fields = ['name', 'park', 'park_area', 'category', 'manufacturer', 'model_name', 'status',
             'opening_date', 'closing_date', 'status_since', 'min_height_in', 'max_height_in',
             'accessibility_options', 'capacity_per_hour', 'ride_duration_seconds', 'description']

    def form_valid(self, form):
        # If user is moderator or above, save directly
        if self.request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
            self.object = form.save()
            return HttpResponseRedirect(self.get_success_url())
        
        # Otherwise, create a submission
        cleaned_data = form.cleaned_data.copy()
        # Convert model instances to IDs for JSON serialization
        if cleaned_data.get('park'):
            cleaned_data['park'] = cleaned_data['park'].id
        if cleaned_data.get('park_area'):
            cleaned_data['park_area'] = cleaned_data['park_area'].id
        if cleaned_data.get('manufacturer'):
            cleaned_data['manufacturer'] = cleaned_data['manufacturer'].id

        submission = EditSubmission.objects.create(
            user=self.request.user,
            content_type=ContentType.objects.get_for_model(Ride),
            submission_type='CREATE',
            changes=cleaned_data,
            reason=self.request.POST.get('reason', ''),
            source=self.request.POST.get('source', '')
        )
        return HttpResponseRedirect(reverse('rides:ride_list'))

    def get_success_url(self):
        return reverse('rides:ride_detail', kwargs={
            'park_slug': self.object.park.slug,
            'ride_slug': self.object.slug
        })

class RideDetailView(SlugRedirectMixin, EditSubmissionMixin, PhotoSubmissionMixin, InlineEditMixin, HistoryMixin, DetailView):
    model = Ride
    template_name = 'rides/ride_detail.html'
    context_object_name = 'ride'
    slug_url_kwarg = 'ride_slug'

    def get_object(self, queryset=None):
        if queryset is None:
            queryset = self.get_queryset()
        park_slug = self.kwargs.get('park_slug')
        ride_slug = self.kwargs.get('ride_slug')
        # Try to get by current or historical slug
        obj, is_old_slug = self.model.get_by_slug(ride_slug)
        if obj.park.slug != park_slug:
            raise self.model.DoesNotExist("Park slug doesn't match")
        return obj

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.object.category == 'RC':
            context['coaster_stats'] = RollerCoasterStats.objects.filter(ride=self.object).first()
        return context

    def get_redirect_url_pattern(self):
        return 'rides:ride_detail'

    def get_redirect_url_kwargs(self):
        return {
            'park_slug': self.object.park.slug,
            'ride_slug': self.object.slug
        }

class RideListView(ListView):
    model = Ride
    template_name = 'rides/ride_list.html'
    context_object_name = 'rides'

    def get_queryset(self):
        queryset = Ride.objects.select_related('park', 'coaster_stats', 'manufacturer').prefetch_related('photos')
        
        search = self.request.GET.get('search', '').strip() or None
        category = self.request.GET.get('category', '').strip() or None
        status = self.request.GET.get('status', '').strip() or None
        manufacturer = self.request.GET.get('manufacturer', '').strip() or None
        
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) | 
                Q(park__name__icontains=search)
            )
        if category:
            queryset = queryset.filter(category=category)
        if status:
            queryset = queryset.filter(status=status)
        if manufacturer:
            # Example: Exclude null manufacturers in RideListView
            queryset = Ride.objects.exclude(manufacturer__isnull=True)
        
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Exclude cases where manufacturer is null or an empty string
        context['manufacturers'] = list(
            Ride.objects.exclude(manufacturer__isnull=True)
                .exclude(manufacturer__isnull=True)
                .values_list('manufacturer__name', flat=True)
                .distinct().order_by('manufacturer__name')
        )

        # Add current filter values to context
        context['current_filters'] = {
            'search': self.request.GET.get('search', ''),
            'category': self.request.GET.get('category', ''),
            'status': self.request.GET.get('status', ''),
            'manufacturer': self.request.GET.get('manufacturer', '')
        }
        
        return context

    def get(self, request, *args, **kwargs):
        # Check if this is an HTMX request
        if request.htmx:
            # If it is, return just the rides list partial
            self.template_name = 'rides/partials/ride_list.html'
        return super().get(request, *args, **kwargs)
