from django.db.models import Sum, Q
from django.http import HttpResponse

from LiveStock.models import LiveStockAllocations, Rancher, LiveStockProduct, Cooperative, LiveStockRolseProduct, \
    CooperativeProductsShare
from panel.convert_date import convert_to_miladi
from panel.models import StewardAllocation, StewardFreeBarInformation, StewardFreeSaleBarInformation, \
    PosAllocationTransactions, PosMachineTransactions, PosSegmentation, ProductsTransactions, RolesProducts, \
    WarehouseArchive


def guild_steward_free_buying_product_warehousing(product):
    guild_steward_free_buying_bars = StewardFreeBarInformation.objects.filter(
        Q(guild=product.guild) | Q(steward=product.guild), trash=False,warehouse=True)
    product.free_buying_carcasses_quantity = \
        guild_steward_free_buying_bars.aggregate(total=Sum('number_of_carcasses'))[
            'total'] or 0
    product.free_buying_carcasses_weight = \
        guild_steward_free_buying_bars.aggregate(total=Sum('weight_of_carcasses'))[
            'total'] or 0
    product.save()
    product.guild.total_out_province_buying_bars_weight = product.free_buying_carcasses_weight
    product.guild.save()


def guild_steward_free_sale_product_warehousing(product):
    guild_steward_free_sale_bars = StewardFreeSaleBarInformation.objects.filter(
        Q(guild=product.guild) | Q(steward=product.guild), trash=False,warehouse=True)

    product.out_province_allocated_quantity = guild_steward_free_sale_bars.aggregate(total=Sum('number_of_carcasses'))[
                                                  'total'] or 0
    product.out_province_allocated_weight = guild_steward_free_sale_bars.aggregate(total=Sum('weight_of_carcasses'))[
                                                'total'] or 0
    out_province_governmental_allocated_weight = guild_steward_free_sale_bars.filter(quota='governmental').aggregate(total=Sum('weight_of_carcasses'))[
                                                'total'] or 0
    out_province_free_allocated_weight = guild_steward_free_sale_bars.filter(quota='free').aggregate(total=Sum('weight_of_carcasses'))[
                                                'total'] or 0

    product.save()
    product.guild.total_selling_out_province_governmental_weight=out_province_governmental_allocated_weight
    product.guild.total_selling_out_province_free_weight = out_province_free_allocated_weight
    product.guild.save()


def guild_steward_allocations_product_warehousing(product):
    guild_steward_allocations = StewardAllocation.objects.filter(
        Q(guilds=product.guild) | Q(to_guilds=product.guild) | Q(steward=product.guild) | Q(to_steward=product.guild),
        trash=False, calculate_status=True,warehouse=True,steward_warehouse=True)

    guild_steward_allocated = guild_steward_allocations.filter(Q(guilds=product.guild) | Q(steward=product.guild))
    guild_steward_allocated_from = guild_steward_allocations.filter(
        Q(to_guilds=product.guild) | Q(to_steward=product.guild))

    governmental_guild_steward_allocated_from = guild_steward_allocated_from.filter(quota='governmental')
    free_guild_steward_allocated_from = guild_steward_allocated_from.filter(quota='free')

    product.province_allocated_quantity = \
        guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate(
            total=Sum('real_number_of_carcasses'))[
            'total'] or 0
    product.province_allocated_weight = \
        guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate(
            total=Sum('real_weight_of_carcasses'))[
            'total'] or 0

    in_province_governmental_allocated_weight = \
        guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted'),quota='governmental').aggregate(
            total=Sum('real_weight_of_carcasses'))[
            'total'] or 0

    in_province_free_allocated_weight = \
        guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted'),quota='free').aggregate(
            total=Sum('real_weight_of_carcasses'))[
            'total'] or 0

    product.receive_governmental_carcasses_quantity = \
        governmental_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate(
            total=Sum('receiver_real_number_of_carcasses'))[
            'total'] or 0
    product.receive_governmental_carcasses_weight = \
        governmental_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate(
            total=Sum('receiver_real_weight_of_carcasses'))[
            'total'] or 0
    product.receive_free_carcasses_quantity = \
        free_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate(
            total=Sum('receiver_real_number_of_carcasses'))[
            'total'] or 0
    product.receive_free_carcasses_weight = \
        free_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate(
            total=Sum('receiver_real_weight_of_carcasses'))[
            'total'] or 0

    product.save()
    product.guild.total_in_province_governmental_bars_weight = product.receive_governmental_carcasses_weight
    product.guild.total_in_province_free_bars_weight = product.receive_free_carcasses_weight
    product.guild.total_selling_in_province_governmental_weight = in_province_governmental_allocated_weight
    product.guild.total_selling_in_province_free_weight = in_province_free_allocated_weight
    product.guild.save()


def allocation_calculate_price(allocation):
    transactions = PosAllocationTransactions.objects.filter(allocation=allocation, trash=False, paid=True)
    allocation.total_amount_paid = transactions.aggregate(total=Sum('price'))['total'] or 0
    allocation.save()


def pos_allocation_weight_for_product(product):
    transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False,warehouse=True)
    product.pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0
    product.save()
    pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0
    pos_governmental_allocated_weight = transactions.filter(price_approved=True).aggregate(total=Sum('cur_weight'))['total'] or 0
    pos_free_allocated_weight = transactions.filter(price_approved=False).aggregate(total=Sum('cur_weight'))['total'] or 0
    if product.kill_house:
        product.kill_house.pos_allocated_weight=int(pos_allocated_weight/1000)
        product.kill_house.pos_governmental_allocated_weight=int(pos_governmental_allocated_weight/1000)
        product.kill_house.pos_free_allocated_weight=int(pos_free_allocated_weight/1000)
        product.kill_house.save()
    else:
        product.guild.pos_allocated_weight=int(pos_allocated_weight/1000)
        product.guild.pos_governmental_allocated_weight=int(pos_governmental_allocated_weight/1000)
        product.guild.pos_free_allocated_weight=int(pos_free_allocated_weight/1000)
        product.guild.save()



