# academics/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, TemplateView, CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.http import JsonResponse
from django.urls import reverse_lazy
from django.db.models import Count, Q
from datetime import date, timedelta


from .models import SchoolClass, Subject, Attendance, ClassSubject
from students.models import Student
from staff.models import Staff

# ========== CLASS VIEWS ==========

class ClassListView(LoginRequiredMixin, ListView):
    """List all classes"""
    model = SchoolClass
    template_name = 'academics/class_list.html'
    context_object_name = 'classes'
    
    def get_queryset(self):
        return SchoolClass.objects.all().order_by('level', 'section')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        total_students = 0
        english_count = 0
        
        for cls in context['classes']:
            # Count students in each class
            cls.student_count = Student.objects.filter(current_class=cls).count()
            total_students += cls.student_count
            
            # Count teachers (through ClassSubject)
            cls.teacher_count = ClassSubject.objects.filter(
                school_class=cls, teacher__isnull=False
            ).values('teacher').distinct().count()
            
            # Count English section classes
            if cls.section_type == 'english':
                english_count += 1
        
        context['total_students'] = total_students
        context['english_count'] = english_count
        
        return context


class ClassDetailView(LoginRequiredMixin, DetailView):
    """View class details with teachers and students"""
    model = SchoolClass
    template_name = 'academics/class_detail.html'
    context_object_name = 'class'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get students in this class
        students = Student.objects.filter(
            current_class=self.object
        ).order_by('first_name')
        context['students'] = students
        
        # Get all teachers for dropdown
        context['all_teachers'] = Staff.objects.filter(
            is_active=True,
            role__in=['teacher', 'class_teacher', 'subject_teacher']
        ).select_related('user').order_by('user__first_name')
        
        # Get all subjects
        context['all_subjects'] = Subject.objects.all().order_by('name')
        
        # Get teachers for this class (through subject assignments)
        teacher_assignments = ClassSubject.objects.filter(
            school_class=self.object
        ).select_related('subject', 'teacher__user')
        
        # Group by teacher
        teachers_dict = {}
        for assignment in teacher_assignments:
            if assignment.teacher:
                teacher_id = assignment.teacher.id
                if teacher_id not in teachers_dict:
                    teachers_dict[teacher_id] = {
                        'teacher': assignment.teacher,
                        'subjects': [],
                        'assignments': []
                    }
                teachers_dict[teacher_id]['subjects'].append(assignment.subject)
                teachers_dict[teacher_id]['assignments'].append(assignment)
        
        context['teachers'] = list(teachers_dict.values())
        
        # Class teacher (homeroom teacher)
        if self.object.class_teacher:
            context['class_teacher'] = self.object.class_teacher
        
        # Today's attendance
        today = date.today()
        today_attendance = Attendance.objects.filter(
            school_class=self.object,
            date=today
        )
        context['today_attendance'] = today_attendance.count()
        
        if students.count() > 0:
            present_count = today_attendance.filter(status='present').count()
            context['attendance_rate'] = round((present_count / students.count()) * 100, 1)
        else:
            context['attendance_rate'] = 0
        
        # Statistics
        context['total_students'] = students.count()
        context['total_subjects'] = teacher_assignments.count()
        context['total_teachers'] = len(teachers_dict)
        
        return context


class ClassStudentsView(LoginRequiredMixin, DetailView):
    """View students in a class"""
    model = SchoolClass
    template_name = 'academics/class_students.html'
    context_object_name = 'class'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['students'] = Student.objects.filter(
            current_class=self.object
        ).order_by('first_name')
        return context


# ========== SUBJECT VIEWS ==========

class SubjectListView(LoginRequiredMixin, ListView):
    """List all subjects"""
    model = Subject
    template_name = 'academics/subject_list.html'
    context_object_name = 'subjects'
    
    def get_queryset(self):
        return Subject.objects.all().order_by('category', 'name')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categories'] = Subject.SUBJECT_CATEGORY_CHOICES
        return context


class SubjectDetailView(LoginRequiredMixin, DetailView):
    """View subject details"""
    model = Subject
    template_name = 'academics/subject_detail.html'
    context_object_name = 'subject'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get classes where this subject is taught
        context['class_assignments'] = ClassSubject.objects.filter(
            subject=self.object
        ).select_related('school_class', 'teacher')
        
        return context


class SubjectCreateView(LoginRequiredMixin, CreateView):
    """Create a new subject"""
    model = Subject
    fields = ['code', 'name', 'name_fr', 'category', 'description']
    template_name = 'academics/subject_form.html'
    success_url = reverse_lazy('academics:subject_list')

    def form_valid(self, form):
        messages.success(self.request, f'Subject "{form.instance.name}" created successfully!')
        return super().form_valid(form)


# ========== TEACHER ASSIGNMENT VIEWS ==========

from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required

