from rest_framework import serializers

from apps.authentication.api.v1.serializers.serializer import (
    OrganizationSerializer,
    ProvinceSerializer,
    CitySerializer
)
from apps.herd.exception import HerdCapacityException, HerdException
from apps.herd.models import Herd, Rancher, RancherOrganizationLink


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

    class Meta:
        model = Herd
        fields = '__all__'

    def validate(self, attrs):
        """ some validations for herd """

        if attrs['heavy_livestock_number'] + attrs['light_livestock_number'] > attrs['capacity']:
            raise HerdCapacityException()

        return attrs

    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 to_representation(self, instance):
        """ customize output of serializer """

        representation = super().to_representation(instance)

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

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

        representation['organizations'] = [
            {'id': item.organization.id, 'name': item.organization.name}
            for item in instance.organization_links.all()
        ]

        return representation


class RancherOrganizationLinkSerializer(serializers.ModelSerializer):
    class Meta:
        model = RancherOrganizationLink
        fields = '__all__'

    def validate(self, attrs):
        rancher = attrs['rancher']
        organization = attrs['organization']

        if not self.instance:
            if self.Meta.model.objects.filter(rancher=rancher, organization=organization).exists():
                raise HerdException(message="دامدار برای تعاونی مد نظر از قبل وجود دارد", status_code=403)  # noqa

            elif self.Meta.model.objects.filter(
                    rancher=rancher,
                    organization__parent_organization=organization.parent_organization
            ).exists():
                raise HerdException(
                    message="دامدار نمیتواند زیر مجموعه دو تعاونی با اتحادیه یکسان باشند",  # noqa
                    status_code=403
                )

        if self.instance:
            if rancher.city not in organization.service_area.all():
                raise HerdException(message="دامدار در محدوده فعالیت تعاونی قرار ندارد", status_code=403)  # noqa

            elif self.instance.organization == organization:
                raise HerdException(message="دامدار برای تعاونی مد نظر از قبل وجود دارد", status_code=403)  # noqa

            elif self.instance.organization.parent_organization == organization.parent_organization:
                raise HerdException(
                    message="دامدار نمیتواند زیر مجموعه دو تعاونی با اتحادیه یکسان باشند",  # noqa
                    status_code=403
                )

        return attrs

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

        if instance.rancher:
            representation['rancher'] = RancherSerializer(instance.rancher).data

        if instance.organization:
            representation['organization'] = {
                "id": instance.organization.id,
                "name": instance.organization.name,
                "province": instance.organization.province.name,
                "city": instance.organization.city.name
            }

        return representation
