from rest_framework import serializers
from .models import (
    Event, EventTemplate, InvitationTemplate, EventInvitation, EventTeam,
    EventSpeaker, EventScheduleItem, EventRegistration, EventMedia, EventDocument, EventLog,
    RegistrationForm, RegistrationFormField, RegistrationFormSubmission,
    EventBlocklist, EventSettings, DEFAULT_EVENT_SETTINGS,
    OfficeCalendarEntry,
)


class OfficeCalendarEntrySerializer(serializers.ModelSerializer):
    """Serializer for org-wide calendar entries (holidays / office events)."""

    class Meta:
        model = OfficeCalendarEntry
        fields = [
            "id", "title", "entry_type", "date", "end_date",
            "recurring", "description", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class EventSerializer(serializers.ModelSerializer):
    """Serializer for Event model."""
    organizer_name = serializers.SerializerMethodField()

    class Meta:
        model = Event
        fields = [
            "id", "name", "event_type", "description", "start_date", "end_date",
            "location", "organizer", "organizer_name", "status", "capacity",
            "tags", "settings", "created_at", "updated_at"
        ]
        read_only_fields = ["id", "organizer", "created_at", "updated_at"]

    def get_organizer_name(self, obj):
        return obj.organizer.get_full_name() or obj.organizer.username


class EventTemplateSerializer(serializers.ModelSerializer):
    """Serializer for EventTemplate model."""
    created_by_name = serializers.SerializerMethodField()

    class Meta:
        model = EventTemplate
        fields = ["id", "name", "event_type", "description", "duration_hours", "default_settings", "created_by", "created_by_name", "created_at"]
        read_only_fields = ["id", "created_at"]

    def get_created_by_name(self, obj):
        if obj.created_by:
            return obj.created_by.get_full_name() or obj.created_by.username
        return None


class InvitationTemplateSerializer(serializers.ModelSerializer):
    """Serializer for InvitationTemplate model."""
    created_by_name = serializers.SerializerMethodField()
    thumbnail_url = serializers.SerializerMethodField()
    category_display = serializers.CharField(source="get_category_display", read_only=True)

    class Meta:
        model = InvitationTemplate
        fields = [
            "id", "name", "category", "category_display", "description",
            "design", "thumbnail", "thumbnail_url", "is_default",
            "created_by", "created_by_name", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at", "created_by"]

    def get_created_by_name(self, obj):
        if obj.created_by:
            return obj.created_by.get_full_name() or obj.created_by.username
        return None

    def get_thumbnail_url(self, obj):
        if not obj.thumbnail:
            return None
        request = self.context.get("request")
        url = obj.thumbnail.url
        return request.build_absolute_uri(url) if request else url


class EventInvitationSerializer(serializers.ModelSerializer):
    """Serializer for EventInvitation model."""
    event_name = serializers.SerializerMethodField()
    invited_by_name = serializers.SerializerMethodField()
    contact_company = serializers.SerializerMethodField()
    contact_phone = serializers.SerializerMethodField()
    contact_position = serializers.SerializerMethodField()

    class Meta:
        model = EventInvitation
        fields = [
            "id", "event", "event_name", "contact",
            "email", "name", "status",
            "contact_company", "contact_phone", "contact_position",
            "invited_by", "invited_by_name", "responded_at", "check_in_time", "created_at",
        ]
        read_only_fields = ["id", "created_at"]

    def get_event_name(self, obj):
        return obj.event.name

    def get_invited_by_name(self, obj):
        if obj.invited_by:
            return obj.invited_by.get_full_name() or obj.invited_by.username
        return None

    def get_contact_company(self, obj):
        c = obj.contact
        if not c:
            return ""
        return getattr(c, "company", "") or ""

    def get_contact_phone(self, obj):
        c = obj.contact
        if not c:
            return ""
        return getattr(c, "phone", "") or ""

    def get_contact_position(self, obj):
        c = obj.contact
        if not c:
            return ""
        return getattr(c, "title", "") or getattr(c, "position", "") or ""


class EventTeamSerializer(serializers.ModelSerializer):
    """Serializer for EventTeam model."""
    user_name = serializers.SerializerMethodField()
    event_name = serializers.SerializerMethodField()
    user_email = serializers.SerializerMethodField()
    user_avatar = serializers.SerializerMethodField()
    name = serializers.EmailField(write_only=True, required=False, allow_blank=True)

    class Meta:
        model = EventTeam
        fields = ["id", "event", "event_name", "user", "user_name", "user_email", "user_avatar", "name", "role", "is_lead", "joined_at"]
        read_only_fields = ["id", "joined_at"]

    def get_user_name(self, obj):
        return obj.user.get_full_name() or obj.user.username

    def get_user_email(self, obj):
        return obj.user.email

    def get_user_avatar(self, obj):
        avatar = getattr(obj.user, "avatar", None)
        if avatar:
            request = self.context.get("request")
            url = avatar.url
            return request.build_absolute_uri(url) if request else url
        contact = getattr(obj.user, "contact_profile", None)
        if contact and getattr(contact, "avatar", None):
            request = self.context.get("request")
            url = contact.avatar.url
            return request.build_absolute_uri(url) if request else url
        return None

    def get_event_name(self, obj):
        return obj.event.name

    def create(self, validated_data):
        from django.contrib.auth import get_user_model
        User = get_user_model()
        name = validated_data.pop("name", None)
        if name:
            user, _ = User.objects.get_or_create(email=name)
            validated_data["user"] = user
        return super().create(validated_data)


class EventSpeakerSerializer(serializers.ModelSerializer):
    """Serializer for EventSpeaker model."""
    event_name = serializers.SerializerMethodField()
    material_file = serializers.FileField(required=False, allow_null=True)
    material_file_name = serializers.SerializerMethodField()

    class Meta:
        model = EventSpeaker
        fields = [
            "id", "event", "event_name", "name", "title", "organization", "bio",
            "session_title", "session_type", "start_time", "end_time",
            "material_status", "material_file", "material_file_name", "created_at"
        ]
        read_only_fields = ["id", "created_at"]

    def validate_material_file(self, value):
        from apps.core.uploads import validate_upload
        if value:
            validate_upload(value)
        return value

    def get_event_name(self, obj):
        return obj.event.name

    def get_material_file_name(self, obj):
        if obj.material_file:
            import os
            return os.path.basename(obj.material_file.name)
        return ""

    def update(self, instance, validated_data):
        if "material_file" in validated_data:
            f = validated_data["material_file"]
            if f:
                validated_data["material_status"] = "uploaded"
            else:
                validated_data["material_status"] = "pending"
        return super().update(instance, validated_data)


class EventScheduleItemSerializer(serializers.ModelSerializer):
    """Serializer for EventScheduleItem model."""
    event_name = serializers.SerializerMethodField()
    duration_minutes = serializers.SerializerMethodField()

    class Meta:
        model = EventScheduleItem
        fields = [
            "id", "event", "event_name", "title", "description", "session_type",
            "track", "start_time", "end_time", "duration_minutes",
            "speaker_name", "material_file", "created_at"
        ]
        read_only_fields = ["id", "created_at"]

    def get_event_name(self, obj):
        return obj.event.name

    def get_duration_minutes(self, obj):
        if obj.start_time and obj.end_time:
            start_minutes = obj.start_time.hour * 60 + obj.start_time.minute
            end_minutes = obj.end_time.hour * 60 + obj.end_time.minute
            return end_minutes - start_minutes
        return 0


class EventRegistrationSerializer(serializers.ModelSerializer):
    """Serializer for EventRegistration model."""
    event_name = serializers.SerializerMethodField()

    class Meta:
        model = EventRegistration
        fields = [
            "id", "event", "event_name", "name", "email", "phone", "company",
            "status", "is_vip", "check_in_time", "registration_date", "created_at"
        ]
        read_only_fields = ["id", "created_at"]

    def get_event_name(self, obj):
        return obj.event.name


class EventMediaSerializer(serializers.ModelSerializer):
    """Serializer for EventMedia model."""
    event_name = serializers.SerializerMethodField()
    uploaded_by_name = serializers.SerializerMethodField()
    file = serializers.FileField(required=False, allow_null=True)
    file_url = serializers.SerializerMethodField()

    class Meta:
        model = EventMedia
        fields = [
            "id", "event", "event_name",
            "file", "file_url",
            "file_type", "title", "description", "caption", "is_cover",
            "uploaded_by", "uploaded_by_name", "created_at",
        ]
        read_only_fields = ["id", "created_at", "file_url", "is_cover"]
        extra_kwargs = {"event": {"required": False}}

    def validate_file(self, value):
        from apps.core.uploads import validate_upload
        if value:
            validate_upload(value)
        return value

    def get_event_name(self, obj):
        return obj.event.name

    def get_uploaded_by_name(self, obj):
        if obj.uploaded_by:
            return obj.uploaded_by.get_full_name() or obj.uploaded_by.username
        return None

    def get_file_url(self, obj):
        if not obj.file:
            return ""
        request = self.context.get("request")
        url = obj.file.url
        return request.build_absolute_uri(url) if request else url


class EventDocumentSerializer(serializers.ModelSerializer):
    """Serializer for EventDocument model."""
    event_name = serializers.SerializerMethodField()
    uploaded_by_name = serializers.SerializerMethodField()
    file = serializers.FileField(required=False, allow_null=True)
    file_url = serializers.SerializerMethodField()
    file_size_human = serializers.SerializerMethodField()

    class Meta:
        model = EventDocument
        fields = [
            "id", "event", "event_name", "name",
            "title", "description",
            "file", "file_url",
            "file_size", "file_size_human",
            "category",
            "uploaded_by", "uploaded_by_name",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at", "file_url", "file_size", "file_size_human"]
        extra_kwargs = {"event": {"required": False}}

    def validate_file(self, value):
        from apps.core.uploads import validate_upload
        if value:
            validate_upload(value)
        return value

    def get_event_name(self, obj):
        return obj.event.name

    def get_uploaded_by_name(self, obj):
        if obj.uploaded_by:
            return obj.uploaded_by.get_full_name() or obj.uploaded_by.username
        return None

    def get_file_url(self, obj):
        if not obj.file:
            return ""
        request = self.context.get("request")
        url = obj.file.url
        return request.build_absolute_uri(url) if request else url

    def get_file_size_human(self, obj):
        size = obj.file_size or 0
        if size <= 0:
            return ""
        units = ["B", "KB", "MB", "GB"]
        s = float(size)
        i = 0
        while s >= 1024 and i < len(units) - 1:
            s /= 1024.0
            i += 1
        return f"{s:.1f} {units[i]}" if i else f"{int(s)} {units[i]}"

    def create(self, validated_data):
        f = validated_data.get("file")
        if f:
            if not validated_data.get("name"):
                import os
                validated_data["name"] = os.path.basename(getattr(f, "name", ""))
            try:
                validated_data["file_size"] = f.size
            except Exception:
                pass
        return super().create(validated_data)

    def update(self, instance, validated_data):
        f = validated_data.get("file")
        if f:
            if not validated_data.get("name"):
                import os
                validated_data["name"] = os.path.basename(getattr(f, "name", instance.name))
            try:
                validated_data["file_size"] = f.size
            except Exception:
                pass
        return super().update(instance, validated_data)


class RegistrationFormFieldSerializer(serializers.ModelSerializer):
    """Serializer for RegistrationFormField."""

    class Meta:
        model = RegistrationFormField
        fields = [
            "id", "form", "order", "type", "label", "placeholder",
            "required", "options", "columns", "meta",
        ]
        read_only_fields = ["id"]
        extra_kwargs = {"form": {"required": False}}


class RegistrationFormSerializer(serializers.ModelSerializer):
    """Serializer for RegistrationForm (with nested fields)."""
    fields_data = RegistrationFormFieldSerializer(source="fields", many=True, read_only=True)
    event_name = serializers.SerializerMethodField()
    project_name = serializers.SerializerMethodField()
    created_by_name = serializers.SerializerMethodField()
    submission_count = serializers.IntegerField(read_only=True, default=0)
    pending_count = serializers.IntegerField(read_only=True, default=0)
    approved_count = serializers.IntegerField(read_only=True, default=0)
    reviewed_count = serializers.IntegerField(read_only=True, default=0)

    class Meta:
        model = RegistrationForm
        fields = [
            "id", "name", "description", "source",
            "event", "event_name", "project", "project_name",
            "status", "config",
            "fields_data",
            "submission_count", "pending_count", "approved_count", "reviewed_count",
            "created_by", "created_by_name",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at", "created_by"]

    def get_event_name(self, obj):
        return obj.event.name if obj.event_id else None

    def get_project_name(self, obj):
        return obj.project.name if obj.project_id else None

    def get_created_by_name(self, obj):
        if obj.created_by:
            return obj.created_by.get_full_name() or obj.created_by.username
        return None


class RegistrationFormSubmissionSerializer(serializers.ModelSerializer):
    """Serializer for RegistrationFormSubmission."""
    reviewed_by_name = serializers.SerializerMethodField()
    form_name = serializers.SerializerMethodField()

    class Meta:
        model = RegistrationFormSubmission
        fields = [
            "id", "form", "form_name",
            "submitter_name", "submitter_email", "answers",
            "status", "auto_blocked", "block_reason",
            "submitted_at", "reviewed_at",
            "reviewed_by", "reviewed_by_name", "ip_address",
        ]
        read_only_fields = ["id", "submitted_at", "ip_address", "auto_blocked", "block_reason"]
        extra_kwargs = {"form": {"required": False}}

    def get_reviewed_by_name(self, obj):
        if obj.reviewed_by:
            return obj.reviewed_by.get_full_name() or obj.reviewed_by.username
        return None

    def get_form_name(self, obj):
        return obj.form.name


class EventBlocklistSerializer(serializers.ModelSerializer):
    """Serializer for EventBlocklist."""
    blocked_by_name = serializers.SerializerMethodField()
    event_name = serializers.SerializerMethodField()
    scope = serializers.SerializerMethodField()

    class Meta:
        model = EventBlocklist
        fields = [
            "id", "email", "name", "reason",
            "event", "event_name", "scope",
            "blocked_by", "blocked_by_name", "blocked_at",
        ]
        read_only_fields = ["id", "blocked_at", "blocked_by"]
        extra_kwargs = {"event": {"required": False, "allow_null": True}}

    def get_blocked_by_name(self, obj):
        if obj.blocked_by:
            return obj.blocked_by.get_full_name() or obj.blocked_by.username
        return None

    def get_event_name(self, obj):
        return obj.event.name if obj.event_id else None

    def get_scope(self, obj):
        return "event" if obj.event_id else "global"


class EventLogSerializer(serializers.ModelSerializer):
    """Serializer for EventLog model."""
    event_name = serializers.SerializerMethodField()
    actor_name = serializers.SerializerMethodField()

    class Meta:
        model = EventLog
        fields = ["id", "event", "event_name", "actor", "actor_name", "action", "detail", "log_type", "created_at"]
        read_only_fields = ["id", "created_at"]

    def get_event_name(self, obj):
        return obj.event.name

    def get_actor_name(self, obj):
        if obj.actor:
            return obj.actor.get_full_name() or obj.actor.username
        return None


class EventSettingsSerializer(serializers.ModelSerializer):
    class Meta:
        model = EventSettings
        fields = ["settings", "updated_at"]
        read_only_fields = ["updated_at"]

    def to_representation(self, instance):
        import copy
        base = copy.deepcopy(DEFAULT_EVENT_SETTINGS)
        base.update(instance.settings or {})
        return base

    def update(self, instance, validated_data):
        payload = self.context["request"].data if self.context.get("request") else validated_data.get("settings", {})
        instance.settings = dict(payload)
        instance.save(update_fields=["settings", "updated_at"])
        return instance