import contextlib

from django.db.models import Exists
from django.db.models import OuterRef
from django.utils import timezone

from membership.models import Member
from membership.models import Membership
from membership.models import SubscriptionPeriod


def get_subscription_periods(member: Member | None = None) -> list[SubscriptionPeriod]:
    subscription_periods = SubscriptionPeriod.objects.prefetch_related(
        "membership_set",
        "membership_set__user",
    ).all()

    if member:
        subscription_periods = subscription_periods.annotate(
            membership_exists=Exists(
                Membership.objects.filter(
                    user=member,
                    period=OuterRef("pk"),
                ),
            ),
        ).filter(membership_exists=True)

    return list(subscription_periods)


def get_current_subscription_period() -> SubscriptionPeriod | None:
    with contextlib.suppress(SubscriptionPeriod.DoesNotExist):
        return SubscriptionPeriod.objects.prefetch_related(
            "membership_set",
            "membership_set__user",
        ).get(period__contains=timezone.now())


def get_memberships(
    *,
    member: Member | None = None,
    period: SubscriptionPeriod | None = None,
) -> Membership.QuerySet:
    memberships = Membership.objects.select_related("membership_type").all()

    if member:
        memberships = memberships.for_member(member=member)

    if period:
        memberships = memberships.filter(period=period)

    return memberships


def get_members():
    return Member.objects.all().annotate_membership().order_by("username")


def get_member(*, member_id: int) -> Member:
    return get_members().get(id=member_id)
