from rest_framework import serializers

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


class POSFreeProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = POSFreeProducts
        fields = '__all__'

    def validate(self, attrs):
        """
        @check free product for pos to be unique
        """

        if not self.instance:

            product = attrs['product']
            organization = attrs['organization']
            device = self.context['device']

            if self.Meta.model.objects.filter(
                    organization=organization,
                    product=product,
                    device=device
            ).exists():
                raise FreePOSProductUniqueCheck()

        return attrs

    def to_representation(self, instance):
        representation = super().to_representation(instance)

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

        representation['total_price'] = instance.price + instance.company_fee
        representation['main_shaba'] = "IR" + instance.organization.bank_information.all().first().sheba  # noqa

        main_company = product_models.Organization.objects.get(
            national_unique_id='1111111111'
        )
        main_company_bank_account = main_company.bank_information.first()
        if instance.company_fee != 0:
            representation['company_shaba'] = "IR" + main_company_bank_account.sheba  # noqa
        else:
            representation['company_shaba'] = ""  # noqa

        return representation


#
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__'
