import datetime
from collections import defaultdict
from datetime import timedelta

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

from authentication.sahandsms.sms import kill_house_price
from panel.models import PoultryRequest, PoultryHatching, KillHouseRequest, ProvinceKillRequest, \
    HatchingIncreaseRequest, ChickenCommissionPrices, KillRequest, PoultryRequestQuarantineCode, MarketDailyLimitation


def poultry_prediction(poultry):
    total_quantity = 0
    total_weight = 0
    total_count = 0
    killing_ave_weight = 0

    hatchings = PoultryHatching.objects.filter(poultry=poultry, trash=False, state='pending',
                                               archive=False, temporary_trash=False,
                                               temporary_deleted=False)

    poultry_requests = PoultryRequest.objects.filter(poultry=poultry, trash=False,
                                                     state_process__in=('pending', 'accepted'),
                                                     province_state__in=('pending', 'accepted'),
                                                     out_province_request_cancel=False, killing_age__gt=30,
                                                     killing_age__lte=70, temporary_trash=False,
                                                     temporary_deleted=False)
    sum_killing_ages = poultry_requests.aggregate(total=Sum('killing_age'))[
                           'total'] or 0
    ave_killing_age = int(sum_killing_ages / len(poultry_requests)) if len(poultry_requests) > 0 else 1
    if hatchings:
        for hatching in hatchings:
            if hatching.now_age <= ave_killing_age:
                difference = ave_killing_age - hatching.now_age
                predicate_date = datetime.datetime.now().date() + timedelta(days=difference)
                hatching.predicate_date = predicate_date
                hatching.save()
    poultry.killing_ave_age = ave_killing_age

    province_kill_requests = ProvinceKillRequest.objects.filter(trash=False,
                                                                province_request__poultry_request__poultry=poultry,
                                                                state__in=('pending', 'accepted'),
                                                                return_to_province=False, first_car_allocated_quantity=0
                                                                , temporary_trash=False,
                                                                temporary_deleted=False)

    sum_province_kill_requests_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[
                                              'total'] or 0
    sum_kill_province_kill_requests_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[
                                                 'total'] or 0
    kill_house_requests = KillHouseRequest.objects.filter(trash=False,
                                                          province_request__poultry_request__poultry=poultry,
                                                          temporary_trash=False,
                                                          temporary_deleted=False)
    sum_kill_house_requests_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[
                                           'total'] or 0
    sum_kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[
                                         'total'] or 0
    loss_percent = kill_house_requests.aggregate(total=Sum('weight_loss'))[
                       'total'] or 0
    ave_loss_percent = round(loss_percent / len(kill_house_requests), 2) if len(kill_house_requests) > 0 else 0
    total_quantity = sum_province_kill_requests_quantity + sum_kill_house_requests_quantity
    total_weight = sum_kill_province_kill_requests_weight + sum_kill_house_requests_weight
    total_count = len(province_kill_requests) + len(kill_house_requests)
    killing_ave_count = total_quantity / total_count if total_count > 0 else 0
    killing_ave_weight = round(total_weight / total_quantity, 2) if total_quantity > 0 else 0

    poultry.killing_ave_count = killing_ave_count
    poultry.real_killing_ave_weight = killing_ave_weight
    poultry.real_killing_loss_weight_percent = ave_loss_percent
    poultry.save()


