from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.views.generic import TemplateView
from django.contrib.admin.views.decorators import staff_member_required
from django.utils.decorators import method_decorator
from django.db.models import Count, Q
from django.utils import timezone
from .models import ICICTRegistrant, AttendanceDay, DailyAttendance, AttendanceConfiguration, WorkshopFeedback, FeedbackConfiguration
from django.db.models import Avg, Count
import json


class AttendanceCheckInView(TemplateView):
    """View for users to check in their attendance"""
    template_name = 'icict_attendance/check_in.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        config = AttendanceConfiguration.get_config()
        context['config'] = config
        context['current_day'] = config.current_day
        return context


@csrf_exempt
@require_http_methods(["POST"])
def confirm_attendance(request):
    """AJAX endpoint to confirm attendance"""
    try:
        data = json.loads(request.body)
        identifier = data.get('identifier', '').strip()
        
        if not identifier:
            return JsonResponse({
                'success': False,
                'message': 'Please enter your ID or email address'
            })
        
        config = AttendanceConfiguration.get_config()
        
        if not config.attendance_enabled:
            return JsonResponse({
                'success': False,
                'message': 'Attendance checking is currently disabled'
            })
        
        if not config.current_day:
            return JsonResponse({
                'success': False,
                'message': 'No attendance day is currently configured'
            })
        
        # Try to find registrant by ID or email
        registrant = None
        
        # First try by registration ID if it's numeric
        if identifier.isdigit():
            try:
                registrant = ICICTRegistrant.objects.get(registration_id=int(identifier))
            except ICICTRegistrant.DoesNotExist:
                pass
        
        # If not found by ID, try by email
        if not registrant:
            try:
                registrant = ICICTRegistrant.objects.get(email__iexact=identifier)
            except ICICTRegistrant.DoesNotExist:
                pass
        
        if not registrant:
            return JsonResponse({
                'success': False,
                'message': 'Registration not found. Please check your ID or email address.'
            })
        
        # Check if already attended today
        existing_attendance = DailyAttendance.objects.filter(
            registrant=registrant,
            attendance_day=config.current_day
        ).first()
        
        if existing_attendance:
            return JsonResponse({
                'success': True,
                'already_attended': True,
                'message': f'You have already confirmed attendance for {config.current_day.title}',
                'registrant': {
                    'name': registrant.name,
                    'email': registrant.email,
                    'registration_id': registrant.registration_id,
                    'payment_status': registrant.get_payment_status_display(),
                    'attended_at': existing_attendance.checked_in_at.strftime('%Y-%m-%d %H:%M:%S')
                }
            })
        
        # Record attendance
        attendance = DailyAttendance.objects.create(
            registrant=registrant,
            attendance_day=config.current_day,
            ip_address=request.META.get('REMOTE_ADDR'),
            user_agent=request.META.get('HTTP_USER_AGENT', '')
        )
        
        return JsonResponse({
            'success': True,
            'already_attended': False,
            'message': f'Attendance confirmed for {config.current_day.title}!',
            'registrant': {
                'name': registrant.name,
                'email': registrant.email,
                'registration_id': registrant.registration_id,
                'payment_status': registrant.get_payment_status_display(),
                'attended_at': attendance.checked_in_at.strftime('%Y-%m-%d %H:%M:%S')
            }
        })
        
    except json.JSONDecodeError:
        return JsonResponse({
            'success': False,
            'message': 'Invalid request format'
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': 'An error occurred. Please try again.'
        })


@method_decorator(staff_member_required, name='dispatch')
class AttendanceAdminView(TemplateView):
    """Admin view for managing attendance configuration and viewing statistics"""
    template_name = 'icict_attendance/admin_dashboard.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        config = AttendanceConfiguration.get_config()
        
        # Get all attendance days
        attendance_days = AttendanceDay.objects.all()
        
        # Get statistics
        total_registrants = ICICTRegistrant.objects.count()
        awaiting_payment = ICICTRegistrant.objects.filter(payment_status='awaiting_payment').count()
        completed_payment = ICICTRegistrant.objects.filter(payment_status='completed').count()
        
        # Daily attendance statistics
        daily_stats = []
        for day in attendance_days:
            attendance_count = DailyAttendance.objects.filter(attendance_day=day).count()
            daily_stats.append({
                'day': day,
                'attendance_count': attendance_count,
                'percentage': round((attendance_count / total_registrants * 100) if total_registrants > 0 else 0, 1)
            })
        
        # Recent attendance (last 20)
        recent_attendance = DailyAttendance.objects.select_related('registrant', 'attendance_day').order_by('-checked_in_at')[:20]
        
        context.update({
            'config': config,
            'attendance_days': attendance_days,
            'total_registrants': total_registrants,
            'awaiting_payment': awaiting_payment,
            'completed_payment': completed_payment,
            'daily_stats': daily_stats,
            'recent_attendance': recent_attendance,
        })
        
        return context


