import os
from rest_framework import serializers
from .models import MeetingRoom, Meeting, MeetingInvitation, MeetingMinutes, MeetingPresentation


class MeetingRoomSerializer(serializers.ModelSerializer):
    class Meta:
        model = MeetingRoom
        fields = [
            "id", "name", "location", "capacity", "facilities",
            "is_active", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class MeetingSerializer(serializers.ModelSerializer):
    room_name = serializers.SerializerMethodField()
    event_name = serializers.SerializerMethodField()
    project_name = serializers.SerializerMethodField()
    organizer_name = serializers.SerializerMethodField()
    attendees_detail = serializers.SerializerMethodField()
    attendee_ids = serializers.PrimaryKeyRelatedField(
        source="attendees", many=True, queryset=Meeting._meta.get_field("attendees").related_model.objects.all(),
        required=False, write_only=True,
    )

    class Meta:
        model = Meeting
        fields = [
            "id", "title", "description",
            "room", "room_name",
            "start_time", "end_time", "status",
            "event", "event_name", "project", "project_name",
            "fund", "donor_visible",
            "organizer", "organizer_name",
            "attendee_ids", "attendees_detail",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "organizer", "created_at", "updated_at"]

    def get_room_name(self, obj):
        return obj.room.name if obj.room_id else None

    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_organizer_name(self, obj):
        if obj.organizer:
            return obj.organizer.get_full_name() or obj.organizer.username
        return None

    def get_attendees_detail(self, obj):
        return [
            {"id": str(u.id), "name": u.get_full_name() or u.username}
            for u in obj.attendees.all()
        ]

    def validate(self, attrs):
        request = self.context.get("request")
        if request is not None:
            from apps.core.tenancy import get_active_organization, assert_same_organization
            org = get_active_organization(request)
            assert_same_organization(org, attrs.get("room"), attrs.get("event"), attrs.get("project"))

        start = attrs.get("start_time", getattr(self.instance, "start_time", None))
        end = attrs.get("end_time", getattr(self.instance, "end_time", None))
        if start and end and end <= start:
            raise serializers.ValidationError({"end_time": "End time must be after start time."})

        room = attrs.get("room", getattr(self.instance, "room", None))
        status = attrs.get("status", getattr(self.instance, "status", "scheduled"))
        if room and start and end and status != "cancelled":
            probe = Meeting(
                room=room, start_time=start, end_time=end, status=status,
                pk=self.instance.pk if self.instance else None,
            )
            clash = probe.conflicts().first()
            if clash:
                raise serializers.ValidationError({
                    "room": f"Room already booked from {clash.start_time:%Y-%m-%d %H:%M} "
                            f"to {clash.end_time:%H:%M} ({clash.title})."
                })
        return attrs


class MeetingInvitationSerializer(serializers.ModelSerializer):
    source = serializers.SerializerMethodField()

    class Meta:
        model = MeetingInvitation
        fields = [
            "id", "meeting", "user", "contact", "email", "name", "status",
            "source", "invited_by", "sent_at", "responded_at", "created_at",
        ]
        read_only_fields = ["id", "invited_by", "sent_at", "created_at"]
        extra_kwargs = {
            "email": {"required": False},
            "name": {"required": False},
        }

    def get_source(self, obj):
        return "internal" if obj.user_id else "external"

    def validate(self, attrs):
        request = self.context.get("request")
        if request is not None:
            from apps.core.tenancy import get_active_organization, assert_same_organization
            org = get_active_organization(request)
            assert_same_organization(org, attrs.get("meeting"), attrs.get("contact"))

        user = attrs.get("user")
        if user:
            # Internal: fill name/email from the linked user.
            attrs.setdefault("name", user.get_full_name() or user.username)
            if not attrs.get("email"):
                attrs["email"] = getattr(user, "email", "") or ""
        if not attrs.get("email"):
            raise serializers.ValidationError({"email": "Email required for external invitees."})
        if not attrs.get("name"):
            attrs["name"] = attrs["email"]
        return attrs


class MeetingMinutesSerializer(serializers.ModelSerializer):
    recorded_by_name = serializers.SerializerMethodField()

    class Meta:
        model = MeetingMinutes
        fields = [
            "id", "meeting", "body", "discussion_points", "action_items",
            "recorded_by", "recorded_by_name", "updated_at", "created_at",
        ]
        read_only_fields = ["id", "recorded_by", "updated_at", "created_at"]

    def get_recorded_by_name(self, obj):
        if obj.recorded_by:
            return obj.recorded_by.get_full_name() or obj.recorded_by.username
        return None

    def validate_meeting(self, value):
        from apps.core.tenancy import validate_same_organization_field
        return validate_same_organization_field(self, value)


class MeetingPresentationSerializer(serializers.ModelSerializer):
    file = serializers.FileField(required=False, allow_null=True)
    file_url = serializers.SerializerMethodField()
    file_name = serializers.SerializerMethodField()

    class Meta:
        model = MeetingPresentation
        fields = [
            "id", "meeting", "presenter", "presenter_name", "title",
            "file", "file_url", "file_name", "uploaded_by", "created_at",
        ]
        read_only_fields = ["id", "uploaded_by", "created_at", "file_url", "file_name"]
        extra_kwargs = {"meeting": {"required": False}}

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

    def validate_meeting(self, value):
        from apps.core.tenancy import validate_same_organization_field
        return validate_same_organization_field(self, value)

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

    def get_file_name(self, obj):
        return os.path.basename(obj.file.name) if obj.file else ""
