from rest_framework import serializers

from establishment import models
from establishment import serializers as model_serializers
from location.serializers import AddressDetailSerializer, TranslatedField
from main.models import Currency
from main.serializers import AwardSerializer
from utils.decorators import with_base_attributes
from utils.serializers import TimeZoneChoiceField
from gallery.models import Image
from django.utils.translation import gettext_lazy as _
from account.serializers.common import UserShortSerializer


class EstablishmentListCreateSerializer(model_serializers.EstablishmentBaseSerializer):
    """Establishment create serializer"""

    type_id = serializers.PrimaryKeyRelatedField(
        source='establishment_type',
        queryset=models.EstablishmentType.objects.all(),
        write_only=True
    )
    phones = model_serializers.ContactPhonesSerializer(read_only=True,
                                                       many=True, )
    emails = model_serializers.ContactEmailsSerializer(read_only=True,
                                                       many=True, )
    socials = model_serializers.SocialNetworkRelatedSerializers(read_only=True,
                                                                many=True, )
    type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type',
                                                             read_only=True)
    tz = TimeZoneChoiceField()

    class Meta:
        model = models.Establishment
        fields = [
            'id',
            'name',
            'transliterated_name',
            'index_name',
            'website',
            'phones',
            'emails',
            'price_level',
            'toque_number',
            'type_id',
            'type',
            'socials',
            'image_url',
            'slug',
            # TODO: check in admin filters
            'is_publish',
            'guestonline_id',
            'lastable_id',
            'tags',
            'tz',
        ]


class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
    """Establishment create serializer"""

    type_id = serializers.PrimaryKeyRelatedField(
        source='establishment_type',
        queryset=models.EstablishmentType.objects.all(), write_only=True
    )
    address = AddressDetailSerializer()
    phones = model_serializers.ContactPhonesSerializer(read_only=False,
                                                       many=True, )
    emails = model_serializers.ContactEmailsSerializer(read_only=False,
                                                       many=True, )
    socials = model_serializers.SocialNetworkRelatedSerializers(read_only=False,
                                                                many=True, )
    type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type')

    class Meta:
        model = models.Establishment
        fields = [
            'id',
            'name',
            'website',
            'phones',
            'emails',
            'price_level',
            'toque_number',
            'type_id',
            'type',
            'socials',
            'image_url',
            # TODO: check in admin filters
            'is_publish',
            'address',
            'tags',
        ]


class SocialChoiceSerializers(serializers.ModelSerializer):
    """SocialChoice serializers."""

    class Meta:
        model = models.SocialChoice
        fields = '__all__'


class SocialNetworkSerializers(serializers.ModelSerializer):
    """Social network serializers."""

    class Meta:
        model = models.SocialNetwork
        fields = [
            'id',
            'establishment',
            'network',
            'url',
        ]


class PlatesSerializers(model_serializers.PlateSerializer):
    """Plates serializers."""

    currency_id = serializers.PrimaryKeyRelatedField(
        source='currency',
        queryset=Currency.objects.all(), write_only=True
    )

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

        model = models.Plate
        fields = model_serializers.PlateSerializer.Meta.fields + [
            'name',
            'currency_id',
            'menu'
        ]


class ContactPhoneBackSerializers(model_serializers.PlateSerializer):
    """ContactPhone serializers."""

    class Meta:
        model = models.ContactPhone
        fields = [
            'id',
            'establishment',
            'phone'
        ]


class ContactEmailBackSerializers(model_serializers.PlateSerializer):
    """ContactEmail serializers."""

    class Meta:
        model = models.ContactEmail
        fields = [
            'id',
            'establishment',
            'email'
        ]



class PositionBackSerializer(serializers.ModelSerializer):
    """Position Back serializer."""

    name_translated = TranslatedField()

    class Meta:
        model = models.Position
        fields = [
            'id',
            'name_translated',
            'priority',
            'index_name',
        ]

