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

from __future__ import annotations

from django.db.models import Q, QuerySet

from simorgh.apps.content.models import (
    ContentCategory,
    ContentItem,
    ContentStatus,
    ContentVersion,
    ContentVisibility,
)

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

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


def category_tree(tenant_id: int) -> list[dict]:
    """Return nested tree structure for frontend rendering."""
    cats = list(
        ContentCategory.objects.filter(tenant_id=tenant_id, is_active=True)
        .values("pk", "public_id", "name", "slug", "parent_id", "icon")
        .order_by("sort_order")
    )
    by_parent: dict[int | None, list[dict]] = {}
    for c in cats:
        c["public_id"] = str(c["public_id"])
        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) -> ContentCategory:
    return ContentCategory.objects.get(tenant_id=tenant_id, pk=pk)


def category_by_slug(tenant_id: int, slug: str) -> ContentCategory:
    return ContentCategory.objects.get(tenant_id=tenant_id, slug=slug, is_active=True)


# ── Content Items ───────────────────────────────────────────────────────────

def items_for_tenant(
    tenant_id: int,
    *,
    content_type: str | None = None,
    status: str | None = None,
    category_id: int | None = None,
    author_id: int | None = None,
    visibility: str | None = None,
    workspace_id: int | None = None,
) -> QuerySet:
    qs = ContentItem.objects.filter(tenant_id=tenant_id).select_related("category", "author")
    if content_type:
        qs = qs.filter(content_type=content_type)
    if status:
        qs = qs.filter(status=status)
    if category_id:
        qs = qs.filter(category_id=category_id)
    if author_id:
        qs = qs.filter(author_id=author_id)
    if visibility:
        qs = qs.filter(visibility=visibility)
    if workspace_id:
        qs = qs.filter(workspace_id=workspace_id)
    return qs


def items_visible_to(tenant_id: int, *, user_id: int | None = None, is_authenticated: bool = False) -> QuerySet:
    """Return content items visible to the given user context."""
    qs = ContentItem.objects.filter(
        tenant_id=tenant_id,
        status=ContentStatus.PUBLISHED,
    ).select_related("category", "author")

    if user_id and is_authenticated:
        qs = qs.filter(
            Q(visibility=ContentVisibility.PUBLIC)
            | Q(visibility=ContentVisibility.INTERNAL)
            | Q(visibility=ContentVisibility.PRIVATE, author_id=user_id)
        )
    else:
        qs = qs.filter(visibility=ContentVisibility.PUBLIC)

    return qs


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


def item_by_slug(tenant_id: int, slug: str) -> ContentItem:
    return ContentItem.objects.get(
        tenant_id=tenant_id,
        slug=slug,
        status=ContentStatus.PUBLISHED,
        visibility=ContentVisibility.PUBLIC,
    )


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


def my_items(tenant_id: int, author_id: int) -> QuerySet:
    return ContentItem.objects.filter(
        tenant_id=tenant_id,
        author_id=author_id,
    ).select_related("category").order_by("-updated_at")


def recent_items(tenant_id: int, *, limit: int = 20) -> QuerySet:
    return items_visible_to(tenant_id, is_authenticated=True).order_by("-published_at")[:limit]


def search_items(tenant_id: int, query: str, *, limit: int = 20) -> QuerySet:
    """Full-text search across published content."""
    return items_visible_to(tenant_id, is_authenticated=True).filter(
        Q(title__icontains=query)
        | Q(body__icontains=query)
        | Q(excerpt__icontains=query)
        | Q(category__name__icontains=query)
        | Q(meta_keywords__icontains=query)
    )[:limit]


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

def versions_for_item(content_item: ContentItem) -> QuerySet:
    return ContentVersion.objects.filter(content_item=content_item).select_related("changed_by")


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