from django.db import models
from django.db.models import functions as db_functions

from ocyan.plugin.oscar_partner.partner import mixins as ocyan


class UseCheapestChildProductStockRecord(ocyan.UseCheapestChildProductStockRecord):
    def get_product_stockrecords_queryset(self, product):
        return product.stockrecords.filter(
            price_currency__isnull=False, price__isnull=False
        )

    def get_product_children_queryset(self, product):
        return product.variants_ordered_by_price.filter(
            is_public=True,
            stockrecords__price_currency__isnull=False,
            stockrecords__price__isnull=False,
        )

    def select_stockrecord(self, product):
        pc = product.get_product_class()
        if pc.track_stock:
            return (
                self.get_product_stockrecords_queryset(product)
                .annotate(
                    db_effective_stock=db_functions.Coalesce(
                        "num_in_stock", models.Value(0)
                    )
                    - db_functions.Coalesce("num_allocated", models.Value(0))
                )
                .annotate(
                    has_stock=models.Case(
                        models.When(db_effective_stock__gt=0, then=models.Value(True)),
                        default=models.Value(False),
                        output_field=models.BooleanField(),
                    )
                )
                .order_by("-has_stock", "price", "-db_effective_stock")
            ).first()
        else:
            return self.get_product_stockrecords_queryset(product).first()