@staff_member_required
@csrf_exempt
@require_http_methods(["POST"])
def update_attendance_config(request):
    """AJAX endpoint to update attendance configuration"""
    try:
        data = json.loads(request.body)
        config = AttendanceConfiguration.get_config()
        
        if 'current_day_id' in data:
            if data['current_day_id']:
                current_day = get_object_or_404(AttendanceDay, id=data['current_day_id'])
                config.current_day = current_day
            else:
                config.current_day = None
        
        if 'attendance_enabled' in data:
            config.attendance_enabled = data['attendance_enabled']
        
        if 'welcome_message' in data:
            config.welcome_message = data['welcome_message']
        
        config.save()
        
        return JsonResponse({
            'success': True,
            'message': 'Configuration updated successfully'
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': str(e)
        })


class FeedbackFormView(TemplateView):
    """View for participants to submit feedback"""
    template_name = 'icict_attendance/feedback_form.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        feedback_config = FeedbackConfiguration.get_config()
        context['feedback_config'] = feedback_config
        context['current_day'] = feedback_config.current_feedback_day
        context['attendance_days'] = AttendanceDay.objects.all().order_by('day_number')
        return context


@csrf_exempt
@require_http_methods(["POST"])
def submit_feedback(request):
    """AJAX endpoint to submit feedback"""
    try:
        data = json.loads(request.body)
        
        feedback_config = FeedbackConfiguration.get_config()
        
        if not feedback_config.feedback_enabled:
            return JsonResponse({
                'success': False,
                'message': 'Feedback collection is currently disabled'
            })
        
        # Extract form data
        participant_email = data.get('participant_email', '').strip()
        is_anonymous = data.get('is_anonymous', False)
        
        # Ratings
        overall_rating = int(data.get('overall_rating', 0))
        content_quality = int(data.get('content_quality', 0))
        presenter_effectiveness = int(data.get('presenter_effectiveness', 0))
        venue_facilities = int(data.get('venue_facilities', 0))
        
        # Text feedback
        what_liked_most = data.get('what_liked_most', '').strip()
        suggestions_improvement = data.get('suggestions_improvement', '').strip()
        
        # Validation
        if not is_anonymous and not participant_email:
            return JsonResponse({
                'success': False,
                'message': 'Email address is required for non-anonymous feedback'
            })
        
        if not all([overall_rating, content_quality, presenter_effectiveness, venue_facilities]):
            return JsonResponse({
                'success': False,
                'message': 'Please provide ratings for all categories'
            })
        
        # Try to find registrant if not anonymous
        registrant = None
        participant_name = "Anonymous Participant"
        
        if not is_anonymous and participant_email:
            try:
                registrant = ICICTRegistrant.objects.get(email__iexact=participant_email)
                participant_name = registrant.name
            except ICICTRegistrant.DoesNotExist:
                participant_name = participant_email.split('@')[0].title()
        
        # Handle anonymous feedback
        if is_anonymous:
            if participant_email:
                # Try to find registrant even for anonymous feedback to link data
                try:
                    registrant = ICICTRegistrant.objects.get(email__iexact=participant_email)
                except ICICTRegistrant.DoesNotExist:
                    pass
            else:
                participant_email = f"anonymous_{timezone.now().timestamp()}@feedback.local"
        
        # Use overall session type since we're not selecting specific days
        session_type = 'general'
        
        # Create feedback record (without attendance_day since it's overall feedback)
        feedback = WorkshopFeedback.objects.create(
            registrant=registrant,
            participant_name=participant_name,
            participant_email=participant_email,
            attendance_day=None,  # Overall feedback, not day-specific
            session_type=session_type,
            overall_rating=overall_rating,
            content_quality=content_quality,
            presenter_effectiveness=presenter_effectiveness,
            venue_facilities=venue_facilities,
            what_liked_most=what_liked_most or None,
            suggestions_improvement=suggestions_improvement or None,
            additional_topics=None,
            general_comments=None,
            ip_address=request.META.get('REMOTE_ADDR'),
            is_anonymous=is_anonymous
        )
        
        return JsonResponse({
            'success': True,
            'message': 'Thank you for your feedback! Your response has been recorded.',
            'feedback_id': feedback.id,
            'average_rating': round(feedback.average_rating, 1)
        })
        
    except json.JSONDecodeError:
        return JsonResponse({
            'success': False,
            'message': 'Invalid request format'
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': 'An error occurred while submitting feedback. Please try again.'
        })


