import random

from django.db import transaction

from apps.authentication.models import Organization
from apps.tag.exceptions import TagException
from apps.tag.models import Tag, TagBatch, TagDistribution, TagDistributionBatch
from common.generics import generate_unique_code


class TagDistributionService:
    """
    service of distribute tags in organizations
    """

    def create_distribution(self, org: Organization = None, data: dict = None):
        """
        distribute tags with batch
        """
        with transaction.atomic():
            distributions = []
            total_counted_tags = 0
            assigned_org = Organization.objects.get(id=data.get('assigned_org'))

            for distribution in data.get('dists'):
                batch_identity = distribution.get('batch_identity', None)
                # if batch identity exists distribute tags of batch
                if batch_identity:
                    batch = TagBatch.objects.get(batch_identity=batch_identity)
                    tags = Tag.objects.filter(
                        batches__batch_identity=batch_identity,
                        species_code=distribution.get('species_code'),
                        status='F'
                    )
                    distribution_type = 'batch'
                else:
                    batch = None
                    # get tags without batch and only with species code
                    tags = Tag.objects.filter(
                        species_code=distribution.get('species_code'),
                        status='F'
                    )
                    distribution_type = 'random'

                if tags.count() < distribution.get('count'):
                    raise TagException(
                        "تعداد وارد شده از تعداد موجودی این گونه بیشتر میباشد.",  # noqa
                        403
                    )

                dist = TagDistribution.objects.create(
                    batch=batch,
                    assigner_org=org,
                    assigned_org=assigned_org,
                    species_code=distribution.get('species_code'),
                    distributed_number=distribution.get('count'),
                    dist_identity=generate_unique_code(f"{random.randint(1000, 9999)}"),
                )

                #  get counted tag ids and filter by them to update status To Reserve
                counted_tags_obj = tags.order_by('create_date')[:int(distribution.get('count'))]
                counted_tag_ids = [tag.id for tag in counted_tags_obj]
                tags.filter(id__in=counted_tag_ids).update(status='R')

                dist.tag.add(*counted_tags_obj)
                distributions.append(dist)

                total_counted_tags += distribution.get('count')

            # create distribution batch
            distributions_batch = TagDistributionBatch.objects.create(
                assigner_org=org,
                assigned_org=assigned_org,
                total_tag_count=total_counted_tags,
                dist_batch_identity=generate_unique_code(f"{random.randint(1000, 9999)}"),
                distribution_type=distribution_type,
            )
            distributions_batch.distributions.add(*distributions)

        return {'tag_distributions': distributions, 'distributions_batch': distributions_batch}

    def edit_distribution(self):
        """
        edit record of distributed tags
        """
        pass
