from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
from .models import School, SchoolType, SchoolBoard, UserProfile, EmailTemplate, BulkEmailLog, SchoolModule, SchoolModuleAccess, Language
from django.contrib.auth.models import User


class MasterAdminTokenSerializer(TokenObtainPairSerializer):

    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)

        # -----------------------
        # BASIC IDENTITY (SAFE)
        # -----------------------
        token["user_id"] = user.id
        token["email"] = user.email

        # Platform admin (YOU)
        token["is_platform_admin"] = bool(user.is_superuser and user.is_staff)
        token["is_school_admin"] = bool(user.is_staff and not user.is_superuser)
        # -----------------------
        # SCHOOL CONTEXT (SAFE)
        # -----------------------
        profile = getattr(user, "profile", None)

        if profile:
            school = profile.school

            token["school_id"] = school.id if school else None
            token["school_slug"] = school.slug if school else None
        else:
            token["school_id"] = None
            token["school_slug"] = None

        return token


class SchoolTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = SchoolType
        fields = "__all__"


class SchoolBoardSerializer(serializers.ModelSerializer):
    class Meta:
        model = SchoolBoard
        fields = "__all__"


class SchoolSerializer(serializers.ModelSerializer):
    school_type = SchoolTypeSerializer(read_only=True)
    school_type_id = serializers.PrimaryKeyRelatedField(
        queryset=SchoolType.objects.all(),
        source="school_type",
        write_only=True,
        required=False,
    )

    school_board = SchoolBoardSerializer(read_only=True)
    school_board_id = serializers.PrimaryKeyRelatedField(
        queryset=SchoolBoard.objects.all(),
        source="school_board",
        write_only=True,
        required=False,
    )

    country_name = serializers.CharField(source="country.name", read_only=True)
    state_name = serializers.CharField(source="state.name", read_only=True)
    city_name = serializers.CharField(source="city.name", read_only=True)
    area_name = serializers.CharField(source="area.name", read_only=True)

    verified_by_username = serializers.CharField(
        source="verified_by.username", read_only=True
    )
    enabled_module_codes = serializers.SerializerMethodField()

    def get_enabled_module_codes(self, obj):
        default_codes = list(
            SchoolModule.objects.filter(is_default=True, is_active=True)
            .values_list('code', flat=True)
        )
        assigned_codes = list(
            obj.module_access.filter(is_enabled=True)
            .values_list('module__code', flat=True)
        )
        return list(set(default_codes + assigned_codes))

    class Meta:
        model = School
        fields = [
            "id",
            "uuid",
            "name",
            "slug",  # This is in fields
            "domain_name",
            "school_type",
            "school_type_id",
            "school_board",
            "school_board_id",
            "country",
            "country_name",
            "state",
            "state_name",
            "city",
            "city_name",
            "area",
            "area_name",
            "pincode",
            "address_line1",
            "address_line2",
            "landmark",
            "latitude",
            "longitude",
            "email",
            "phone",
            "alternate_phone",
            "fax",
            "website",
            "established_year",
            "registration_number",
            "affiliation_number",
            "motto",
            "vision",
            "mission",
            "logo",
            "banner_image",
            "prospectus",
            "is_active",
            "is_trial",
            "trial_ends_at",
            "verified_at",
            "verified_by",
            "verified_by_username",
            "created_at",
            "updated_at",
            "metadata",
            "enabled_module_codes",
        ]
        read_only_fields = [
            "uuid",
            # REMOVE "slug" from here! ⬅️⬅️⬅️ THIS IS THE FIX
            "created_at",
            "updated_at",
            "verified_at",
            "verified_by",
            "verified_by_username",
            "enabled_module_codes",
        ]


class SchoolModuleSerializer(serializers.ModelSerializer):
    class Meta:
        model = SchoolModule
        fields = ['id', 'code', 'name', 'description', 'icon', 'is_default', 'is_active', 'order', 'created_at', 'updated_at']
        read_only_fields = ['created_at', 'updated_at']


class SchoolModuleAccessSerializer(serializers.ModelSerializer):
    module_code = serializers.CharField(source='module.code', read_only=True)
    module_name = serializers.CharField(source='module.name', read_only=True)
    module_icon = serializers.CharField(source='module.icon', read_only=True)
    module_is_default = serializers.BooleanField(source='module.is_default', read_only=True)

    class Meta:
        model = SchoolModuleAccess
        fields = ['id', 'module', 'module_code', 'module_name', 'module_icon', 'module_is_default', 'is_enabled', 'enabled_at']
        read_only_fields = ['enabled_at']


class LanguageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Language
        fields = ['id', 'code', 'name', 'native_name', 'is_default', 'is_active', 'order', 'created_at', 'updated_at']
        read_only_fields = ['created_at', 'updated_at']


class UserProfileSerializer(serializers.ModelSerializer):
    user = serializers.StringRelatedField(read_only=True)
    school_name = serializers.CharField(source="school.name", read_only=True)

    class Meta:
        model = UserProfile
        fields = "__all__"


# In your people/serializers.py, add this serializer:


class CurrentUserSerializer(serializers.Serializer):
    """Serializer for the authenticated user endpoint"""

    # Master Database Models
    user = serializers.SerializerMethodField()
    school = serializers.SerializerMethodField()
    user_profile = serializers.SerializerMethodField()

    # School Database Models (people models)
    teacher_profile = serializers.SerializerMethodField()
    student_profile = serializers.SerializerMethodField()
    parent_profile = serializers.SerializerMethodField()

    # User roles and permissions
    roles = serializers.SerializerMethodField()
    permissions = serializers.SerializerMethodField()

    class Meta:
        fields = [
            "user",
            "school",
            "user_profile",
            "teacher_profile",
            "student_profile",
            "parent_profile",
            "roles",
            "permissions",
        ]

    def get_user(self, obj):
        """Get user data from master database"""
        user = obj.get("user")
        if not user:
            return None

        return {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "is_staff": user.is_staff,
            "is_superuser": user.is_superuser,
            "is_active": user.is_active,
            "date_joined": user.date_joined,
            "last_login": user.last_login,
        }

    def get_school(self, obj):
        """Get school data from master database"""
        school = obj.get("school")
        if not school:
            return None

        # Build school data based on your School model
        school_data = {
            "id": school.id,
            "uuid": str(school.uuid),
            "name": school.name,
            "slug": school.slug,
            "domain_name": school.domain_name,
            "address_line1": school.address_line1,
            "address_line2": school.address_line2,
            "landmark": school.landmark,
            "email": school.email,
            "phone": school.phone,
            "alternate_phone": school.alternate_phone,
            "fax": school.fax,
            "website": school.website,
            "established_year": school.established_year,
            "registration_number": school.registration_number,
            "affiliation_number": school.affiliation_number,
            "motto": school.motto,
            "vision": school.vision,
            "mission": school.mission,
            "is_active": school.is_active,
            "is_trial": school.is_trial,
            "trial_ends_at": school.trial_ends_at,
            "created_at": school.created_at,
            "updated_at": school.updated_at,
        }

        # Add logo URL if exists
        if school.logo:
            school_data["logo_url"] = self.context["request"].build_absolute_uri(
                school.logo.url
            )
        else:
            school_data["logo_url"] = None

        # Add banner URL if exists
        if school.banner_image:
            school_data["banner_url"] = self.context["request"].build_absolute_uri(
                school.banner_image.url
            )
        else:
            school_data["banner_url"] = None

        # Add related model data if they exist
        if school.school_type:
            school_data["school_type"] = {
                "id": school.school_type.id,
                "name": school.school_type.name,
                "code": school.school_type.code,
                "institution_type": school.school_type.institution_type,
                "ownership": school.school_type.ownership,
                "gender_type": school.school_type.gender_type,
            }

        if school.school_board:
            school_data["school_board"] = {
                "id": school.school_board.id,
                "name": school.school_board.name,
                "code": school.school_board.code,
                "board_type": school.school_board.board_type,
            }

        # Add location hierarchy if available
        location_data = {}
        if school.country:
            location_data["country"] = {
                "code": school.country.code,
                "name": school.country.name,
                "phone_code": school.country.phone_code,
            }
        if school.state:
            location_data["state"] = {
                "id": school.state.id,
                "name": school.state.name,
                "code": school.state.code,
            }
        if school.city:
            location_data["city"] = {
                "id": school.city.id,
                "name": school.city.name,
            }
        if school.area:
            location_data["area"] = {
                "id": school.area.id,
                "name": school.area.name,
                "pincode": school.area.pincode,
            }
        if school.pincode:
            location_data["pincode"] = {
                "id": school.pincode.id,
                "pincode": school.pincode.pincode,
                "delivery_office": school.pincode.delivery_office,
            }

        if location_data:
            school_data["location"] = location_data

        # Add coordinates if available
        if school.latitude and school.longitude:
            school_data["coordinates"] = {
                "latitude": float(school.latitude),
                "longitude": float(school.longitude),
            }

        # Add metadata if exists
        if school.metadata:
            school_data["metadata"] = school.metadata

        return school_data

    def get_user_profile(self, obj):
        """Get user profile from master database"""
        user_profile = obj.get("user_profile")
        if not user_profile:
            return None

        profile_data = {
            "id": user_profile.id,
            "external_id": user_profile.external_id,
            "phone": user_profile.phone,
            "address": user_profile.address,
            "date_of_birth": user_profile.date_of_birth,
            "department": user_profile.department,
            "designation": user_profile.designation,
            "joining_date": user_profile.joining_date,
            "is_active": user_profile.is_active,
            "is_primary_contact": user_profile.is_primary_contact,
            "email_notifications": user_profile.email_notifications,
            "sms_notifications": user_profile.sms_notifications,
            "language": user_profile.language,
            "timezone": user_profile.timezone,
            "created_at": user_profile.created_at,
            "updated_at": user_profile.updated_at,
        }

        # Add profile picture URL if exists
        if user_profile.profile_picture:
            profile_data["profile_picture_url"] = self.context[
                "request"
            ].build_absolute_uri(user_profile.profile_picture.url)
        else:
            profile_data["profile_picture_url"] = None

        # Add location data if available
        location_data = {}
        if user_profile.country:
            location_data["country"] = {
                "code": user_profile.country.code,
                "name": user_profile.country.name,
            }
        if user_profile.state:
            location_data["state"] = {
                "id": user_profile.state.id,
                "name": user_profile.state.name,
            }
        if user_profile.city:
            location_data["city"] = {
                "id": user_profile.city.id,
                "name": user_profile.city.name,
            }
        if user_profile.area:
            location_data["area"] = {
                "id": user_profile.area.id,
                "name": user_profile.area.name,
            }
        if user_profile.pincode:
            location_data["pincode"] = {
                "id": user_profile.pincode.id,
                "pincode": user_profile.pincode.pincode,
            }

        if location_data:
            profile_data["location"] = location_data

        # Add metadata with role information
        if user_profile.metadata:
            profile_data["metadata"] = user_profile.metadata
            profile_data["role"] = user_profile.metadata.get("role", "USER")
        else:
            profile_data["metadata"] = {}
            profile_data["role"] = "USER"

        return profile_data

    def get_teacher_profile(self, obj):
        """Get teacher profile from school database"""
        request = self.context["request"]
        user_profile = obj.get("user_profile")

        if not user_profile:
            return None

        # Check role from metadata
        user_metadata = user_profile.metadata or {}
        role = user_metadata.get("role")
        if role != "TEACHER":
            return None

        try:
            # Get external_teacher_id from metadata
            external_teacher_id = user_metadata.get("external_teacher_id")
            if not external_teacher_id:
                return None

            # Get teacher from school database
            # Using the default router which should route to school DB
            teacher = Teacher.objects.get(id=external_teacher_id, is_active=True)

            teacher_data = {
                "id": teacher.id,
                "first_name": teacher.first_name,
                "last_name": teacher.last_name,
                "full_name": teacher.full_name,
                "email": teacher.email,
                "phone": teacher.phone,
                "employee_id": teacher.employee_id,
                "employment_type": teacher.employment_type,
                "qualification": teacher.qualification,
                "date_of_joining": teacher.date_of_joining,
                "is_active": teacher.is_active,
                "created_at": teacher.created_at,
                "updated_at": teacher.updated_at,
            }

            # Add profile image URL if exists
            if teacher.profile_image:
                teacher_data["profile_image_url"] = request.build_absolute_uri(
                    teacher.profile_image.url
                )
            else:
                teacher_data["profile_image_url"] = None

            # Add external_user_id if exists
            if teacher.external_user_id:
                teacher_data["external_user_id"] = teacher.external_user_id

            return teacher_data

        except Teacher.DoesNotExist:
            return None
        except Exception as e:
            # Log error but don't crash the request
            import logging

            logger = logging.getLogger(__name__)
            logger.error(f"Error fetching teacher profile: {str(e)}")
            return None

    def get_student_profile(self, obj):
        """Get student profile from school database"""
        request = self.context["request"]
        user_profile = obj.get("user_profile")

        if not user_profile:
            return None

        # Check role from metadata
        user_metadata = user_profile.metadata or {}
        role = user_metadata.get("role")
        if role != "STUDENT":
            return None

        try:
            # Get external_student_id from metadata
            external_student_id = user_metadata.get("external_student_id")
            if not external_student_id:
                return None

            # Get student from school database
            student = Student.objects.get(id=external_student_id, is_active=True)

            student_data = {
                "id": student.id,
                "first_name": student.first_name,
                "last_name": student.last_name,
                "full_name": student.full_name,
                "email": student.email,
                "phone": student.phone,
                "student_id": student.student_id,
                "admission_number": student.admission_number,
                "roll_number": student.roll_number,
                "gender": student.gender,
                "date_of_birth": student.date_of_birth,
                "blood_group": student.blood_group,
                "admission_date": student.admission_date,
                "is_active": student.is_active,
                "created_at": student.created_at,
                "updated_at": student.updated_at,
            }

            # Add profile image URL if exists
            if student.profile_image:
                student_data["profile_image_url"] = request.build_absolute_uri(
                    student.profile_image.url
                )
            else:
                student_data["profile_image_url"] = None

            # Add external_user_id if exists
            if student.external_user_id:
                student_data["external_user_id"] = student.external_user_id

            return student_data

        except Student.DoesNotExist:
            return None
        except Exception as e:
            import logging

            logger = logging.getLogger(__name__)
            logger.error(f"Error fetching student profile: {str(e)}")
            return None

    def get_parent_profile(self, obj):
        """Get parent profile from school database"""
        request = self.context["request"]
        user_profile = obj.get("user_profile")

        if not user_profile:
            return None

        # Check role from metadata
        user_metadata = user_profile.metadata or {}
        role = user_metadata.get("role")
        if role != "PARENT":
            return None

        try:
            # Get external_parent_id from metadata
            external_parent_id = user_metadata.get("external_parent_id")
            if not external_parent_id:
                return None

            # Get parent from school database
            parent = Parent.objects.get(id=external_parent_id, is_active=True)

            parent_data = {
                "id": parent.id,
                "first_name": parent.first_name,
                "last_name": parent.last_name,
                "full_name": parent.full_name,
                "email": parent.email,
                "phone": parent.phone,
                "parent_type": parent.parent_type,
                "occupation": parent.occupation,
                "is_primary": parent.is_primary,
                "is_active": parent.is_active,
                "created_at": parent.created_at,
                "updated_at": parent.updated_at,
            }

            # Add profile image URL if exists
            if parent.profile_image:
                parent_data["profile_image_url"] = request.build_absolute_uri(
                    parent.profile_image.url
                )
            else:
                parent_data["profile_image_url"] = None

            # Add external_user_id if exists
            if parent.external_user_id:
                parent_data["external_user_id"] = parent.external_user_id

            return parent_data

        except Parent.DoesNotExist:
            return None
        except Exception as e:
            import logging

            logger = logging.getLogger(__name__)
            logger.error(f"Error fetching parent profile: {str(e)}")
            return None

    def get_roles(self, obj):
        """Get user roles from both user flags and profile metadata"""
        user = obj.get("user")
        user_profile = obj.get("user_profile")

        roles = []

        if user:
            # Add roles based on user flags
            if user.is_superuser:
                roles.append("SUPER_ADMIN")
            if user.is_staff:
                roles.append("ADMIN")
            if user.is_active:
                roles.append("ACTIVE_USER")

        if user_profile and user_profile.metadata:
            # Add role from metadata
            metadata_role = user_profile.metadata.get("role")
            if metadata_role:
                roles.append(metadata_role.upper())

        # Deduplicate and return
        return list(set(roles))

    def get_permissions(self, obj):
        """Get user permissions based on roles"""
        user = obj.get("user")
        user_profile = obj.get("user_profile")

        permissions = []

        # Base permissions for all authenticated users
        base_permissions = [
            "view_profile",
            "edit_profile",
            "change_password",
            "view_dashboard",
        ]
        permissions.extend(base_permissions)

        if user:
            # Super admin permissions
            if user.is_superuser:
                permissions.extend(
                    [
                        "manage_all_schools",
                        "manage_all_users",
                        "manage_system_settings",
                        "view_all_analytics",
                        "export_all_data",
                        "manage_subscriptions",
                        "manage_payments",
                    ]
                )

            # Staff/admin permissions
            if user.is_staff:
                permissions.extend(
                    [
                        "manage_school_settings",
                        "manage_users",
                        "manage_students",
                        "manage_teachers",
                        "manage_parents",
                        "manage_academics",
                        "manage_attendance",
                        "manage_exams",
                        "manage_fees",
                        "view_reports",
                        "export_data",
                    ]
                )

        # Role-specific permissions from user profile metadata
        if user_profile and user_profile.metadata:
            role = user_profile.metadata.get("role", "").upper()

            if role == "TEACHER":
                permissions.extend(
                    [
                        "manage_classes",
                        "manage_subjects",
                        "take_attendance",
                        "enter_grades",
                        "manage_assignments",
                        "send_notifications",
                        "view_student_profiles",
                        "view_gradebook",
                    ]
                )

            elif role == "STUDENT":
                permissions.extend(
                    [
                        "view_attendance",
                        "view_grades",
                        "view_timetable",
                        "submit_assignments",
                        "view_assignments",
                        "view_notices",
                        "view_results",
                        "update_profile",
                    ]
                )

            elif role == "PARENT":
                permissions.extend(
                    [
                        "view_child_attendance",
                        "view_child_grades",
                        "view_child_timetable",
                        "view_child_assignments",
                        "view_child_results",
                        "view_notices",
                        "update_contact_info",
                        "make_fee_payments",
                    ]
                )

        # Deduplicate and sort for consistency
        return sorted(list(set(permissions)))
    