def poultry_prediction_helper(ave_killing_age, consumption_limit_type, date1=None, date2=None):
    # دریافت جوجه‌ریزی‌ها
    hatchings = PoultryHatching.objects.filter(
        trash=False, state='pending', archive=False, now_age__lte=ave_killing_age
    ).order_by('date').select_related('poultry').only('poultry', 'left_over', 'now_age')

    grouped_data = defaultdict(lambda: {
        "quantity": 0,
        "weight": 0,
        "poultry_count": 0,
        "poultry_ids": set(),
        "hatching_ids": set(),
    })

    for hatching in hatchings:
        if hatching.now_age <= ave_killing_age:
            if date1:
                target_date = (
                        datetime.datetime.now().date() + timedelta(days=ave_killing_age - hatching.now_age)).isoformat()
                obj_date = datetime.datetime.strptime(target_date, '%Y-%m-%d').date()
                if obj_date > date2 or obj_date < date1:
                    continue
            else:
                target_date = (
                        datetime.datetime.now().date() + timedelta(days=ave_killing_age - hatching.now_age)).isoformat()
            grouped_data[target_date]["quantity"] += hatching.left_over
            grouped_data[target_date]["weight"] += int(
                hatching.left_over * hatching.poultry.real_killing_ave_weight) if consumption_limit_type in (
                'quantity', 'live_weight') else int(
                (hatching.left_over * hatching.poultry.real_killing_ave_weight) * 0.75)
            grouped_data[target_date]["hatching_ids"].add(hatching.id)
            grouped_data[target_date]["poultry_ids"].add(hatching.poultry.id)
            grouped_data[target_date]["poultry_count"] = len(grouped_data[target_date]["poultry_ids"])

    result = [
        {
            "age": ave_killing_age,
            "poultry": data['poultry_count'],
            "quantity": data["quantity"],
            "weight": data["weight"],
            "hatchings": data["hatching_ids"],
            "date": date
        }
        for date, data in grouped_data.items()
    ]

    return result


def calculate_hatching_increase(hatching):
    hatching_increase = HatchingIncreaseRequest.objects.filter(trash=False, hatching=hatching)
    quantity = hatching_increase.aggregate(total=Sum('quantity'))[
                   'total'] or 0
    hatching.increase_quantity = quantity
    hatching.save()


def create_update_chicken_commission_prices():
    now = datetime.datetime.now().date()
    chicken_commission = ChickenCommissionPrices.objects.get_or_create(date__date=now,
                                                                       defaults={'date': datetime.datetime.now(),
                                                                                 'kill_house_price': kill_house_price})[
        0]
    # poultry_request
    poultry_request = PoultryRequest.objects.filter(trash=False, send_date__date=now,
                                                    state_process__in=('pending', 'accepted'),
                                                    province_state__in=('pending', 'accepted'), out=False,
                                                    amount__gt=0).only(
        'amount')
    poultry_request_amount = poultry_request.aggregate(total=Sum('amount'))[
                                 'total'] or 0
    # ProvinceKillRequest
    province_kill_req = ProvinceKillRequest.objects.filter(trash=False, kill_request__recive_date__date=now,
                                                           state__in=('pending', 'accepted'),
                                                           kill_house_price__gt=0).only(
        'kill_house_price')

    province_kill_req_kill_house_price = province_kill_req.aggregate(total=Sum('kill_house_price'))[
                                             'total'] or 0

    # KillRequest
    kill_req = KillRequest.objects.filter(trash=False, recive_date__date=now, province_state__in=('accepted', 'pending')
                                          , poultry__isnull=False,
                                          direct_buying_state__in=('accepted', 'pending'), amount__gt=0).only(
        'amount')
    kill_req_amount = kill_req.aggregate(total=Sum('amount'))[
                          'total'] or 0

    kill_request_amount = round(
        kill_req_amount / kill_req.count()) if kill_req.count() > 0 else 0

    province_kill_request_amount = round(province_kill_req_kill_house_price / province_kill_req.count()) \
        if province_kill_req.count() > 0 else 0

    poultry_req_amount = round(poultry_request_amount / poultry_request.count()) if poultry_request.count() > 0 \
        else 0

    amount = round(
        kill_req_amount + province_kill_req_kill_house_price + poultry_request_amount)

    counts = poultry_request.count() + province_kill_req.count() + kill_req.count()

    chicken_commission.chicken_average_price = round(amount / counts) if counts > 0 else 0
    chicken_commission.kill_request_amount = kill_request_amount
    chicken_commission.province_kill_request_amount = province_kill_request_amount
    chicken_commission.poultry_request_amount = poultry_req_amount

    chicken_commission.save()


