from rest_framework import serializers
from .models import Event, EventPackage, EventLike, EventSave


class EventPackageSerializer(serializers.ModelSerializer):
    """Serializer for event packages"""

    class Meta:
        model = EventPackage
        fields = [
            'id', 'name', 'description', 'price', 'price_type',
            'whats_included', 'max_attendees', 'duration',
            'created_at', 'updated_at',
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']


class EventSerializer(serializers.ModelSerializer):
    """Basic event serializer for listing"""
    vendor_name = serializers.CharField(source='vendor.shop_name', read_only=True)
    vendor_slug = serializers.CharField(source='vendor.slug', read_only=True)
    vendor_county = serializers.CharField(source='vendor.user.county', read_only=True)
    shop_name = serializers.CharField(source='vendor.shop_name', read_only=True)
    shop_logo = serializers.ImageField(source='vendor.shop_logo', read_only=True)
    is_verified_vendor = serializers.BooleanField(source='vendor.is_verified_vendor', read_only=True)
    likes_count = serializers.SerializerMethodField()
    is_liked = serializers.SerializerMethodField()
    is_saved = serializers.SerializerMethodField()
    is_sponsored = serializers.SerializerMethodField()
    rating = serializers.DecimalField(source='vendor.rating', max_digits=2, decimal_places=1, read_only=True)
    min_price = serializers.SerializerMethodField()
    max_price = serializers.SerializerMethodField()
    packages_count = serializers.SerializerMethodField()
    packages = EventPackageSerializer(many=True, read_only=True)
    vendor_whatsapp = serializers.CharField(source='vendor.user.phone_number', read_only=True)
    # Mall/Group info
    group_id = serializers.IntegerField(source='group.id', read_only=True, allow_null=True)
    group_name = serializers.CharField(source='group.name', read_only=True, allow_null=True)
    group_slug = serializers.CharField(source='group.slug', read_only=True, allow_null=True)

    class Meta:
        model = Event
        fields = [
            'id', 'title', 'slug', 'category', 'description',
            'event_type', 'date', 'time', 'end_time', 'recurring_days',
            'start_date', 'end_date',
            'location_type', 'venue', 'online_link', 'county', 'town_area',
            'is_free', 'image', 'video', 'status', 'views',
            'likes_count', 'min_price', 'max_price', 'packages_count',
            'vendor_name', 'vendor_slug', 'vendor_county',
            'shop_name', 'shop_logo', 'is_verified_vendor', 'vendor_whatsapp',
            'is_liked', 'is_saved', 'is_sponsored', 'rating', 'packages',
            'group_id', 'group_name', 'group_slug',
            'created_at', 'updated_at',
        ]
        read_only_fields = ['id', 'slug', 'views', 'created_at', 'updated_at']

    def get_likes_count(self, obj):
        return obj.likes.count()

    def get_is_liked(self, obj):
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            return EventLike.objects.filter(user=request.user, event=obj).exists()
        return False

    def get_is_saved(self, obj):
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            return EventSave.objects.filter(user=request.user, event=obj).exists()
        return False

    def get_min_price(self, obj):
        return obj.min_price

    def get_max_price(self, obj):
        return obj.max_price

    def get_packages_count(self, obj):
        return obj.packages.count()

    def get_is_sponsored(self, obj):
        return getattr(obj, 'is_sponsored', False)


class EventDetailSerializer(EventSerializer):
    """Detailed event serializer with full vendor info"""

    class Meta(EventSerializer.Meta):
        fields = EventSerializer.Meta.fields + ['vendor']

    def get_fields(self):
        fields = super().get_fields()
        from accounts.serializers import VendorProfileSerializer
        fields['vendor'] = VendorProfileSerializer(read_only=True)
        return fields


class EventCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating events"""
    packages_json = serializers.CharField(required=False, write_only=True, allow_blank=True)
    recurring_days_json = serializers.CharField(required=False, write_only=True, allow_blank=True, allow_null=True)
    group_id = serializers.IntegerField(required=False, write_only=True, allow_null=True)

    class Meta:
        model = Event
        fields = [
            'title', 'category', 'description',
            'event_type', 'date', 'time', 'end_time', 'recurring_days',
            'start_date', 'end_date',
            'location_type', 'venue', 'online_link', 'county', 'town_area',
            'is_free', 'image', 'video', 'status', 'packages_json', 'recurring_days_json', 'group_id',
        ]
        extra_kwargs = {
            'recurring_days': {'required': False, 'allow_null': True},
        }

    def validate(self, data):
        import json
        request = self.context.get('request')
        vendor_profile = request.user.vendor_profile

        # Parse recurring_days_json
        recurring_days_json = data.pop('recurring_days_json', None)
        if recurring_days_json:
            try:
                data['recurring_days'] = json.loads(recurring_days_json) if isinstance(recurring_days_json, str) else recurring_days_json
            except json.JSONDecodeError:
                data['recurring_days'] = []

        # Parse packages_json
        packages_json = data.pop('packages_json', None)
        packages = []
        if packages_json:
            try:
                packages = json.loads(packages_json) if isinstance(packages_json, str) else packages_json
            except json.JSONDecodeError:
                packages = []
        data['packages'] = packages

        # Validate event type requirements
        event_type = data.get('event_type', 'one-time')
        if event_type == 'one-time' and not data.get('date'):
            raise serializers.ValidationError({'date': 'Date is required for one-time events.'})
        if event_type == 'recurring' and not data.get('recurring_days'):
            raise serializers.ValidationError({'recurring_days': 'Recurring days are required for recurring events.'})

        # Validate pricing
        is_free = data.get('is_free', False)
        if not is_free and not packages:
            raise serializers.ValidationError({'packages': 'At least one package is required for paid events.'})

        # Video only for upgraded vendors
        if not vendor_profile.is_upgraded and data.get('video'):
            raise serializers.ValidationError(
                "Video upload is only available for upgraded vendors."
            )

        # Validate group membership if group_id provided
        group_id = data.get('group_id')
        if group_id:
            from groups.models import Group, GroupMembership
            try:
                group = Group.objects.get(id=group_id, is_active=True)
                # Check if vendor is a member of the group
                if not GroupMembership.objects.filter(
                    group=group,
                    user=request.user,
                    status='active'
                ).exists():
                    raise serializers.ValidationError({'group_id': 'You must be a member of this mall to post events.'})
            except Group.DoesNotExist:
                raise serializers.ValidationError({'group_id': 'Mall not found.'})

        return data

    def create(self, validated_data):
        request = self.context.get('request')
        vendor_profile = request.user.vendor_profile
        packages_data = validated_data.pop('packages', [])
        group_id = validated_data.pop('group_id', None)

        # Get group if specified
        group = None
        if group_id:
            from groups.models import Group
            try:
                group = Group.objects.get(id=group_id)
            except Group.DoesNotExist:
                pass

        event = Event.objects.create(
            vendor=vendor_profile,
            group=group,
            **validated_data
        )

        # Create packages
        for pkg_data in packages_data:
            EventPackage.objects.create(
                event=event,
                name=pkg_data.get('name'),
                description=pkg_data.get('description', ''),
                price=pkg_data.get('price', 0),
                price_type=pkg_data.get('price_type', 'fixed'),
                whats_included=pkg_data.get('whats_included', ''),
                max_attendees=pkg_data.get('max_attendees'),
                duration=pkg_data.get('duration'),
            )

        return event


class EventUpdateSerializer(serializers.ModelSerializer):
    """Serializer for updating events"""
    packages_json = serializers.CharField(required=False, write_only=True, allow_blank=True)
    deleted_packages_json = serializers.CharField(required=False, write_only=True, allow_blank=True)
    recurring_days_json = serializers.CharField(required=False, write_only=True, allow_blank=True, allow_null=True)

    class Meta:
        model = Event
        fields = [
            'title', 'category', 'description',
            'event_type', 'date', 'time', 'end_time', 'recurring_days',
            'location_type', 'venue', 'online_link', 'county', 'town_area',
            'is_free', 'image', 'video', 'status',
            'packages_json', 'deleted_packages_json', 'recurring_days_json',
        ]
        extra_kwargs = {
            'recurring_days': {'required': False, 'allow_null': True},
        }

    def validate(self, data):
        import json
        request = self.context.get('request')
        vendor_profile = request.user.vendor_profile

        if not vendor_profile.is_upgraded and data.get('video'):
            raise serializers.ValidationError(
                "Video upload is only available for upgraded vendors."
            )

        # Parse recurring_days_json
        recurring_days_json = data.pop('recurring_days_json', None)
        if recurring_days_json:
            try:
                data['recurring_days'] = json.loads(recurring_days_json) if isinstance(recurring_days_json, str) else recurring_days_json
            except json.JSONDecodeError:
                data['recurring_days'] = []

        # Parse packages_json
        packages_json = data.pop('packages_json', None)
        packages = []
        if packages_json:
            try:
                packages = json.loads(packages_json) if isinstance(packages_json, str) else packages_json
            except json.JSONDecodeError:
                packages = []
        data['packages'] = packages

        # Parse deleted_packages_json
        deleted_packages_json = data.pop('deleted_packages_json', None)
        deleted_packages = []
        if deleted_packages_json:
            try:
                deleted_packages = json.loads(deleted_packages_json) if isinstance(deleted_packages_json, str) else deleted_packages_json
            except json.JSONDecodeError:
                deleted_packages = []
        data['deleted_packages'] = deleted_packages

        return data

    def update(self, instance, validated_data):
        packages_data = validated_data.pop('packages', None)
        deleted_packages = validated_data.pop('deleted_packages', [])

        # Update event fields
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        # Delete specified packages
        if deleted_packages:
            EventPackage.objects.filter(id__in=deleted_packages, event=instance).delete()

        # Update/create packages
        if packages_data is not None:
            for pkg_data in packages_data:
                pkg_id = pkg_data.get('id')
                if pkg_id:
                    # Update existing package
                    try:
                        pkg = EventPackage.objects.get(id=pkg_id, event=instance)
                        pkg.name = pkg_data.get('name', pkg.name)
                        pkg.description = pkg_data.get('description', pkg.description)
                        pkg.price = pkg_data.get('price', pkg.price)
                        pkg.price_type = pkg_data.get('price_type', pkg.price_type)
                        pkg.whats_included = pkg_data.get('whats_included', pkg.whats_included)
                        pkg.max_attendees = pkg_data.get('max_attendees')
                        pkg.duration = pkg_data.get('duration')
                        pkg.save()
                    except EventPackage.DoesNotExist:
                        pass
                else:
                    # Create new package
                    EventPackage.objects.create(
                        event=instance,
                        name=pkg_data.get('name'),
                        description=pkg_data.get('description', ''),
                        price=pkg_data.get('price', 0),
                        price_type=pkg_data.get('price_type', 'fixed'),
                        whats_included=pkg_data.get('whats_included', ''),
                        max_attendees=pkg_data.get('max_attendees'),
                        duration=pkg_data.get('duration'),
                    )

        return instance
