from django.db import transaction
from rest_framework import status

from apps.product.models import QuotaDistribution, OrganizationQuotaStats
from apps.warehouse.exceptions import WareHouseException
from apps.warehouse.models import InventoryEntry, InventoryEntryAllocation


class WarehouseAllocationService:

    @staticmethod
    def allocate(entry: InventoryEntry):
        """
        Auto allocate entry.total_weight between multiple distributions
        """
        with transaction.atomic():
            distributions = QuotaDistribution.objects.filter(
                assigned_organization=entry.organization,
                quota=entry.quota
            ).select_related('quota').order_by('-create_date')

            if not distributions.exists():
                raise WareHouseException("توزیعی برای این انبار وجود ندارد", status.HTTP_403_FORBIDDEN)  # noqa

            remaining = entry.weight
            for dist in distributions:
                if remaining <= 0:
                    break
                stat = OrganizationQuotaStats.objects.get(
                    quota=dist.quota,
                    organization=dist.assigned_organization
                )
                capacity = stat.remaining_amount
                if capacity <= 0:
                    continue

                allocate_weight = min(remaining, capacity)

                InventoryEntryAllocation.objects.create(
                    distribution=dist,
                    inventory_entry=entry,
                    weight=allocate_weight
                )

                stat.inventory_received += allocate_weight
                stat.inventory_entry_balance += allocate_weight
                stat.remaining_amount -= allocate_weight
                stat.save()

                remaining -= allocate_weight

            if remaining > 0:
                raise WareHouseException(
                    "مقدار وارد شده از انبار بیشتر از مقدار کل سهمیه توزیع داده شده است",  # noqa
                    status.HTTP_400_BAD_REQUEST
                )

            org = entry.organization.parent_organization
            parent_orgs = []
            while org:
                # import parent org to list
                parent_orgs.append(org)
                org = org.parent_organization

            parent_org_ids = [org.id for org in parent_orgs]

            target_org_ids = set(parent_org_ids)

            if entry.quota.registerer_organization.id not in target_org_ids:
                target_org_ids.add(entry.quota.registerer_organization.id)

            stats = (OrganizationQuotaStats.objects.filter(
                quota=entry.quota,
                organization__in=target_org_ids
            ))

            for stat in stats:
                stat.inventory_received += entry.weight

            OrganizationQuotaStats.objects.bulk_update(stats, ["inventory_received"])
