from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import CreateView, ListView, TemplateView
from django.contrib import messages
from django.urls import reverse_lazy
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.db.models import Q, Count, Avg
from django.utils import timezone
from datetime import date
import json

from .models import Feedback, FeedbackConfiguration, FeedbackCategory
from .forms import FeedbackForm
from registration.models import Event, Registration
from attendance.models import RegisteredUser

class FeedbackFormView(CreateView):
    model = Feedback
    template_name = 'feedback/feedback_form.html'
    fields = ['category', 'rating', 'comment', 'tags', 'name', 'email', 'registration_code']
    success_url = reverse_lazy('feedback:thank_you')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get feedback configuration
        config = FeedbackConfiguration.get_active_config()
        context['config'] = config
        
        if config:
            # Get available events based on configuration mode
            available_events = config.get_available_events()
            context['available_events'] = available_events
            context['is_multi_event'] = config.event_selection_mode == FeedbackConfiguration.MULTI_EVENT
            context['selected_event_id'] = self.request.GET.get('event')
            
            # If single event mode or only one event available, set default
            if len(available_events) == 1:
                context['default_event'] = available_events[0]
            elif context['selected_event_id']:
                # User has pre-selected an event via URL parameter
                try:
                    selected_event = Event.objects.get(id=context['selected_event_id'])
                    if config.is_event_active(selected_event):
                        context['default_event'] = selected_event
                except Event.DoesNotExist:
                    pass
        
        # Get categories and tags for the form
        context['categories'] = FeedbackCategory.objects.filter(is_active=True)
        
        return context
    
    def form_valid(self, form):
        # Get the selected event
        event_id = self.request.POST.get('event_id')
        config = FeedbackConfiguration.get_active_config()
        
        if event_id:
            try:
                event = Event.objects.get(id=event_id)
                if config and config.is_event_active(event):
                    form.instance.event = event
                else:
                    messages.error(self.request, 'Selected event is not active for feedback.')
                    return self.form_invalid(form)
            except Event.DoesNotExist:
                messages.error(self.request, 'Selected event does not exist.')
                return self.form_invalid(form)
        elif config:
            # Use default event if no event selected
            available_events = config.get_available_events()
            if available_events:
                form.instance.event = available_events[0]
            else:
                messages.error(self.request, 'No active events available for feedback.')
                return self.form_invalid(form)
        
        # Handle anonymous flag
        is_anonymous = self.request.POST.get('anonymous') == 'on'
        form.instance.is_anonymous = is_anonymous
        
        if is_anonymous:
            # Clear name and email for anonymous feedback
            form.instance.name = None
            form.instance.email = None
        else:
            # Set name and email from form
            form.instance.name = self.request.POST.get('name', '').strip()
            form.instance.email = self.request.POST.get('email', '').strip()
        
        # Set registration code
        form.instance.registration_code = self.request.POST.get('registration_code', '').strip()
        
        # Set IP address for tracking
        form.instance.ip_address = self.get_client_ip()
        
        # Store event info in session for thank you page
        if form.instance.event:
            self.request.session['feedback_event_name'] = form.instance.event.name
            self.request.session['feedback_event_id'] = form.instance.event.id
        
        messages.success(self.request, 'Thank you for your feedback!')
        return super().form_valid(form)
    
    def get_client_ip(self):
        x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = self.request.META.get('REMOTE_ADDR')
        return ip

