"""Catalog Engine — read-only selectors."""

from __future__ import annotations

from django.db.models import Q, QuerySet

from simorgh.apps.catalog.models import (
    CatalogCategory,
    CatalogItem,
    CatalogItemStatus,
    CatalogItemVersion,
)

# ── Categories ──────────────────────────────────────────────────────────────

def categories_for_tenant(tenant_id: int, *, catalog_type: str | None = None, active_only: bool = True) -> QuerySet:
    qs = CatalogCategory.objects.filter(tenant_id=tenant_id).select_related("parent")
    if catalog_type:
        qs = qs.filter(catalog_type=catalog_type)
    if active_only:
        qs = qs.filter(is_active=True)
    return qs.order_by("sort_order")


def category_tree(tenant_id: int, catalog_type: str | None = None) -> list[dict]:
    cats = list(
        CatalogCategory.objects.filter(tenant_id=tenant_id, is_active=True)
        .values("pk", "public_id", "name", "slug", "parent_id", "catalog_type", "icon")
        .order_by("sort_order")
    )
    if catalog_type:
        cats = [c for c in cats if c["catalog_type"] == catalog_type]
    for c in cats:
        c["public_id"] = str(c["public_id"])
    by_parent: dict[int | None, list[dict]] = {}
    for c in cats:
        by_parent.setdefault(c["parent_id"], []).append(c)
    return _build_tree(by_parent, None)


def _build_tree(by_parent: dict, parent_id: int | None) -> list[dict]:
    children = by_parent.get(parent_id, [])
    for child in children:
        child["children"] = _build_tree(by_parent, child["pk"])
    return children


def category_by_pk(tenant_id: int, pk: int) -> CatalogCategory:
    return CatalogCategory.objects.get(tenant_id=tenant_id, pk=pk)


# ── Catalog Items ───────────────────────────────────────────────────────────

def items_for_tenant(
    tenant_id: int,
    *,
    catalog_type: str | None = None,
    status: str | None = None,
    category_id: int | None = None,
    owner_id: int | None = None,
) -> QuerySet:
    qs = CatalogItem.objects.filter(tenant_id=tenant_id).select_related("category", "owner")
    if catalog_type:
        qs = qs.filter(catalog_type=catalog_type)
    if status:
        qs = qs.filter(status=status)
    if category_id:
        qs = qs.filter(category_id=category_id)
    if owner_id:
        qs = qs.filter(owner_id=owner_id)
    return qs


def published_items(tenant_id: int, *, catalog_type: str | None = None) -> QuerySet:
    return items_for_tenant(tenant_id, catalog_type=catalog_type, status=CatalogItemStatus.PUBLISHED)


def item_by_public_id(tenant_id: int, public_id: str) -> CatalogItem:
    return CatalogItem.objects.get(tenant_id=tenant_id, public_id=public_id)


def item_by_slug(tenant_id: int, slug: str) -> CatalogItem:
    return CatalogItem.objects.get(tenant_id=tenant_id, slug=slug, status=CatalogItemStatus.PUBLISHED)


def item_by_pk(tenant_id: int, pk: int) -> CatalogItem:
    return CatalogItem.objects.get(tenant_id=tenant_id, pk=pk)


def search_items(tenant_id: int, query: str, *, limit: int = 20) -> QuerySet:
    return published_items(tenant_id).filter(
        Q(name__icontains=query)
        | Q(description__icontains=query)
        | Q(short_description__icontains=query)
        | Q(category__name__icontains=query)
    )[:limit]


# ── Versions ────────────────────────────────────────────────────────────────

def versions_for_item(catalog_item: CatalogItem) -> QuerySet:
    return CatalogItemVersion.objects.filter(catalog_item=catalog_item).select_related("changed_by")


def version_by_id(tenant_id: int, catalog_item_id: int, version: int) -> CatalogItemVersion:
    return CatalogItemVersion.objects.get(
        tenant_id=tenant_id,
        catalog_item_id=catalog_item_id,
        version=version,
    )
