from apps.authentication.api.v1.serializers.serializer import (
    UserSerializer,
    OrganizationSerializer,
    ProvinceSerializer,
    CitySerializer
)
from apps.herd.exception import UniqueRancherApiException
from apps.livestock import models as livestock_models
from rest_framework import serializers
from apps.herd.models import Herd, Rancher
from django.db.transaction import atomic


class HerdSerializer(serializers.ModelSerializer):
    """ Herd Serializer """

    class Meta:
        model = Herd
        fields = '__all__'

    def to_representation(self, instance):
        """ Customize serializer output """
        representation = super().to_representation(instance)
        if isinstance(instance, Herd):
            if instance.owner:
                representation['owner'] = instance.owner.id
            representation['cooperative'] = OrganizationSerializer(instance.cooperative).data
            representation['province'] = ProvinceSerializer(instance.province).data
            representation['city'] = CitySerializer(instance.city).data
            if instance.contractor:
                representation['contractor'] = OrganizationSerializer(instance.contractor).data
            representation['rancher'] = RancherSerializer(instance.rancher).data

        return representation


class RancherSerializer(serializers.ModelSerializer):
    class Meta:
        model = Rancher
        fields = '__all__'

    def create(self, validated_data):
        """ create rancher in pos device (without herd) """
        data = self.context['request'].data.copy()

        with atomic():
            rancher = Rancher.objects.create(**validated_data)  # create rancher
            if 'livestock' in data.keys():
                live_stocks = data['livestock']
                livestock_types = {stock.id: stock for stock in livestock_models.LiveStockType.objects.all()}

                for stock in live_stocks:
                    livestock_models.TemporaryLiveStock.objects.create(
                        livestock_type=livestock_types.get(stock.pop('livestock_type')),
                        rancher=rancher,
                        **stock
                    )

            return rancher

    def validate(self, attrs):
        """ some validations for operations relate to rancher """

        if self.Meta.model.objects.filter(national_code=attrs['national_code']).exists():
            raise UniqueRancherApiException()

        return attrs

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

        representation = super().to_representation(instance)

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

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

        return representation
