"""Search indexes serializers."""
from rest_framework import serializers
from elasticsearch_dsl import AttrDict
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
from news.serializers import NewsTypeSerializer
from search_indexes.documents import EstablishmentDocument, NewsDocument
from search_indexes.documents.product import ProductDocument
from search_indexes.utils import get_translated_value
from json import loads


class TagsDocumentSerializer(serializers.Serializer):
    """Tags serializer for ES Document."""

    id = serializers.IntegerField()
    label_translated = serializers.SerializerMethodField()

    def get_label_translated(self, obj):
        if isinstance(obj, dict):
            return get_translated_value(obj.get('label'))
        return get_translated_value(obj.label)


class EstablishmentTypeSerializer(serializers.Serializer):
    """Establishment type serializer for ES Document"""

    id = serializers.IntegerField()
    name_translated = serializers.SerializerMethodField()
    index_name = serializers.CharField()
    default_image = serializers.CharField()
    preview_image_url = serializers.CharField()

    def get_name_translated(self, obj):
        if isinstance(obj, dict):
            return get_translated_value(obj.get('name'))
        return get_translated_value(obj.name)


class ProductSubtypeDocumentSerializer(serializers.Serializer):
    """Product subtype serializer for ES Document."""

    id = serializers.IntegerField()
    name_translated = serializers.SerializerMethodField()
    default_image = serializers.CharField()
    preview_image_url = serializers.CharField()

    def get_name_translated(self, obj):
        if isinstance(obj, dict):
            return get_translated_value(obj.get('name'))
        return get_translated_value(obj.name)


class WineRegionCountryDocumentSerialzer(serializers.Serializer):
    """Wine region country ES document serializer."""

    id = serializers.IntegerField()
    code = serializers.CharField()
    name_translated = serializers.SerializerMethodField()

    @staticmethod
    def get_name_translated(obj):
        return get_translated_value(obj.name)

    def get_attribute(self, instance):
        return instance.country if instance and instance.country else None


class WineRegionDocumentSerializer(serializers.Serializer):
    """Wine region ES document serializer."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    country = WineRegionCountryDocumentSerialzer(allow_null=True)

    def get_attribute(self, instance):
        return instance.wine_region if instance and instance.wine_region else None


class WineSubRegionDocumentSerializer(serializers.Serializer):
    """Wine region ES document serializer."""

    id = serializers.IntegerField()
    name = serializers.CharField()

    def get_attribute(self, instance):
        return instance.wine_sub_region if instance and instance.wine_sub_region else None


class TagDocumentSerializer(serializers.Serializer):
    """Tag ES document serializer,"""

    id = serializers.IntegerField()
    label_translated = serializers.SerializerMethodField()
    index_name = serializers.CharField(source='value')

    @staticmethod
    def get_label_translated(obj):
        if isinstance(obj, dict):
            return get_translated_value(obj.get('label'))
        return get_translated_value(obj.label)


class ProductTypeSerializer(serializers.Serializer):
    """Product type ES document serializer."""

    id = serializers.IntegerField()
    index_name = serializers.CharField()
    name_translated = serializers.SerializerMethodField()
    default_image = serializers.CharField()
    preview_image_url = serializers.CharField()

    @staticmethod
    def get_name_translated(obj):
        if isinstance(obj, dict):
            return get_translated_value(obj.get('name'))
        return get_translated_value(obj.name)

    def get_attribute(self, instance):
        return instance.product_type if instance and instance.product_type else None


class CityDocumentShortSerializer(serializers.Serializer):
    """City serializer for ES Document,"""

    id = serializers.IntegerField()
    code = serializers.CharField(allow_null=True)
    name = serializers.CharField()


class CountryDocumentSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    code = serializers.CharField(allow_null=True)
    svg_image = serializers.CharField()
    name_translated = serializers.SerializerMethodField()

    @staticmethod
    def get_name_translated(obj):
        if isinstance(obj, dict):
            return get_translated_value(obj.get('name'))
        return get_translated_value(obj.name)


class AnotherCityDocumentShortSerializer(CityDocumentShortSerializer):
    country = CountryDocumentSerializer()

    def to_representation(self, instance):
        if instance != AttrDict(d={}) or \
                (isinstance(instance, dict) and len(instance) != 0):
            return super().to_representation(instance)
        return None


class AddressDocumentSerializer(serializers.Serializer):
    """Address serializer for ES Document."""

    id = serializers.IntegerField()
    city = CityDocumentShortSerializer()
    street_name_1 = serializers.CharField()
    street_name_2 = serializers.CharField()
    number = serializers.IntegerField()
    postal_code = serializers.CharField()
    latitude = serializers.FloatField(allow_null=True, source='coordinates.lat')
    longitude = serializers.FloatField(allow_null=True, source='coordinates.lon')
    geo_lon = serializers.FloatField(allow_null=True, source='coordinates.lon')
    geo_lat = serializers.FloatField(allow_null=True, source='coordinates.lat')

    # todo: refator
    def to_representation(self, instance):
        if instance != AttrDict(d={}) or \
                (isinstance(instance, dict) and len(instance) != 0):
            return super().to_representation(instance)
        return None


class PSAddressDocumentSerializer(serializers.Serializer):
    """Address serializer for ES Document."""

    id = serializers.IntegerField()
    street_name_1 = serializers.CharField()
    postal_code = serializers.CharField()


class ProductEstablishmentSerializer(serializers.Serializer):
    """Related to Product Establishment ES document serializer."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()
    index_name = serializers.CharField()
    city = AnotherCityDocumentShortSerializer()
    address = PSAddressDocumentSerializer(allow_null=True)

    def get_attribute(self, instance):
        return instance.establishment if instance and instance.establishment else None


