# attendance/serializers.py

from rest_framework import serializers
from .models import (
    AttendanceSession, StudentAttendance, AttendanceLeave, AttendanceSummary
)
from academics.models import AcademicClass, StudentEnrollment, Subject
from people.models import Teacher, Student


class AttendanceSessionSerializer(serializers.ModelSerializer):
    """Serializer for attendance sessions"""
    
    class_name = serializers.SerializerMethodField()
    teacher_name = serializers.SerializerMethodField()
    session_type_display = serializers.SerializerMethodField()
    status_display = serializers.SerializerMethodField()
    
    class Meta:
        model = AttendanceSession
        fields = [
            'id', 'academic_class', 'class_name', 'subject', 'taken_by', 'teacher_name',
            'date', 'period_number', 'session_type', 'session_type_display', 'status',
            'status_display', 'start_time', 'end_time', 'total_students', 'present_count',
            'absent_count', 'late_count', 'leave_count', 'remarks', 'created_at'
        ]
        read_only_fields = ['created_at', 'updated_at']
    
    def get_class_name(self, obj):
        return str(obj.academic_class) if obj.academic_class else None
    
    def get_teacher_name(self, obj):
        return obj.taken_by.full_name if obj.taken_by else None
    
    def get_session_type_display(self, obj):
        return dict(AttendanceSession.SESSION_TYPE_CHOICES).get(obj.session_type, obj.session_type)
    
    def get_status_display(self, obj):
        return dict(AttendanceSession.STATUS_CHOICES).get(obj.status, obj.status)


class StudentAttendanceSerializer(serializers.ModelSerializer):
    """Serializer for student attendance records"""
    
    student_name = serializers.SerializerMethodField()
    roll_number = serializers.SerializerMethodField()
    student_profile_image = serializers.SerializerMethodField()
    status_display = serializers.SerializerMethodField()
    
    class Meta:
        model = StudentAttendance
        fields = [
            'id', 'session', 'enrollment', 'student', 'student_name', 'roll_number',
            'student_profile_image', 'status', 'status_display', 'remarks', 'late_minutes',
            'leave', 'marked_by', 'marked_at', 'updated_at'
        ]
        read_only_fields = ['marked_at', 'updated_at']
    
    def get_student_name(self, obj):
        return obj.student.full_name if obj.student else None
    
    def get_roll_number(self, obj):
        return obj.enrollment.roll_number if obj.enrollment else None
    
    def get_student_profile_image(self, obj):
        return obj.student.profile_image.url if obj.student and obj.student.profile_image else None
    
    def get_status_display(self, obj):
        return dict(StudentAttendance.STATUS_CHOICES).get(obj.status, obj.status)


class StudentAttendanceListSerializer(serializers.ModelSerializer):
    """Serializer for student attendance list in a session"""
    
    student_id = serializers.IntegerField(source='student.id', read_only=True)
    student_name = serializers.SerializerMethodField()
    roll_number = serializers.SerializerMethodField()
    profile_image = serializers.SerializerMethodField()
    status_display = serializers.SerializerMethodField()
    
    class Meta:
        model = StudentAttendance
        fields = [
            'id', 'student_id', 'student_name', 'roll_number', 'profile_image',
            'status', 'status_display', 'remarks', 'late_minutes', 'marked_at'
        ]
    
    def get_student_name(self, obj):
        return obj.student.full_name if obj.student else None
    
    def get_roll_number(self, obj):
        return obj.enrollment.roll_number if obj.enrollment else None
    
    def get_profile_image(self, obj):
        return obj.student.profile_image.url if obj.student and obj.student.profile_image else None
    
    def get_status_display(self, obj):
        return dict(StudentAttendance.STATUS_CHOICES).get(obj.status, obj.status)


