from rest_framework.serializers import ModelSerializer

from apps.authentication.api.v1.serializers.serializer import BankAccountSerializer
from apps.pos_device import exceptions as pos_exceptions
from apps.pos_device import models as pos_models
from apps.pos_device.web.api.v1.serilaizers import client as client_serializer
from apps.product.web.api.v1.serializers.quota_distribution_serializers import QuotaDistributionSerializer


class ProviderCompanySerializer(ModelSerializer):
    class Meta:
        model = pos_models.ProviderCompany
        fields = '__all__'


class DeviceSerializer(ModelSerializer):
    class Meta:
        model = pos_models.Device
        fields = '__all__'

    def to_representation(self, instance):
        """ custom output of serializer """
        representation = super().to_representation(instance)

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

        representation['assignment'] = DeviceAssignmentSerializer(
            instance.assignment.all().first()
        ).data

        return representation


class DeviceVersionSerializer(ModelSerializer):
    class Meta:
        model = pos_models.DeviceVersion
        fields = '__all__'


class SessionSerializer(ModelSerializer):
    class Meta:
        model = pos_models.Sessions
        fields = '__all__'


class DeviceAssignmentSerializer(ModelSerializer):
    class Meta:
        model = pos_models.DeviceAssignment
        fields = '__all__'

    def validate(self, attrs):

        device = attrs['device']
        client = attrs['client']

        if not self.instance:
            if self.Meta.model.objects.filter(device=device, client=client).exists():
                raise pos_exceptions.DeviceAlreadyAssigned()

        return attrs

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

        representation['client'] = client_serializer.POSClientSerializer(
            instance.client
        ).data

        return representation


class StakeHoldersSerializer(ModelSerializer):
    class Meta:
        model = pos_models.StakeHolders
        fields = '__all__'

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

        # get organization bank account that set to a device
        bank_account_device_links = instance.organization.bank_account_device_links.filter(device=instance.device)

        representation['bank_account'] = BankAccountSerializer(
            instance.organization.bank_information.all().first()
            if not bank_account_device_links.exists() else bank_account_device_links.first().bank_account
        ).data

        representation['device'] = instance.device.device_identity
        representation['device_id'] = instance.device.id

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

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

        return representation


class StakeHolderShareAmountSerializer(ModelSerializer):
    class Meta:
        model = pos_models.StakeHolderShareAmount
        fields = '__all__'

    def validate(self, attrs):
        # check organization has pos device
        assigned_organization = attrs['quota_distribution'].assigned_organization
        if not assigned_organization.has_pos:
            raise pos_exceptions.OrganizationDeviceNotAssigned()

        return attrs

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

        # distribution information
        representation['quota_distribution'] = QuotaDistributionSerializer(
            instance.quota_distribution
        ).data

        # stakeholders information
        representation['stakeholders'] = StakeHoldersSerializer(instance.stakeholders).data

        return representation


class BankAccountDeviceLinkSerializer(ModelSerializer):
    class Meta:
        model = pos_models.BankAccountDeviceLink
        fields = '__all__'
