from rest_framework import serializers
from .models import Menu, MenuCategory, MenuItem, MenuItemVariant, MenuLike, MenuSave


class MenuItemVariantSerializer(serializers.ModelSerializer):
    """Serializer for menu item variants"""

    class Meta:
        model = MenuItemVariant
        fields = [
            'id', 'group_name', 'option_name', 'price_adjustment', 'display_order',
        ]
        read_only_fields = ['id']


class MenuItemSerializer(serializers.ModelSerializer):
    """Serializer for menu items"""
    variants = MenuItemVariantSerializer(many=True, read_only=True)

    class Meta:
        model = MenuItem
        fields = [
            'id', 'category', 'name', 'description', 'price', 'price_type',
            'image', 'display_order', 'is_available', 'is_popular', 'is_new',
            'is_spicy', 'is_vegetarian', 'views', 'variants', 'created_at',
        ]
        read_only_fields = ['id', 'views', 'created_at']


class MenuCategorySerializer(serializers.ModelSerializer):
    """Serializer for menu categories"""
    items = MenuItemSerializer(many=True, read_only=True)
    items_count = serializers.SerializerMethodField()

    class Meta:
        model = MenuCategory
        fields = [
            'id', 'menu', 'name', 'description', 'image', 'display_order',
            'is_active', 'items', 'items_count', 'created_at',
        ]
        read_only_fields = ['id', 'created_at']

    def get_items_count(self, obj):
        return obj.items.filter(is_available=True).count()


class MenuSerializer(serializers.ModelSerializer):
    """Basic menu 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)
    vendor_whatsapp = serializers.CharField(source='vendor.whatsapp_number', read_only=True)
    likes_count = serializers.SerializerMethodField()
    is_liked = serializers.SerializerMethodField()
    is_saved = serializers.SerializerMethodField()
    is_sponsored = serializers.SerializerMethodField()
    categories_count = serializers.SerializerMethodField()
    items_count = serializers.SerializerMethodField()
    categories = MenuCategorySerializer(many=True, read_only=True)

    class Meta:
        model = Menu
        fields = [
            'id', 'name', 'slug', 'menu_type', 'description', 'logo', 'cover_image',
            'currency', 'show_prices', 'status', 'views', 'qr_scans',
            'contact_phone', 'contact_whatsapp',
            'vendor_name', 'vendor_slug', 'vendor_county',
            'shop_name', 'shop_logo', 'is_verified_vendor', 'vendor_whatsapp',
            'likes_count', 'is_liked', 'is_saved', 'is_sponsored',
            'categories_count', 'items_count', 'categories',
            'created_at', 'updated_at',
        ]
        read_only_fields = ['id', 'slug', 'views', 'qr_scans', '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 MenuLike.objects.filter(user=request.user, menu=obj).exists()
        return False

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

    def get_categories_count(self, obj):
        return obj.categories.filter(is_active=True).count()

    def get_items_count(self, obj):
        return MenuItem.objects.filter(category__menu=obj, is_available=True).count()

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


class MenuListSerializer(serializers.ModelSerializer):
    """Lightweight menu serializer for list views"""
    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)
    is_sponsored = serializers.SerializerMethodField()
    categories_count = serializers.SerializerMethodField()
    items_count = serializers.SerializerMethodField()
    likes_count = serializers.SerializerMethodField()

    class Meta:
        model = Menu
        fields = [
            'id', 'name', 'slug', 'menu_type', 'description', 'logo', 'cover_image',
            'status', 'views', 'qr_scans',
            'vendor_name', 'vendor_slug', 'vendor_county', 'shop_name',
            'shop_logo', 'is_verified_vendor', 'is_sponsored',
            'categories_count', 'items_count', 'likes_count',
            'created_at', 'updated_at',
        ]

    def get_categories_count(self, obj):
        return obj.categories.filter(is_active=True).count()

    def get_items_count(self, obj):
        return MenuItem.objects.filter(category__menu=obj, is_available=True).count()

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

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


class MenuCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating menus"""
    categories_json = serializers.CharField(required=False, write_only=True, allow_blank=True)

    class Meta:
        model = Menu
        fields = [
            'name', 'menu_type', 'description', 'logo', 'cover_image',
            'currency', 'show_prices', 'contact_phone', 'contact_whatsapp',
            'categories_json',
        ]

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

        # Check if vendor can add more menus
        if not vendor_profile.can_add_menu:
            raise serializers.ValidationError(
                f"You have reached the maximum number of menus ({vendor_profile.max_menus}). "
                "Please upgrade your account for unlimited menus."
            )

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

        return data

    def create(self, validated_data):
        request = self.context.get('request')
        vendor_profile = request.user.vendor_profile
        categories_data = validated_data.pop('categories', [])

        menu = Menu.objects.create(
            vendor=vendor_profile,
            **validated_data
        )

        # Create categories with items
        for cat_data in categories_data:
            items_data = cat_data.pop('items', [])
            category = MenuCategory.objects.create(
                menu=menu,
                name=cat_data.get('name'),
                description=cat_data.get('description', ''),
                display_order=cat_data.get('display_order', 0),
            )

            for item_data in items_data:
                variants_data = item_data.pop('variants', [])
                item = MenuItem.objects.create(
                    category=category,
                    name=item_data.get('name'),
                    description=item_data.get('description', ''),
                    price=item_data.get('price'),
                    price_type=item_data.get('price_type', 'fixed'),
                    display_order=item_data.get('display_order', 0),
                    is_available=item_data.get('is_available', True),
                    is_popular=item_data.get('is_popular', False),
                    is_new=item_data.get('is_new', False),
                    is_spicy=item_data.get('is_spicy', False),
                    is_vegetarian=item_data.get('is_vegetarian', False),
                )

                # Create variants (premium only)
                if vendor_profile.is_upgraded:
                    for var_data in variants_data:
                        MenuItemVariant.objects.create(
                            item=item,
                            group_name=var_data.get('group_name'),
                            option_name=var_data.get('option_name'),
                            price_adjustment=var_data.get('price_adjustment', 0),
                            display_order=var_data.get('display_order', 0),
                        )

        # Update vendor menu count
        vendor_profile.total_menus += 1
        vendor_profile.save(update_fields=['total_menus'])

        return menu