@login_required
@require_POST
def assign_teacher(request, class_id):
    """Assign a teacher to teach a subject in a class"""
    try:
        school_class = get_object_or_404(SchoolClass, id=class_id)
        teacher_id = request.POST.get('teacher_id')
        subject_id = request.POST.get('subject_id')
        hours = request.POST.get('hours_per_week', 2)
        
        if not teacher_id or not subject_id:
            messages.error(request, 'Please select both teacher and subject')
            return redirect('academics:class_detail', pk=class_id)
        
        teacher = get_object_or_404(Staff, id=teacher_id)
        subject = get_object_or_404(Subject, id=subject_id)
        
        # Check if assignment already exists
        assignment, created = ClassSubject.objects.get_or_create(
            school_class=school_class,
            subject=subject,
            defaults={
                'teacher': teacher,
                'hours_per_week': hours
            }
        )
        
        if not created:
            # Update existing assignment
            assignment.teacher = teacher
            assignment.hours_per_week = hours
            assignment.save()
            message = f"✅ Updated: {teacher.user.get_full_name()} now teaches {subject.name}"
        else:
            message = f"✅ Assigned: {teacher.user.get_full_name()} to teach {subject.name}"
        
        messages.success(request, message)
        
    except Staff.DoesNotExist:
        messages.error(request, f"Teacher with ID {teacher_id} not found")
    except Subject.DoesNotExist:
        messages.error(request, f"Subject with ID {subject_id} not found")
    except Exception as e:
        messages.error(request, f"Error: {str(e)}")
    
    return redirect('academics:class_detail', pk=class_id)


@login_required
def get_teachers_for_class(request, class_id):
    """API endpoint to get current teacher assignments for a class"""
    try:
        school_class = get_object_or_404(SchoolClass, id=class_id)
        assignments = ClassSubject.objects.filter(
            school_class=school_class
        ).select_related('teacher__user', 'subject')
        
        data = []
        for assignment in assignments:
            if assignment.teacher:
                data.append({
                    'id': assignment.id,
                    'teacher_id': assignment.teacher.id,
                    'teacher_name': assignment.teacher.user.get_full_name(),
                    'subject': assignment.subject.name,
                    'subject_id': assignment.subject.id,
                    'hours': assignment.hours_per_week
                })
        
        return JsonResponse({
            'success': True, 
            'data': data,
            'count': len(data)
        })
        
    except SchoolClass.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Class not found'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
@require_POST
def remove_teacher_assignment(request, assignment_id):
    """Remove a teacher-subject-class assignment"""
    try:
        assignment = get_object_or_404(ClassSubject, id=assignment_id)
        class_id = assignment.school_class.id
        subject_name = assignment.subject.name
        teacher_name = assignment.teacher.user.get_full_name() if assignment.teacher else "Unknown"
        
        assignment.delete()
        messages.success(request, f"✅ Removed {teacher_name} from teaching {subject_name}")
        
    except Exception as e:
        messages.error(request, f"Error removing assignment: {str(e)}")
        class_id = request.POST.get('class_id')
    
    return redirect('academics:class_detail', pk=class_id)


@login_required
def bulk_assign_teachers(request, class_id):
    """Bulk assign multiple teachers to a class"""
    if request.method == 'POST':
        # This can be expanded later for CSV upload or multi-select
        messages.info(request, "Bulk assignment feature coming soon!")
        return redirect('academics:class_detail', pk=class_id)
    
    return JsonResponse({'success': False, 'error': 'Method not allowed'})


# ========== ATTENDANCE VIEWS ==========

class AttendanceListView(LoginRequiredMixin, ListView):
    """List attendance records"""
    model = Attendance
    template_name = 'academics/attendance/list.html'
    context_object_name = 'attendances'
    paginate_by = 50
    
    def get_queryset(self):
        queryset = Attendance.objects.all().select_related(
            'student', 'school_class', 'marked_by__user'
        )
        
        # Filter by date
        date_filter = self.request.GET.get('date')
        if date_filter:
            queryset = queryset.filter(date=date_filter)
        else:
            queryset = queryset.filter(date=date.today())
        
        # Filter by class
        class_filter = self.request.GET.get('class')
        if class_filter:
            queryset = queryset.filter(school_class_id=class_filter)
        
        # Filter by status
        status_filter = self.request.GET.get('status')
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        
        return queryset.order_by('-date', 'school_class', 'student__first_name')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['classes'] = SchoolClass.objects.all()
        context['today'] = date.today()
        return context