@method_decorator(staff_member_required, name='dispatch')
class FeedbackDashboardView(TemplateView):
    """Admin view for viewing feedback statistics and responses"""
    template_name = 'icict_attendance/feedback_dashboard.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get filter parameters
        day_filter = self.request.GET.get('day')
        session_filter = self.request.GET.get('session')
        
        # Base queryset
        feedbacks = WorkshopFeedback.objects.all()
        
        # Apply filters
        if day_filter:
            feedbacks = feedbacks.filter(attendance_day_id=day_filter)
        if session_filter:
            feedbacks = feedbacks.filter(session_type=session_filter)
        
        # Statistics
        total_feedback = feedbacks.count()
        if total_feedback > 0:
            avg_ratings = feedbacks.aggregate(
                overall=Avg('overall_rating'),
                content=Avg('content_quality'),
                presenter=Avg('presenter_effectiveness'),
                venue=Avg('venue_facilities')
            )
        else:
            avg_ratings = {'overall': 0, 'content': 0, 'presenter': 0, 'venue': 0}
        
        # Daily feedback counts
        daily_stats = []
        for day in AttendanceDay.objects.all().order_by('day_number'):
            day_feedbacks = WorkshopFeedback.objects.filter(attendance_day=day)
            daily_stats.append({
                'day': day,
                'feedback_count': day_feedbacks.count(),
                'avg_rating': day_feedbacks.aggregate(avg=Avg('overall_rating'))['avg'] or 0
            })
        
        # Recent feedback
        recent_feedback = feedbacks.order_by('-submitted_at')[:20]
        
        # Rating distribution
        rating_distribution = feedbacks.values('overall_rating').annotate(
            count=Count('overall_rating')
        ).order_by('overall_rating')
        
        context.update({
            'total_feedback': total_feedback,
            'avg_ratings': avg_ratings,
            'daily_stats': daily_stats,
            'recent_feedback': recent_feedback,
            'rating_distribution': rating_distribution,
            'attendance_days': AttendanceDay.objects.all().order_by('day_number'),
            'session_types': WorkshopFeedback.SESSION_TYPE_CHOICES,
            'selected_day': day_filter,
            'selected_session': session_filter,
            'feedback_config': FeedbackConfiguration.get_config(),
        })
        
        return context


@staff_member_required
@csrf_exempt
@require_http_methods(["POST"])
def update_feedback_config(request):
    """AJAX endpoint to update feedback configuration"""
    try:
        data = json.loads(request.body)
        config = FeedbackConfiguration.get_config()
        
        if 'current_feedback_day_id' in data:
            if data['current_feedback_day_id']:
                current_day = get_object_or_404(AttendanceDay, id=data['current_feedback_day_id'])
                config.current_feedback_day = current_day
            else:
                config.current_feedback_day = None
        
        if 'feedback_enabled' in data:
            config.feedback_enabled = data['feedback_enabled']
        
        if 'feedback_message' in data:
            config.feedback_message = data['feedback_message']
        
        if 'allow_anonymous_feedback' in data:
            config.allow_anonymous_feedback = data['allow_anonymous_feedback']
        
        if 'require_attendance' in data:
            config.require_attendance = data['require_attendance']
        
        config.save()
        
        return JsonResponse({
            'success': True,
            'message': 'Feedback configuration updated successfully'
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': str(e)
        })


class PublicFeedbackResultsView(TemplateView):
    """Public view for displaying feedback results to all users"""
    template_name = 'icict_attendance/public_feedback_results.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get all feedback
        feedbacks = WorkshopFeedback.objects.all()
        total_feedback = feedbacks.count()
        
        if total_feedback > 0:
            # Calculate average ratings
            avg_ratings = feedbacks.aggregate(
                overall=Avg('overall_rating'),
                content=Avg('content_quality'),
                presenter=Avg('presenter_effectiveness'),
                venue=Avg('venue_facilities')
            )
            
            # Rating distribution
            rating_distribution = []
            for i in range(1, 6):
                count = feedbacks.filter(overall_rating=i).count()
                percentage = (count / total_feedback * 100) if total_feedback > 0 else 0
                rating_distribution.append({
                    'rating': i,
                    'count': count,
                    'percentage': round(percentage, 1)
                })
            
            # Category breakdown
            categories = [
                {'name': 'Overall Experience', 'avg': avg_ratings['overall'], 'icon': 'fas fa-star'},
                {'name': 'Content Quality', 'avg': avg_ratings['content'], 'icon': 'fas fa-book'},
                {'name': 'Presenter Effectiveness', 'avg': avg_ratings['presenter'], 'icon': 'fas fa-user-tie'},
                {'name': 'Venue & Facilities', 'avg': avg_ratings['venue'], 'icon': 'fas fa-building'},
            ]
            
        else:
            avg_ratings = {'overall': 0, 'content': 0, 'presenter': 0, 'venue': 0}
            rating_distribution = []
            categories = []
        
        context.update({
            'total_feedback': total_feedback,
            'avg_ratings': avg_ratings,
            'rating_distribution': rating_distribution,
            'categories': categories,
        })
        
        return context