class ScheduleDocumentSerializer(serializers.Serializer):
    """Schedule serializer for ES Document"""

    id = serializers.IntegerField()
    weekday = serializers.IntegerField()
    weekday_display = serializers.CharField()
    closed_at = serializers.CharField()
    opening_at = serializers.CharField()


class InFavoritesMixin(DocumentSerializer):
    """Append in_favorites field."""

    in_favorites = serializers.SerializerMethodField()

    def get_in_favorites(self, obj):
        request = self.context['request']
        user = request.user
        if user.is_authenticated:
            return user.id in obj.favorites_for_users
        return False

    class Meta:
        """Meta class."""

        _abstract = True


class NewsDocumentSerializer(InFavoritesMixin, DocumentSerializer):
    """News document serializer."""

    title_translated = serializers.SerializerMethodField(allow_null=True)
    subtitle_translated = serializers.SerializerMethodField(allow_null=True)
    news_type = NewsTypeSerializer()
    tags = TagsDocumentSerializer(many=True, source='visible_tags')
    slug = serializers.SerializerMethodField(allow_null=True)

    class Meta:
        """Meta class."""

        document = NewsDocument
        fields = (
            'id',
            'title_translated',
            'subtitle_translated',
            'is_highlighted',
            'image_url',
            'preview_image_url',
            'news_type',
            'tags',
            'start',
            'slug',
        )

    @staticmethod
    def get_slug(obj):
        return get_translated_value(loads(obj.slugs))

    @staticmethod
    def get_title_translated(obj):
        return get_translated_value(obj.title)

    @staticmethod
    def get_subtitle_translated(obj):
        return get_translated_value(obj.subtitle)


class WineOriginSerializer(serializers.Serializer):
    """Wine origin serializer."""

    wine_region = WineRegionDocumentSerializer()
    wine_sub_region = WineSubRegionDocumentSerializer(allow_null=True)


class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer):
    """Establishment document serializer."""

    type = EstablishmentTypeSerializer(source='establishment_type')
    subtypes = EstablishmentTypeSerializer(many=True, source='establishment_subtypes')
    address = AddressDocumentSerializer(allow_null=True)
    tags = TagsDocumentSerializer(many=True, source='visible_tags')
    restaurant_category = TagsDocumentSerializer(many=True, allow_null=True)
    restaurant_cuisine = TagsDocumentSerializer(many=True, allow_null=True)
    artisan_category = TagsDocumentSerializer(many=True, allow_null=True)
    schedule = ScheduleDocumentSerializer(many=True, allow_null=True)
    wine_origins = WineOriginSerializer(many=True)

    class Meta:
        """Meta class."""

        document = EstablishmentDocument
        fields = (
            'id',
            'name',
            'transliterated_name',
            'index_name',
            'price_level',
            'toque_number',
            'public_mark',
            'slug',
            'preview_image',
            'address',
            'tags',
            'restaurant_category',
            'restaurant_cuisine',
            'artisan_category',
            'schedule',
            'works_noon',
            'works_evening',
            'works_at_weekday',
            'tz',
            'wine_origins',
            # 'works_now',
            # 'collections',
            'type',
            'subtypes',
        )


class ProductDocumentSerializer(InFavoritesMixin):
    """Product document serializer"""

    tags = TagsDocumentSerializer(many=True, source='related_tags')
    subtypes = ProductSubtypeDocumentSerializer(many=True, allow_null=True)
    wine_colors = TagDocumentSerializer(many=True)
    grape_variety = TagDocumentSerializer(many=True)
    product_type = ProductTypeSerializer(allow_null=True)
    establishment_detail = ProductEstablishmentSerializer(source='establishment', allow_null=True)
    wine_origins = WineOriginSerializer(many=True)

    class Meta:
        """Meta class."""

        document = ProductDocument
        fields = (
            'id',
            'category',
            'preview_image_url',
            'name',
            'available',
            'public_mark',
            'slug',
            'old_id',
            'state',
            'old_unique_key',
            'vintage',
            'tags',
            'product_type',
            'subtypes',
            'wine_colors',
            'grape_variety',
            'average_price',
            'created',
            'wine_origins',
        )
