"""Product app serializers."""
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers

from comment.models import Comment
from comment.serializers import CommentSerializer
from establishment.serializers import EstablishmentProductShortSerializer
from establishment.serializers.common import _EstablishmentAddressShortSerializer
from location.serializers import WineOriginRegionBaseSerializer,\
    WineOriginBaseSerializer, EstablishmentWineOriginBaseSerializer
from main.serializers import AwardSerializer
from product import models
from review.serializers import ReviewShortSerializer
from tag.serializers import TagBaseSerializer, TagCategoryProductSerializer
from utils import exceptions as utils_exceptions
from utils.serializers import TranslatedField, FavoritesCreateSerializer, ImageBaseSerializer


class ProductTagSerializer(TagBaseSerializer):
    """Serializer for model Tag."""

    category = TagCategoryProductSerializer(read_only=True)

    class Meta(TagBaseSerializer.Meta):
        """Meta class."""

        fields = TagBaseSerializer.Meta.fields + (
            'category',
        )


class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
    """ProductSubType base serializer"""
    name_translated = TranslatedField()
    index_name_display = serializers.CharField(source='get_index_name_display',
                                               read_only=True)
    default_image_url = serializers.ImageField(source='default_image.image',
                                               allow_null=True)
    preview_image = serializers.URLField(source='preview_image_url',
                                         allow_null=True,
                                         read_only=True)

    class Meta:
        model = models.ProductSubType
        fields = [
            'id',
            'name_translated',
            'index_name_display',
            'default_image_url',
            'preview_image',
        ]


class ProductTypeBaseSerializer(serializers.ModelSerializer):
    """ProductType base serializer"""
    name_translated = TranslatedField()
    default_image_url = serializers.ImageField(source='default_image.image',
                                               allow_null=True)
    preview_image = serializers.URLField(source='preview_image_url',
                                         allow_null=True,
                                         read_only=True)

    class Meta:
        model = models.ProductType
        fields = [
            'id',
            'name_translated',
            'index_name',
            'default_image_url',
            'preview_image',
        ]


class ProductClassificationBaseSerializer(serializers.ModelSerializer):
    """Serializer for model ProductClassification."""

    name = serializers.CharField(source='classification_type.name')

    class Meta:
        """Meta class."""
        model = models.ProductClassification
        fields = (
            'name',
        )


class ProductStandardBaseSerializer(serializers.ModelSerializer):
    """Serializer for model ProductStandard."""

    standard_type = serializers.CharField(source='get_standard_type_display')

    class Meta:
        """Meta class."""
        model = models.ProductStandard
        fields = (
            'name',
            'standard_type',
        )


class ProductBaseSerializer(serializers.ModelSerializer):
    """Product base serializer."""
    name = serializers.CharField(source='display_name', read_only=True)
    product_type = ProductTypeBaseSerializer(read_only=True)
    subtypes = ProductSubTypeBaseSerializer(many=True, read_only=True)
    establishment_detail = EstablishmentProductShortSerializer(source='establishment', read_only=True)
    tags = ProductTagSerializer(source='related_tags', many=True, read_only=True)
    wine_regions = WineOriginRegionBaseSerializer(many=True, source='wine_origins', read_only=True)
    wine_colors = TagBaseSerializer(many=True, read_only=True)
    preview_image_url = serializers.URLField(allow_null=True,
                                             read_only=True)
    in_favorites = serializers.BooleanField(allow_null=True, read_only=True)
    wine_origins = EstablishmentWineOriginBaseSerializer(many=True, read_only=True)

    class Meta:
        """Meta class."""
        model = models.Product
        fields = [
            'id',
            'slug',
            'name',
            'product_type',
            'subtypes',
            'public_mark',
            'establishment_detail',
            'vintage',
            'tags',
            'preview_image_url',
            'wine_regions',
            'wine_colors',
            'in_favorites',
            'wine_origins',
        ]


class ProductDetailSerializer(ProductBaseSerializer):
    """Product detail serializer."""
    description_translated = TranslatedField()
    establishment_detail = _EstablishmentAddressShortSerializer(source='establishment', read_only=True)
    review = ReviewShortSerializer(source='last_published_review', read_only=True)
    awards = AwardSerializer(many=True, read_only=True)
    classifications = ProductClassificationBaseSerializer(many=True, read_only=True)
    standards = ProductStandardBaseSerializer(many=True, read_only=True)
    wine_origins = WineOriginBaseSerializer(many=True, read_only=True)
    bottles_produced = TagBaseSerializer(many=True, read_only=True)
    sugar_contents = TagBaseSerializer(many=True, read_only=True)
    grape_variety = TagBaseSerializer(many=True, read_only=True)
    bottle_sizes = TagBaseSerializer(many=True, read_only=True)
    alcohol_percentage = TagBaseSerializer(read_only=True)
    image_url = serializers.URLField(allow_null=True,
                                     read_only=True)
    new_image = ImageBaseSerializer(source='crop_main_image', allow_null=True, read_only=True)

    class Meta(ProductBaseSerializer.Meta):
        fields = ProductBaseSerializer.Meta.fields + [
            'description_translated',
            'review',
            'awards',
            'classifications',
            'standards',
            'wine_origins',
            'bottles_produced',
            'sugar_contents',
            'image_url',
            'new_image',
            'grape_variety',
            'average_price',
            'bottle_sizes',
            'alcohol_percentage',
        ]


class ProductFavoritesCreateSerializer(FavoritesCreateSerializer):
    """Serializer to create favorite object w/ model Product."""

    def validate(self, attrs):
        """Overridden validate method"""
        # Check product object
        product_qs = models.Product.objects.filter(slug=self.slug)

        # Check product obj by slug from lookup_kwarg
        if not product_qs.exists():
            raise serializers.ValidationError({'detail': _('Object not found.')})
        else:
            product = product_qs.first()

        # Check existence in favorites
        if product.favorites.filter(user=self.user).exists():
            raise utils_exceptions.FavoritesError()

        attrs['product'] = product
        return attrs

    def create(self, validated_data, *args, **kwargs):
        """Overridden create method"""
        validated_data.update({
            'user': self.user,
            'content_object': validated_data.pop('product')
        })
        return super().create(validated_data)


class ProductCommentCreateSerializer(CommentSerializer):
    """Create comment serializer"""
    mark = serializers.IntegerField()

    class Meta:
        """Serializer for model Comment"""
        model = Comment
        fields = [
            'id',
            'created',
            'text',
            'mark',
            'nickname',
            'profile_pic',
        ]

    def validate(self, attrs):
        """Override validate method"""
        # Check product object
        product_slug = self.context.get('request').parser_context.get('kwargs').get('slug')
        product_qs = models.Product.objects.filter(slug=product_slug)
        if not product_qs.exists():
            raise serializers.ValidationError({'detail': _('Product not found.')})
        attrs['product'] = product_qs.first()
        return attrs

    def create(self, validated_data, *args, **kwargs):
        """Override create method"""
        validated_data.update({
            'user': self.context.get('request').user,
            'content_object': validated_data.pop('product')
        })
        return super().create(validated_data)


class ProductGuideElementSerializer(ProductBaseSerializer):
    """Serializer for serializing in GuideElement for model Product."""

    class Meta(ProductBaseSerializer.Meta):
        """Meta class."""
        _unused_fields = ('tags', 'wine_regions', 'wine_colors', 'preview_image_url')
        fields = ProductBaseSerializer.Meta.fields

        # pop unused fields
        for unused_field in _unused_fields: fields.pop(fields.index(unused_field))