@csrf_exempt
def verify_registration_code(request):
    """AJAX endpoint to verify registration code and return user details"""
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            registration_code = data.get('registration_code', '').strip()
            
            if not registration_code:
                return JsonResponse({'success': False, 'message': 'Registration code is required'})
            
            user_data = None
            
            # First, check in the registration module
            try:
                registration = Registration.objects.get(registration_code=registration_code)
                user_data = {
                    'name': registration.full_name,
                    'email': registration.email,
                    'event_name': registration.event.name,
                    'source': 'registration'
                }
            except Registration.DoesNotExist:
                pass
            
            # If not found in registration, check in attendance module
            if not user_data:
                try:
                    registered_user = RegisteredUser.objects.get(registration_code=registration_code)
                    user_data = {
                        'name': registered_user.full_name,
                        'email': registered_user.email,
                        'event_name': registered_user.event_name,
                        'source': 'attendance'
                    }
                except RegisteredUser.DoesNotExist:
                    pass
            
            if user_data:
                return JsonResponse({
                    'success': True,
                    'user_data': user_data,
                    'message': 'Registration code verified successfully'
                })
            else:
                return JsonResponse({
                    'success': False,
                    'message': 'Registration code not found. Please check and try again.'
                })
                
        except json.JSONDecodeError:
            return JsonResponse({'success': False, 'message': 'Invalid request format'})
        except Exception as e:
            return JsonResponse({'success': False, 'message': 'An error occurred during verification'})
    
    return JsonResponse({'success': False, 'message': 'Invalid request method'})

class VerifyRegistrationCode(TemplateView):
    def post(self, request, *args, **kwargs):
        registration_code = request.POST.get('registration_code')
        
        if registration_code:
            # Try attendance module first
            try:
                user = RegisteredUser.objects.get(registration_code=registration_code)
                return JsonResponse({
                    'valid': True,
                    'name': user.full_name,
                    'email': user.email,
                    'event': user.event_name
                })
            except RegisteredUser.DoesNotExist:
                pass
            
            # Try registration module
            try:
                registration = Registration.objects.get(registration_code=registration_code)
                return JsonResponse({
                    'valid': True,
                    'name': registration.full_name,
                    'email': registration.email,
                    'event': registration.event.name
                })
            except Registration.DoesNotExist:
                pass
        
        return JsonResponse({'valid': False})

class ThankYouView(TemplateView):
    template_name = 'feedback/thank_you.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        config = FeedbackConfiguration.get_active_config()
        if config:
            context['thank_you_message'] = config.thank_you_message
            context['active_event'] = config.active_event
        return context

class FeedbackDashboardView(TemplateView):
    template_name = 'feedback/dashboard.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        event_id = self.request.GET.get('event')
        show_legacy = self.request.GET.get('legacy', 'false').lower() == 'true'

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

        if event_id:
            try:
                event = Event.objects.get(id=event_id)
                feedbacks = feedbacks.filter(event=event)
                context['selected_event'] = event
            except Event.DoesNotExist:
                pass
        elif show_legacy:
            feedbacks = feedbacks.filter(event__isnull=True)
            context['showing_legacy'] = True
        else:
            # No filter applied — show all feedback across events (no default)
            # Do NOT set selected_event here
            pass  # feedbacks remain unfiltered by event

        # Statistics
        context['total_feedback'] = feedbacks.count()
        context['average_rating'] = feedbacks.aggregate(Avg('rating'))['rating__avg'] or 0

        # Rating distribution
        rating_distribution = feedbacks.values('rating').annotate(count=Count('rating')).order_by('rating')
        context['rating_distribution'] = {item['rating']: item['count'] for item in rating_distribution}

        # Category breakdown
        from .models import FeedbackCategory
        categories = []
        for category in FeedbackCategory.objects.filter(is_active=True):
            count = feedbacks.filter(category=category).count()
            categories.append({
                'name': category.name,
                'count': count,
                'id': category.id
            })
        context['category_breakdown'] = categories

        # Recent feedback
        context['recent_feedback'] = feedbacks.order_by('-created_at')[:10]

        # Event filter options
        context['available_events'] = Event.objects.filter(is_archived=False).order_by('-start_date')

        # Legacy check
        context['has_legacy_feedback'] = Feedback.objects.filter(event__isnull=True, is_published=True).exists()

        return context