def guild_steward_product_segmentation(product):
    if product.kill_house:
        segmentations = PosSegmentation.objects.filter(kill_house=product.kill_house, trash=False,warehouse=True)
    else:

        segmentations = PosSegmentation.objects.filter(guild=product.guild, trash=False,warehouse=True)
    product.segmentation_weight = \
        segmentations.aggregate(total=Sum('weight'))[
            'total'] or 0
    product.save()
    if product.kill_house:
        product.kill_house.total_segmentation_governmental_weight = segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[
            'total'] or 0
        product.kill_house.total_segmentation_free_weight = segmentations.filter(quota='free').aggregate(total=Sum('weight'))[
            'total'] or 0
        product.kill_house.save()
    else:
        product.guild.total_segmentation_governmental_weight = segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[
            'total'] or 0
        product.guild.total_segmentation_free_weight = segmentations.filter(quota='free').aggregate(total=Sum('weight'))[
            'total'] or 0
        product.guild.save()



def guild_steward_archive_warehousing(guild):
    product = RolesProducts.objects.filter(guild=guild, trash=False, name='مرغ گرم').first()

    archives = WarehouseArchive.objects.filter(Q(steward=guild)|Q(guild=guild),trash=False,warehouse=True)

    archives_info = archives.aggregate(
        archives_weight=Sum('weight'),
        archives_governmental_weight=Sum('weight',
                                         filter=Q(quota='governmental')),
        archives_free_weight=Sum('weight',
                                 filter=Q(quota='free')),

    )
    archives_weight = archives_info['archives_weight'] or 0
    archives_governmental_weight = archives_info['archives_governmental_weight'] or 0
    archives_free_weight = archives_info['archives_free_weight'] or 0
    product.ware_house_archive_weight = archives_weight
    product.save()
    guild.ware_house_archive_governmental_weight = archives_governmental_weight
    guild.ware_house_archive_free_weight = archives_free_weight
    guild.save()



def cooperative_warehousing(product):
    transactions = ProductsTransactions.objects.filter(live_stack_products=product, transaction__paid=True, trash=False)
    output_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0
    product.total_allocated_weight = output_weight
    product.save()


def rancher_warehousing(transaction):
    # todo:دامدار با کد ملی چند تا بر گپمیرگرده باید بر اساس شناسه گله بشه
    rancher = Rancher.objects.filter(national_id=transaction.natcode).order_by('herd_code').first()
    if rancher:
        transactions = ProductsTransactions.objects.filter(transaction=transaction, transaction__paid=True, trash=False)
        output_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0
        rancher.total_weight = output_weight
        rancher.save()


def update_role_product(request):
    products=LiveStockProduct.objects.filter(trash=False).exclude(name__in=('جو','سویا','ذرت','سبوس'))
    cooperative=Cooperative.objects.filter(trash=False)
    for c in cooperative:
        for p in products:
            live=LiveStockRolseProduct(
                parent_product=p,
                cooperative=c,
            )
            live.save()
    return HttpResponse('ok')


def update_cooperative_share(request):
    products=LiveStockProduct.objects.filter(trash=False).exclude(name__in=('جو','سویا','ذرت','سبوس'))
    cooperative=Cooperative.objects.filter(trash=False)
    for c in cooperative:
        for p in products:
            live=CooperativeProductsShare(
                product=p,
                cooperative=c,
            )
            live.save()
    return HttpResponse('ok')


def calculate_bad_transactions():
    transactions = PosMachineTransactions.objects.filter(trash=False, paid=False, live_stock=True, result='تراکنش موفق',
                                                         state=0)
    for transaction in transactions:
        product_transaction = ProductsTransactions.objects.filter(transaction=transaction,
                                                                  trash=False,
                                                                  live_stack_products__isnull=False).first()
        if product_transaction:
            cooperative_warehousing(product_transaction.live_stack_products)
            rancher_warehousing(transaction)
            transaction.paid = True
            transaction.save()




def _normalize_fa_ar(text):
    """نرمالایز کردن متن فارسی/عربی"""
    if not text:
        return text
    mapping = {
        'ك': 'ک',
        'ي': 'ی',
        'ى': 'ی',
        '\u0649': 'ی',
        '\u06CC': 'ی',
        '\u064A': 'ی',
        'ۀ': 'ه',
        'ة': 'ه',
        'ؤ': 'و',
        'أ': 'ا',
        'إ': 'ا',
        'ٱ': 'ا',
        '\u200c': ' ',
    }
    out = str(text)
    for src, dst in mapping.items():
        out = out.replace(src, dst)
    return out.strip()

def parse_yes_no(val):
    """تبدیل مقدار به boolean"""
    if isinstance(val, bool):
        return val
    if isinstance(val, str):
        return False if val == 'خیر' else True
    return bool(val)

def persian_date_to_datetime(persian_date_str):
    """تبدیل تاریخ فارسی به datetime"""
    if not persian_date_str:
        return None
    try:
        persian_numbers = '۰۱۲۳۴۵۶۷۸۹'
        english_numbers = '0123456789'
        translation_table = str.maketrans(persian_numbers, english_numbers)
        english_date = persian_date_str.translate(translation_table)
        parts = english_date.split('/')
        if len(parts) != 3:
            return None
        year = int(parts[0])
        month = int(parts[1])
        day = int(parts[2])
        return convert_to_miladi(year=year, month=month, day=day)
    except:
        return None