from datetime import timedelta
from itertools import islice

from django.conf import settings
from django.db.models import Exists, OuterRef
from django.utils import timezone

from shop.models import Cart, ProductView, SKU


CART = "CART"
VIEW = "VIEW"
NEVER = "NEVER"
PRIORITIES = (CART, VIEW, NEVER)


def recent_view_threshold():
    return timezone.now() - timedelta(
        seconds=settings.SKU_SYNC_VIEW_ACTIVE_SECONDS
    )


def determine_sku_priority(sku):
    if Cart.objects.filter(skuId_id=sku.pk).exists():
        return CART
    if ProductView.objects.filter(
        productId_id=sku.productId_id,
        viewedDate__gte=recent_view_threshold(),
    ).exists():
        return VIEW
    return NEVER


def eligible_sku_ids(priority):
    if priority not in PRIORITIES:
        raise ValueError(f"Unknown SKU priority: {priority}")

    cart_exists = Cart.objects.filter(skuId_id=OuterRef("pk"))
    recent_view_exists = ProductView.objects.filter(
        productId_id=OuterRef("productId_id"),
        viewedDate__gte=recent_view_threshold(),
    )
    queryset = SKU.objects.annotate(
        is_in_cart=Exists(cart_exists),
        has_recent_view=Exists(recent_view_exists),
    )

    if priority == CART:
        queryset = queryset.filter(is_in_cart=True)
    elif priority == VIEW:
        queryset = queryset.filter(is_in_cart=False, has_recent_view=True)
    else:
        queryset = queryset.filter(is_in_cart=False, has_recent_view=False)

    return queryset.order_by("pk").values_list("pk", flat=True)


def chunks(values, chunk_size=None):
    size = chunk_size or settings.SKU_SYNC_CHUNK_SIZE
    iterator = iter(values)
    while True:
        chunk = list(islice(iterator, size))
        if not chunk:
            return
        yield chunk

