from rest_framework import serializers
from shop_management.serializers.data.base import DataRootSerializer
from shop_management.serializers.data.shop import ShopSerializer
from shop_management.models.data.product import Category, Product, ProductPrice


class CategorySerializer(DataRootSerializer):
    shop_details = ShopSerializer(source='shop', read_only=True)

    class Meta:
        model = Category
        fields = '__all__'
class ProductPriceSerializer(DataRootSerializer):
    currency_details = serializers.SerializerMethodField()
    product_details = serializers.SerializerMethodField()

    class Meta:
        model = ProductPrice
        fields = "__all__"
        read_only_fields = ("created_by",)
        extra_kwargs = {
            "price_type": {"required": False, "default": ProductPrice.PriceType.RETAIL}
        }

    def validate_price_type(self, value):
        if value != ProductPrice.PriceType.RETAIL:
            raise serializers.ValidationError("Only one Sale price is supported.")
        return value

    def get_currency_details(self, obj):
        return {"id": obj.currency_id, "title": obj.currency.title}

    def get_product_details(self, obj):
        return {"id": obj.product_id, "name": obj.product.name, "code": obj.product.code}

    def validate(self, attrs):
        product = attrs.get("product") or getattr(self.instance, "product", None)
        currency = attrs.get("currency") or getattr(self.instance, "currency", None)
        if product and currency and product.shop_id != currency.shop_id:
            raise serializers.ValidationError(
                {"currency": "Price currency must belong to the product branch."}
            )
        request = self.context.get("request")
        if request and product and not request.user.is_superuser:
            allowed = product.shop.owner_id == request.user.id or product.shop.assigned_users.filter(
                pk=request.user.id
            ).exists()
            if not allowed:
                raise serializers.ValidationError(
                    {"product": "You do not have access to this product branch."}
                )
        return attrs


class ProductSerializer(DataRootSerializer):
    shop_details = ShopSerializer(source='shop', read_only=True)
    category_details = CategorySerializer(source='category', read_only=True)
    default_unit_details = serializers.SerializerMethodField()
    prices = ProductPriceSerializer(many=True, read_only=True)

    class Meta:
        model = Product
        fields = '__all__'
        extra_kwargs = {
            "default_unit": {
                "required": True,
                "allow_null": False,
                "error_messages": {
                    "required": "Select a default unit for this product.",
                    "null": "Select a default unit for this product.",
                    "does_not_exist": "Select a valid unit belonging to this branch.",
                },
            }
        }

    def get_default_unit_details(self, obj):
        if not obj.default_unit:
            return None
        return {"id": obj.default_unit_id, "title": obj.default_unit.title}

    def validate(self, attrs):
        shop = attrs.get("shop") or getattr(self.instance, "shop", None)
        category = attrs.get("category") or getattr(self.instance, "category", None)
        default_unit = attrs.get("default_unit") or getattr(self.instance, "default_unit", None)
        if not default_unit:
            raise serializers.ValidationError(
                {"default_unit": "A default unit is required. Purchases and sales use this unit automatically."}
            )
        if shop and category and category.shop_id != shop.id:
            raise serializers.ValidationError({"category": "Category must belong to the product branch."})
        if shop and default_unit and default_unit.shop_id != shop.id:
            raise serializers.ValidationError({"default_unit": "Default unit must belong to the product branch."})
        if attrs.get("requires_expiry") and not attrs.get(
            "requires_batch", getattr(self.instance, "requires_batch", False)
        ):
            attrs["requires_batch"] = True
        return attrs