class FeedbackListView(ListView):
    model = Feedback
    template_name = 'feedback/feedback_list.html'
    context_object_name = 'feedbacks'
    paginate_by = 20
    
    def get_queryset(self):
        queryset = Feedback.objects.filter(is_published=True).select_related('category', 'registered_user', 'event')
        
        # Filter by event
        event_id = self.request.GET.get('event')
        if event_id:
            try:
                event = Event.objects.get(id=event_id)
                queryset = queryset.filter(event=event)
            except Event.DoesNotExist:
                pass
        else:
            # Default to active event
            config = FeedbackConfiguration.get_active_config()
            if config:
                queryset = queryset.filter(event=config.active_event)
        
        # Filter by category
        category = self.request.GET.get('category')
        if category:
            queryset = queryset.filter(category__name=category)
        
        # Filter by rating
        rating = self.request.GET.get('rating')
        if rating:
            queryset = queryset.filter(rating=rating)
        
        # Filter by anonymous status
        is_anonymous = self.request.GET.get('is_anonymous')
        if is_anonymous:
            queryset = queryset.filter(is_anonymous=is_anonymous == 'true')
        
        # Filter by published status
        is_published = self.request.GET.get('is_published')
        if is_published:
            queryset = queryset.filter(is_published=is_published == 'true')
        
        # Search in comments
        search = self.request.GET.get('search')
        if search:
            queryset = queryset.filter(comment__icontains=search)
        
        return queryset.order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categories'] = FeedbackCategory.objects.filter(is_active=True)
        context['available_events'] = Event.objects.filter(feedbacks__isnull=False).distinct().order_by('-start_date')
        
        # Get current filters
        context['current_filters'] = {
            'event': self.request.GET.get('event', ''),
            'category': self.request.GET.get('category', ''),
            'rating': self.request.GET.get('rating', ''),
            'is_anonymous': self.request.GET.get('is_anonymous', ''),
            'is_published': self.request.GET.get('is_published', ''),
            'search': self.request.GET.get('search', ''),
        }
        
        return context

class EventArchiveView(TemplateView):
    """View to manage event archives and switch active feedback collection"""
    template_name = 'feedback/event_archive.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get all events with feedback counts
        events_with_feedback = Event.objects.annotate(
            feedback_count=Count('feedbacks')
        ).filter(feedback_count__gt=0).order_by('-start_date')
        
        context['events_with_feedback'] = events_with_feedback
        context['active_config'] = FeedbackConfiguration.get_active_config()
        context['available_events'] = Event.objects.filter(is_active=True).order_by('-start_date')
        
        return context

def switch_active_event(request):
    """AJAX view to switch the active event for feedback collection"""
    if request.method == 'POST' and request.user.is_staff:
        event_id = request.POST.get('event_id')
        mode = request.POST.get('mode', 'single')  # 'single' or 'multi'
        action = request.POST.get('action', 'set')  # 'set', 'add', 'remove'
        
        try:
            event = Event.objects.get(id=event_id)
            config = FeedbackConfiguration.get_active_config()
            
            if mode == 'multi':
                # Switch to multi-event mode
                config.event_selection_mode = FeedbackConfiguration.MULTI_EVENT
                
                if action == 'add':
                    config.active_events.add(event)
                    message = f'Added {event.name} to active events'
                elif action == 'remove':
                    config.active_events.remove(event)
                    message = f'Removed {event.name} from active events'
                else:  # set
                    config.active_events.clear()
                    config.active_events.add(event)
                    config.active_event = event
                    message = f'Set {event.name} as active event (multi-mode)'
                    
            else:  # single mode
                # Switch to single-event mode
                config.event_selection_mode = FeedbackConfiguration.SINGLE_EVENT
                config.active_event = event
                config.active_events.clear()
                message = f'Feedback collection switched to {event.name} (single mode)'
            
            config.feedback_enabled = True
            config.save()
            
            return JsonResponse({
                'success': True,
                'message': message,
                'event_name': event.name,
                'mode': config.event_selection_mode,
                'active_events_count': config.active_events.count()
            })
            
        except Event.DoesNotExist:
            return JsonResponse({
                'success': False,
                'message': 'Event not found'
            })
    
    return JsonResponse({
        'success': False,
        'message': 'Unauthorized or invalid request'
    })
