from django.contrib import admin
from django.db import models
from django.db.models.functions import Coalesce
from django.utils.safestring import mark_safe

from oscar.core.loading import get_model

Category = get_model("catalogue", "Category")


class CategoryFilter(admin.SimpleListFilter):
    title = "Categories"
    parameter_name = "category"

    def lookups(self, request, model_admin):
        value = self.value()
        qs = Category.objects.get_queryset()

        depth = 1
        if value is not None:
            _category = qs.get(pk=value)
            depth = _category.depth + 1

        return [
            (cat.id, mark_safe(("&nbsp;" * cat.depth) + cat.name))
            for cat in qs.filter(depth__lte=depth)
        ]

    def queryset(self, request, queryset):
        value = self.value()
        if value is not None:
            _category = Category.objects.get(pk=value)
            categories = Category.get_tree(_category)
            return queryset.filter(categories__in=categories).distinct()
        return queryset


class ProductClassFilter(admin.SimpleListFilter):
    title = "Producttype"
    parameter_name = "product_class"

    def lookups(self, request, model_admin):
        qs = model_admin.get_queryset(request)
        return set(
            qs.annotate(
                real_product_class_id=Coalesce(
                    models.F("product_class"), models.F("parent__product_class")
                ),
                real_product_class_name=Coalesce(
                    models.F("product_class__name"),
                    models.F("parent__product_class__name"),
                ),
            ).values_list("real_product_class_id", "real_product_class_name")
        )

    def queryset(self, request, queryset):
        value = self.value()
        qs = queryset.annotate(
            real_product_class=Coalesce(
                models.F("product_class"), models.F("parent__product_class")
            )
        )
        if value is not None:
            return qs.filter(real_product_class=value)
        return queryset