class EmailTemplateSerializer(serializers.ModelSerializer):
    created_by_username = serializers.CharField(
        source="created_by.username", read_only=True
    )
    updated_by_username = serializers.CharField(
        source="updated_by.username", read_only=True
    )
    email_log_count = serializers.SerializerMethodField()
 
    class Meta:
        model = EmailTemplate
        fields = [
            "id",
            "uuid",
            "name",
            "subject",
            "body",
            "description",
            "status",
            "tags",
            "variables_used",
            "created_by",
            "created_by_username",
            "updated_by",
            "updated_by_username",
            "email_log_count",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["id", "uuid", "variables_used", "created_at", "updated_at"]
 
    def get_email_log_count(self, obj):
        return obj.email_logs.count()
 
 
class EmailTemplateListSerializer(serializers.ModelSerializer):
    """Lightweight serializer for list views"""
 
    email_log_count = serializers.SerializerMethodField()
 
    class Meta:
        model = EmailTemplate
        fields = [
            "id",
            "uuid",
            "name",
            "subject",
            "body",           # ← ADDED: frontend needs this to populate the editor
            "status",
            "variables_used",
            "email_log_count",
            "created_at",
            "updated_at",
        ]
 
    def get_email_log_count(self, obj):
        return obj.email_logs.count()
 
 
class BulkEmailLogSerializer(serializers.ModelSerializer):
    sent_by_username = serializers.CharField(source="sent_by.username", read_only=True)
    template_name = serializers.CharField(source="template.name", read_only=True)
    to_email_list = serializers.ReadOnlyField()
    cc_email_list = serializers.ReadOnlyField()
 
    class Meta:
        model = BulkEmailLog
        fields = [
            "id",
            "uuid",
            "template",
            "template_name",
            "template_name_snapshot",
            "to_emails",
            "to_email_list",
            "cc_emails",
            "cc_email_list",
            "rendered_subject",
            "rendered_body",
            "context_data",
            "status",
            "error_message",
            "sent_at",
            "sent_by",
            "sent_by_username",
            "created_at",
            "updated_at",
        ]
        read_only_fields = [
            "id",
            "uuid",
            "rendered_subject",
            "rendered_body",
            "status",
            "sent_at",
            "sent_by",
            "created_at",
            "updated_at",
        ]
 
 
class SendBulkEmailSerializer(serializers.Serializer):
    """Serializer for sending a bulk email"""
 
    template_id = serializers.IntegerField()
    to_emails = serializers.ListField(
        child=serializers.EmailField(),
        min_length=1,
        error_messages={"min_length": "At least one recipient email is required."},
    )
    cc_emails = serializers.ListField(
        child=serializers.EmailField(), required=False, default=list
    )
    context = serializers.DictField(
        child=serializers.JSONField(),
        required=False,
        default=dict,
        help_text="Key-value pairs to fill template variables e.g. {'school_name': 'ABC School'}",
    )
 
    def validate_template_id(self, value):
        try:
            template = EmailTemplate.objects.get(id=value, status="active")
            return value
        except EmailTemplate.DoesNotExist:
            raise serializers.ValidationError(
                "Template not found or is not active."
            )