class BulkAttendanceSerializer(serializers.Serializer):
    """Serializer for bulk attendance marking"""
    
    attendance_data = serializers.ListField(
        child=serializers.DictField(),
        min_length=1
    )
    
    def validate_attendance_data(self, value):
        valid_statuses = ['PRESENT', 'ABSENT', 'LATE', 'LEAVE', 'HALF_DAY']
        for item in value:
            if 'enrollment_id' not in item:
                raise serializers.ValidationError("Each entry must have enrollment_id")
            if 'status' not in item:
                raise serializers.ValidationError("Each entry must have status")
            if item['status'] not in valid_statuses:
                raise serializers.ValidationError(f"Invalid status. Choose from {valid_statuses}")
        return value


class AttendanceLeaveSerializer(serializers.ModelSerializer):
    """Serializer for leave requests"""
    
    student_name = serializers.SerializerMethodField()
    class_name = serializers.SerializerMethodField()
    leave_type_display = serializers.SerializerMethodField()
    status_display = serializers.SerializerMethodField()
    approved_by_name = serializers.SerializerMethodField()
    total_days = serializers.IntegerField(read_only=True)
    
    class Meta:
        model = AttendanceLeave
        fields = [
            'id', 'enrollment', 'student', 'student_name', 'class_name', 'leave_type',
            'leave_type_display', 'from_date', 'to_date', 'total_days', 'reason',
            'document', 'status', 'status_display', 'approved_by', 'approved_by_name',
            'approved_at', 'rejection_reason', 'created_at'
        ]
        read_only_fields = ['created_at', 'updated_at']
    
    def get_student_name(self, obj):
        return obj.student.full_name if obj.student else None
    
    def get_class_name(self, obj):
        return str(obj.enrollment.academic_class) if obj.enrollment and obj.enrollment.academic_class else None
    
    def get_leave_type_display(self, obj):
        return dict(AttendanceLeave.LEAVE_TYPE_CHOICES).get(obj.leave_type, obj.leave_type)
    
    def get_status_display(self, obj):
        return dict(AttendanceLeave.STATUS_CHOICES).get(obj.status, obj.status)
    
    def get_approved_by_name(self, obj):
        return obj.approved_by.full_name if obj.approved_by else None


class AttendanceLeaveCreateUpdateSerializer(serializers.ModelSerializer):
    """Serializer for creating/updating leave requests"""
    
    class Meta:
        model = AttendanceLeave
        fields = ['enrollment', 'leave_type', 'from_date', 'to_date', 'reason', 'document']
    
    def validate(self, data):
        if data['from_date'] > data['to_date']:
            raise serializers.ValidationError("From date must be before or equal to to date")
        
        # Check for overlapping pending leaves
        if not self.instance:
            overlapping = AttendanceLeave.objects.filter(
                enrollment=data['enrollment'],
                status='PENDING',
                from_date__lte=data['to_date'],
                to_date__gte=data['from_date']
            ).exists()
        else:
            overlapping = AttendanceLeave.objects.filter(
                enrollment=data['enrollment'],
                status='PENDING',
                from_date__lte=data['to_date'],
                to_date__gte=data['from_date']
            ).exclude(id=self.instance.id).exists()
        
        if overlapping:
            raise serializers.ValidationError("You already have a pending leave request for these dates")
        
        return data


class AttendanceSummarySerializer(serializers.ModelSerializer):
    """Serializer for attendance summary"""
    
    student_name = serializers.SerializerMethodField()
    roll_number = serializers.SerializerMethodField()
    month_name = serializers.SerializerMethodField()
    
    class Meta:
        model = AttendanceSummary
        fields = [
            'id', 'student_name', 'roll_number', 'month', 'month_name', 'year',
            'total_working_days', 'present_days', 'absent_days', 'late_days',
            'leave_days', 'half_days', 'attendance_percentage', 'is_below_minimum'
        ]
    
    def get_student_name(self, obj):
        return obj.student.full_name if obj.student else None
    
    def get_roll_number(self, obj):
        return obj.enrollment.roll_number if obj.enrollment else None
    
    def get_month_name(self, obj):
        months = ['January', 'February', 'March', 'April', 'May', 'June',
                  'July', 'August', 'September', 'October', 'November', 'December']
        return months[obj.month - 1] if 1 <= obj.month <= 12 else str(obj.month)