from datetime import datetime, timedelta

from django.db.models import Sum
from django.utils.timezone import now as timezone_now

from analytics.lib.counts import COUNT_STATS
from analytics.models import StreamCount
from zerver.models import Realm


def get_streams_traffic(realm: Realm, stream_ids: set[int] | None = None) -> dict[int, int] | None:
    stat = COUNT_STATS["messages_in_stream:is_bot:day"]
    traffic_from = timezone_now() - timedelta(days=28)

    filter_kwargs = dict(
        # The realm_id is important, as it makes this significantly better-indexed
        realm_id=realm.id,
        property=stat.property,
        end_time__gt=traffic_from,
    )
    if stream_ids is not None:
        filter_kwargs["stream_id__in"] = stream_ids

    query = StreamCount.objects.filter(**filter_kwargs)

    traffic_list = query.values("stream_id").annotate(sum_value=Sum("value"))
    traffic_dict = {}
    for traffic in traffic_list:
        traffic_dict[traffic["stream_id"]] = traffic["sum_value"]

    return traffic_dict


def round_to_2_significant_digits(number: int) -> int:
    return int(round(number, 2 - len(str(number))))


STREAM_TRAFFIC_CALCULATION_MIN_AGE_DAYS = 7


def get_average_weekly_stream_traffic(
    stream_id: int, stream_date_created: datetime, recent_traffic: dict[int, int]
) -> int | None:
    try:
        stream_traffic = recent_traffic[stream_id]
    except KeyError:
        stream_traffic = 0

    stream_age = (timezone_now() - stream_date_created).days

    if stream_age >= 28:
        average_weekly_traffic = int(stream_traffic // 4)
    elif stream_age >= STREAM_TRAFFIC_CALCULATION_MIN_AGE_DAYS:
        average_weekly_traffic = int(stream_traffic * 7 // stream_age)
    else:
        return None

    if average_weekly_traffic == 0 and stream_traffic > 0:
        average_weekly_traffic = 1

    return round_to_2_significant_digits(average_weekly_traffic)