def create_update_chicken_commission_prices_manual(request):
    now = datetime.datetime.now().date()
    for day in range(7):
        past_date = now - timedelta(days=day)
        past_datetime = datetime.datetime.combine(past_date, datetime.time.min)

        chicken_commission = ChickenCommissionPrices.objects.get_or_create(date__date=past_date,
                                                                           defaults={'date': past_datetime,
                                                                                     'kill_house_price': kill_house_price})[
            0]
        # # poultry_request
        poultry_request = PoultryRequest.objects.filter(trash=False, send_date__date=past_date,
                                                        state_process__in=('pending', 'accepted'),
                                                        province_state__in=('pending', 'accepted'), out=False,
                                                        amount__gt=0).only(
            'amount')
        print(len(poultry_request))
        poultry_request_amount = poultry_request.aggregate(total=Sum('amount'))[
                                     'total'] or 0
        # ProvinceKillRequest
        province_kill_req = ProvinceKillRequest.objects.filter(trash=False, kill_request__recive_date__date=past_date,
                                                               state__in=('pending', 'accepted'),
                                                               kill_house_price__gt=0).only(
            'kill_house_price')

        province_kill_req_kill_house_price = province_kill_req.aggregate(total=Sum('kill_house_price'))[
                                                 'total'] or 0

        # KillRequest
        kill_req = KillRequest.objects.filter(trash=False, recive_date__date=past_date,
                                              province_state__in=('accepted', 'pending')
                                              , poultry__isnull=False,
                                              direct_buying_state__in=('accepted', 'pending'), amount__gt=0).only(
            'amount')
        kill_req_amount = kill_req.aggregate(total=Sum('amount'))[
                              'total'] or 0

        kill_request_amount = round(
            kill_req_amount / kill_req.count()) if kill_req.count() > 0 else 0

        province_kill_request_amount = round(province_kill_req_kill_house_price / province_kill_req.count()) \
            if province_kill_req.count() > 0 else 0

        poultry_req_amount = round(poultry_request_amount / poultry_request.count()) if poultry_request.count() > 0 \
            else 0

        amount = round(
            kill_req_amount + province_kill_req_kill_house_price + poultry_request_amount)

        counts = poultry_request.count() + province_kill_req.count() + kill_req.count()

        chicken_commission.chicken_average_price = round(amount / counts) if counts > 0 else 0
        chicken_commission.kill_request_amount = kill_request_amount
        chicken_commission.province_kill_request_amount = province_kill_request_amount
        chicken_commission.poultry_request_amount = poultry_req_amount

        chicken_commission.save()


def add_poultry_request_quarantine_code(request):
    poultry_requests = PoultryRequest.objects.filter(
        trash=False,
        quarantine_code__isnull=False,
        state_process__in=('pending', 'accepted'),
        province_state__in=('pending', 'accepted')
    ).only('id', 'quarantine_code', 'quarantine_quantity')

    codes = [
        PoultryRequestQuarantineCode(
            poultry_request=poultry_request,
            quarantine_code=poultry_request.quarantine_code,
            system_quarantine_quantity=poultry_request.quarantine_quantity,
            quarantine_quantity=poultry_request.quarantine_quantity,
        )
        for poultry_request in poultry_requests
    ]

    PoultryRequestQuarantineCode.objects.bulk_create(codes)

    return HttpResponse('ok')


def update_archive_date_poultry_hatching(request):
    poultry_hatchings = PoultryHatching.objects.filter(Q(allow_hatching='True', state='complete') | Q(archive=True),
                                                       trash=False,
                                                       )
    for p in poultry_hatchings:
        p.archive_date = p.date + timedelta(p.chicken_age)
        p.save()
    return HttpResponse('ok')


def market_daily_limitation_info():
    limitation_quantity = 0
    market_request_quantity = 0
    limitation = MarketDailyLimitation.objects.filter().first()
    if limitation:
        limitation_quantity = limitation.quantity

    poultry_Requests = PoultryRequest.objects.filter(
        state_process__in=('pending', 'accepted'),
        province_state__in=('pending', 'accepted'),
        temporary_trash=False,
        trash=False,
        out=False,
        send_date__date=datetime.datetime.now().date(),
        final_state='pending',
        market=True
    ).aggregate(
        total_quantity=Sum('quantity')
    )
    market_request_quantity = poultry_Requests['total_quantity'] or 0

    result = {
        "max_limitation_quantity": limitation_quantity,
        "market_request_quantity": market_request_quantity,
        "remain_quantity" : limitation_quantity - market_request_quantity if (limitation_quantity -  market_request_quantity) else 0

    }
    return result
