from decimal import Decimal
from apps.herd.models import Rancher
from apps.livestock.models import LiveStock
from apps.warehouse.models import InventoryEntry
from apps.product.models import Quota, QuotaDistribution
from django.db.models import Count, Q
import typing


def get_rancher_statistics(rancher: Rancher = None) -> typing.Any:
    """ get statistics of a rancher """  # noqa

    livestocks = LiveStock.objects.filter(herd__rancher=rancher)  # noqa

    stats = livestocks.aggregate(
        herd_count=Count("herd", distinct=True),
        light_count=Count('id', filter=Q(weight_type='L')),
        heavy_count=Count('id', filter=Q(weight_type='H')),
        sheep_count=Count('id', filter=Q(type__name='گوسفند')),  # noqa
        goat_count=Count('id', filter=Q(type__name='بز')),
        cow_count=Count('id', filter=Q(type__name='گاو')),
        camel_count=Count('id', filter=Q(type__name='شتر')),
        horse_count=Count('id', filter=Q(type__name='بز')),
    )

    return stats


def rancher_quota_weight(rancher, inventory_entry: InventoryEntry = None, distribution: QuotaDistribution = None):
    """
    :param rancher: Rancher instance
    :param inventory_entry: InventoryEntry instance
    :param distribution: QuotaDistribution instance
    :return: dict {total, by_type}
    """

    live_stock_meta = {
        "گوسفند": "sheep_count",  # noqa
        "بز": "goat_count",
        "گاو": "cow_count",
        "شتر": "camel_count",
        "اسب": "horse_count"
    }

    if inventory_entry:
        quota: Quota = inventory_entry.distribution.quota
    elif distribution:
        quota: Quota = distribution.quota
    else:
        quota: Quota = Quota()

    # list of quota live stock allocations
    allocations = list(quota.livestock_allocations.all().select_related('livestock_type'))
    # list of quota incentive plans
    incentive_plans = list(quota.incentive_assignments.all().select_related('livestock_type'))

    livestock_counts = get_rancher_statistics(rancher)

    total_weight = 0
    merged = {}

    for item in allocations + incentive_plans:  # noqa
        if item.livestock_type:
            animal_type = item.livestock_type.name
            per_head = item.quantity_kg
            count = livestock_counts.get(live_stock_meta.get(animal_type), 0)

            weight = per_head * count
            total_weight += weight

            if animal_type not in merged:
                merged[animal_type] = {
                    "weight": weight,
                    "type": item.livestock_type.weight_type
                }
            else:
                merged[animal_type]['weight'] += weight

    return {
        "total_weight": total_weight,
        "by_type": [{
            "name": key,
            "weight": value['weight'],
            "type": value['type']
    }for key, value in merged.items()]
    }