class AttendanceMarkingView(LoginRequiredMixin, TemplateView):
    """Mark attendance for a class - Teacher Friendly"""
    template_name = 'academics/attendance/mark.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # If teacher is logged in, show only their classes
        if hasattr(self.request.user, 'staff_profile') and self.request.user.staff_profile.is_teacher:
            teacher = self.request.user.staff_profile
            # Get classes this teacher teaches
            teacher_classes = ClassSubject.objects.filter(
                teacher=teacher
            ).values_list('school_class', flat=True).distinct()
            context['classes'] = SchoolClass.objects.filter(id__in=teacher_classes)
        else:
            context['classes'] = SchoolClass.objects.all()
        
        context['today'] = date.today()
        
        class_id = self.request.GET.get('class')
        if class_id:
            selected_class = get_object_or_404(SchoolClass, id=class_id)
            context['selected_class'] = selected_class
            
            # Get students in this class
            students = Student.objects.filter(
                current_class=selected_class,
                status='active'
            ).order_by('first_name')
            context['students'] = students
            
            # Get today's attendance
            attendance_today = Attendance.objects.filter(
                date=date.today(),
                school_class=selected_class
            )
            
            # Create a dictionary for quick lookup
            attendance_dict = {}
            for att in attendance_today:
                attendance_dict[att.student_id] = att.status
            
            context['attendance_dict'] = attendance_dict
            
            # Check if attendance already taken
            context['attendance_taken'] = attendance_today.exists()
        
        return context
    
    def post(self, request, *args, **kwargs):
        class_id = request.POST.get('class_id')
        if not class_id:
            messages.error(request, 'Please select a class')
            return redirect('attendance:mark_attendance')
        
        selected_class = get_object_or_404(SchoolClass, id=class_id)
        students = Student.objects.filter(current_class=selected_class, status='active')
        
        marked_count = 0
        for student in students:
            status = request.POST.get(f'status_{student.id}')
            
            if status:
                attendance, created = Attendance.objects.update_or_create(
                    student=student,
                    date=date.today(),
                    defaults={
                        'school_class': selected_class,
                        'status': status,
                        'marked_by': request.user.staff_profile if hasattr(request.user, 'staff_profile') else None
                    }
                )
                marked_count += 1
        
        messages.success(request, f'✅ Attendance marked for {marked_count} students in {selected_class.name}')
        
        # If teacher, redirect back to their dashboard
        if hasattr(request.user, 'staff_profile') and request.user.staff_profile.is_teacher:
            return redirect('staff:teacher_dashboard')
        
        return redirect(f'/attendance/mark/?class={class_id}')


class AttendanceReportView(LoginRequiredMixin, TemplateView):
    """View attendance reports"""
    template_name = 'academics/attendance/report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get filter parameters
        from_date = self.request.GET.get('from_date')
        to_date = self.request.GET.get('to_date')
        class_id = self.request.GET.get('class')
        
        # Default to current month
        if not from_date:
            from_date = date.today().replace(day=1)
        if not to_date:
            to_date = date.today()
        
        context['classes'] = SchoolClass.objects.all()
        context['from_date'] = from_date
        context['to_date'] = to_date
        
        # Build stats
        stats = []
        classes = SchoolClass.objects.all()
        if class_id:
            classes = classes.filter(id=class_id)
        
        for cls in classes:
            # Get attendance records for this class in date range
            attendances = Attendance.objects.filter(
                school_class=cls,
                date__gte=from_date,
                date__lte=to_date
            )
            
            total = attendances.count()
            if total > 0:
                present = attendances.filter(status='present').count()
                absent = attendances.filter(status='absent').count()
                late = attendances.filter(status='late').count()
                excused = attendances.filter(status='excused').count()
                
                stats.append({
                    'class': cls.name,
                    'total': total,
                    'present': present,
                    'absent': absent,
                    'late': late,
                    'excused': excused,
                    'rate': round((present / total) * 100, 1) if total > 0 else 0
                })
        
        context['stats'] = stats
        
        # Summary stats
        if stats:
            context['total_records'] = sum(s['total'] for s in stats)
            context['total_present'] = sum(s['present'] for s in stats)
            context['overall_rate'] = round(
                (context['total_present'] / context['total_records']) * 100,
                1
            ) if context['total_records'] > 0 else 0
        
        return context


class StudentAttendanceView(LoginRequiredMixin, DetailView):
    """View attendance for a specific student"""
    model = Student
    template_name = 'academics/attendance/student.html'
    context_object_name = 'student'
    
    def get_object(self):
        return get_object_or_404(Student, id=self.kwargs['student_id'])
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get attendance for this student
        attendances = Attendance.objects.filter(
            student=self.object
        ).order_by('-date')[:60]  # Last 60 days
        
        context['attendances'] = attendances
        
        # Calculate stats
        total = attendances.count()
        if total > 0:
            present = attendances.filter(status='present').count()
            context['attendance_rate'] = round((present / total) * 100, 1)
            context['total_days'] = total
            context['present_days'] = present
            context['absent_days'] = attendances.filter(status='absent').count()
            context['late_days'] = attendances.filter(status='late').count()
        
        return context


# ========== API ENDPOINTS ==========

def get_today_attendance(request):
    """API endpoint for today's attendance"""
    today = date.today()
    total = Attendance.objects.filter(date=today).count()
    present = Attendance.objects.filter(date=today, status='present').count()
    
    return JsonResponse({
        'date': today,
        'total': total,
        'present': present,
        'absent': total - present,
        'rate': round((present / total) * 100, 1) if total > 0 else 0
    })


def get_class_stats(request, class_id):
    """API endpoint for class statistics"""
    school_class = get_object_or_404(SchoolClass, id=class_id)
    
    stats = {
        'class': school_class.name,
        'total_students': Student.objects.filter(current_class=school_class).count(),
        'subjects': ClassSubject.objects.filter(school_class=school_class).count(),
        'today_attendance': Attendance.objects.filter(
            school_class=school_class,
            date=date.today()
        ).count(),
    }
    
    return JsonResponse(stats)