# TODO: test decorator
@with_base_attributes
class EmployeeBackSerializers(serializers.ModelSerializer):
    """Employee serializers."""
    public_mark = serializers.SerializerMethodField()
    positions = serializers.SerializerMethodField()
    establishment = serializers.SerializerMethodField()
    awards = AwardSerializer(many=True, read_only=True)


    def get_public_mark(self, obj):
        """Get last list actual public_mark"""
        qs = obj.establishmentemployee_set.actual().order_by('-from_date')\
            .values('establishment__public_mark').first()
        return qs['establishment__public_mark']


    def get_positions(self, obj):
        """Get last list actual positions"""
        est_id = obj.establishmentemployee_set.actual().\
            order_by('-from_date').first().establishment_id

        qs = obj.establishmentemployee_set.actual()\
            .filter(establishment_id=est_id)\
            .prefetch_related('position').values('position')

        positions = models.Position.objects.filter(id__in=[q['position'] for q in qs])

        return [PositionBackSerializer(p).data for p in positions]

    def get_establishment(self, obj):
        """Get last actual establishment"""
        est = obj.establishmentemployee_set.actual().order_by('-from_date')\
            .first().establishment

        return {
            "id": est.id,
            "slug": est.slug
        }

    class Meta:
        model = models.Employee
        fields = [
            'id',
            'name',
            'last_name',
            'user',
            'public_mark',
            'positions',
            'awards',
            'establishment',
            'sex',
            'birth_date',
            'email',
            'phone',
            'toque_number'
        ]


class EstablishmentEmployeeBackSerializer(serializers.ModelSerializer):
    """Establishment Employee serializer."""

    employee = EmployeeBackSerializers()
    position = PositionBackSerializer()

    class Meta:
        model = models.EstablishmentEmployee
        fields = [
            'id',
            'employee',
            'from_date',
            'to_date',
            'position',
            'status',
        ]


class EstablishmentBackOfficeGallerySerializer(serializers.ModelSerializer):
    """Serializer class for model EstablishmentGallery."""

    class Meta:
        """Meta class"""

        model = models.EstablishmentGallery
        fields = [
            'id',
            'is_main',
        ]

    @property
    def request_kwargs(self):
        """Get url kwargs from request."""
        return self.context.get('request').parser_context.get('kwargs')

    def validate(self, attrs):
        """Override validate method."""
        establishment_pk = self.request_kwargs.get('pk')
        establishment_slug = self.request_kwargs.get('slug')

        search_kwargs = {'pk': establishment_pk} if establishment_pk else {'slug': establishment_slug}

        image_id = self.request_kwargs.get('image_id')

        establishment_qs = models.Establishment.objects.filter(**search_kwargs)
        image_qs = Image.objects.filter(id=image_id)

        if not establishment_qs.exists():
            raise serializers.ValidationError({'detail': _('Establishment not found')})

        if not image_qs.exists():
            raise serializers.ValidationError({'detail': _('Image not found')})

        establishment = establishment_qs.first()
        image = image_qs.first()

        if image in establishment.gallery.all():
            raise serializers.ValidationError({'detail': _('Image is already added.')})

        attrs['establishment'] = establishment
        attrs['image'] = image

        return attrs


class EstablishmentCompanyListCreateSerializer(model_serializers.CompanyBaseSerializer):
    """Serializer for linking page w/ advertisement."""

    class Meta(model_serializers.CompanyBaseSerializer.Meta):
        """Meta class."""
        model_serializers.CompanyBaseSerializer.Meta.extra_kwargs.update({
            'establishment': {'required': False}
        })

    def create(self, validated_data):
        """Overridden create method."""
        validated_data['establishment'] = self.context.get('view').get_object()
        return super().create(validated_data)


class EstablishmentNoteBaseSerializer(serializers.ModelSerializer):
    """Serializer for model EstablishmentNote."""

    user_detail = UserShortSerializer(read_only=True, source='user')

    class Meta:
        """Meta class."""
        model = models.EstablishmentNote
        fields = [
            'id',
            'created',
            'modified',
            'text',
            'user',
            'user_detail',
            'establishment',
        ]
        extra_kwargs = {
            'created': {'read_only': True},
            'modified': {'read_only': True},
            'establishment': {'required': False, 'write_only': True},
            'user': {'required': False, 'write_only': True},
        }

    @property
    def serializer_view(self):
        """Return view instance."""
        return self.context.get('view')


class EstablishmentNoteListCreateSerializer(EstablishmentNoteBaseSerializer):
    """Serializer for List|Create action for model EstablishmentNote."""

    def create(self, validated_data):
        """Overridden create method."""
        validated_data['user'] = self.user
        validated_data['establishment'] = self.establishment
        return super().create(validated_data)

    @property
    def user(self):
        """Return user instance from view."""
        if self.serializer_view:
            return self.serializer_view.request.user

    @property
    def establishment(self):
        """Return establishment instance from view."""
        if self.serializer_view:
            return self.serializer_view.get_object()


class EstablishmentAdminListSerializer(UserShortSerializer):
    """Establishment admin serializer."""
    class Meta:
        model = UserShortSerializer.Meta.model
        fields = [
            'id',
            'username',
            'email'
        ]
