from rest_framework import serializers

from apps.authentication.api.v1.serializers.serializer import OrganizationTypeSerializer
from apps.product import exceptions
from apps.product import models as product_models


class ProductCategorySerializer(serializers.ModelSerializer):  # noqa
    class Meta:
        model = product_models.ProductCategory
        fields = '__all__'


class ProductSerializer(serializers.ModelSerializer):
    """ Serializer of product """

    class Meta:
        model = product_models.Product
        fields = '__all__'

    def to_representation(self, instance):
        """ Custom output of product serializer """

        representation = super().to_representation(instance)
        if instance.category:
            representation['category'] = {
                'id': instance.category.id,
                'name': instance.category.name
            }

        return representation


class ProductStatsSerializer(serializers.ModelSerializer):
    class Meta:
        model = product_models.ProductStats
        fields = '__all__'

    def to_representation(self, instance):
        """ custom output of product stat """

        representation = super().to_representation(instance)

        representation['product'] = {
            'id': instance.product.id,
            'name': instance.product.name
        }

        return representation


class AttributeSerializer(serializers.ModelSerializer):
    """ serialize attributes of reference product """

    class Meta:
        model = product_models.Attribute
        fields = '__all__'

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        if instance.product:
            representation['product'] = {
                'id': instance.product.id,
                'name': instance.product.name
            }

        if instance.type:
            representation['type'] = {
                'id': instance.type.id,
                'unit': instance.type.unit
            }
        return representation


class AttributeValueSerializer(serializers.ModelSerializer):
    """ serialize attribute values for child products """

    class Meta:
        model = product_models.AttributeValue
        fields = [
            "id",
            "quota",
            "org_quota_stat",
            "attribute",
            "value",
        ]

    def to_representation(self, instance):
        """ Custom Output of attribute values """
        representation = super().to_representation(instance)
        if instance.attribute:
            representation['attribute_name'] = instance.attribute.name

        return representation

    def update(self, instance, validated_data):
        instance.quota = validated_data.get('quota', instance.quota)
        instance.attribute = validated_data.get('attribute', instance.attribute)
        instance.value = validated_data.get('value', instance.value)
        instance.save()

        return instance


class BrokerSerializer(serializers.ModelSerializer):
    """ serialize product broker """

    class Meta:
        model = product_models.Broker
        fields = '__all__'
        depth = 0

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        if instance.organization_type:
            representation['organization_type'] = OrganizationTypeSerializer(
                instance.organization_type
            ).data

        if instance.product:
            representation['product'] = ProductSerializer(
                instance.product
            ).data

        if instance.calculation_strategy:
            representation['calculation_strategy'] = {
                'id': instance.calculation_strategy.id,
                'unit': instance.calculation_strategy.unit
            }

        return representation


class SaleUnitSerializer(serializers.ModelSerializer):
    """ serialize unit of products for sale """

    class Meta:
        model = product_models.SaleUnit
        fields = [
            "id",
            "product",
            "unit",
            "required",
        ]

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        if instance.product:
            representation['product'] = {
                'id': instance.product.id,
                'name': instance.product.name
            }
        return representation


class IncentivePlanSerializer(serializers.ModelSerializer):  # noqa
    class Meta:
        model = product_models.IncentivePlan
        fields = '__all__'


class IncentivePlanRancherSerializer(serializers.ModelSerializer):
    class Meta:
        model = product_models.IncentivePlanRancher
        fields = '__all__'

    def validate(self, attrs):
        """ validate incentive plans of a rancher """

        rancher_plans_data = self.context['request'].data['data']

        # check if rancher with same plan & livestock exists
        if not self.instance:
            for plan in rancher_plans_data:
                if product_models.IncentivePlanRancher.objects.filter(
                        plan_id=plan['plan'],
                        rancher_id=plan['rancher'],
                        livestock_type_id=plan['livestock_type'],
                ).exists():
                    raise exceptions.RancherIncentivePlanExists()

        return attrs

    def to_representation(self, instance: product_models.IncentivePlanRancher):
        representations = super().to_representation(instance)

        representations['plan_name'] = instance.plan.name
        representations['rancher_id'] = instance.rancher.id
        representations['livestock_type_name'] = instance.livestock_type.name
        representations['allowed_quantity'] = instance.allowed_quantity

        return representations