class MenuUpdateSerializer(serializers.ModelSerializer):
    """Serializer for updating menus"""

    class Meta:
        model = Menu
        fields = [
            'name', 'menu_type', 'description', 'logo', 'cover_image',
            'currency', 'show_prices', 'status', 'contact_phone', 'contact_whatsapp',
        ]

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        return instance


class MenuCategoryCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating/updating categories"""
    items_json = serializers.CharField(required=False, write_only=True, allow_blank=True)

    class Meta:
        model = MenuCategory
        fields = ['name', 'description', 'image', 'display_order', 'is_active', 'items_json']

    def validate(self, data):
        import json
        # Parse items_json
        items_json = data.pop('items_json', None)
        items = []
        if items_json:
            try:
                items = json.loads(items_json) if isinstance(items_json, str) else items_json
            except json.JSONDecodeError:
                items = []
        data['items'] = items
        return data


class MenuItemCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating/updating items"""
    variants_json = serializers.CharField(required=False, write_only=True, allow_blank=True)

    class Meta:
        model = MenuItem
        fields = [
            'name', 'description', 'price', 'price_type', 'image',
            'display_order', 'is_available', 'is_popular', 'is_new',
            'is_spicy', 'is_vegetarian', 'variants_json',
        ]

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

        # Check item limit for free vendors
        if not vendor_profile.is_upgraded:
            menu = self.context.get('menu')
            if menu:
                current_items = MenuItem.objects.filter(category__menu=menu).count()
                if current_items >= vendor_profile.max_items_per_menu:
                    raise serializers.ValidationError(
                        f"Free vendors can only have {vendor_profile.max_items_per_menu} items per menu. "
                        "Please upgrade for unlimited items."
                    )

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

        # Check image upload permission
        if not vendor_profile.is_upgraded and data.get('image'):
            raise serializers.ValidationError(
                "Item images are only available for premium vendors. Please upgrade."
            )

        return data
