"""Lazy SQL selection using current database state, independent of company."""
from django.db.models import Exists, OuterRef, Q

from apps.catalog.models import ProductModel, ProductVariant
from .locking import persisted_pk
from .models import PartCategory, SparePart, SparePartCompatibility


def active_part_categories():
    return PartCategory.objects.filter(is_active=True).order_by("code")


def active_spare_parts():
    return SparePart.objects.filter(is_active=True, category__is_active=True).select_related("category").order_by("part_code")


def search_spare_parts(term):
    if not isinstance(term, str):
        from django.core.exceptions import ValidationError
        raise ValidationError("Supply a text search term.")
    return active_spare_parts().filter(Q(part_code__icontains=term.strip()) | Q(name__icontains=term.strip())
        | Q(manufacturer_part_number__icontains=term.strip()))


def compatible_spare_parts_for_model(product_model):
    pk = persisted_pk(product_model, ProductModel)
    mappings = SparePartCompatibility.objects.filter(spare_part_id=OuterRef("pk"), is_active=True,
        product_model_id=pk, product_model__is_active=True,
        product_model__brand__is_active=True, product_model__category__is_active=True)
    return active_spare_parts().filter(Exists(mappings))


def compatible_spare_parts_for_variant(product_variant):
    pk = persisted_pk(product_variant, ProductVariant)
    variants = ProductVariant.objects.filter(pk=pk, is_active=True, product_model__is_active=True,
        product_model__brand__is_active=True, product_model__category__is_active=True)
    mappings = SparePartCompatibility.objects.filter(spare_part_id=OuterRef("pk"), is_active=True).filter(
        Q(product_model_id__in=variants.values("product_model_id")) | Q(product_variant_id__in=variants.values("pk")))
    return active_spare_parts().filter(Exists(mappings))


def spare_part_is_compatible_with_model(*, spare_part, product_model):
    pk = persisted_pk(spare_part, SparePart)
    return compatible_spare_parts_for_model(product_model).filter(pk=pk).exists()


def spare_part_is_compatible_with_variant(*, spare_part, product_variant):
    pk = persisted_pk(spare_part, SparePart)
    return compatible_spare_parts_for_variant(product_variant).filter(pk=pk).exists()
