"""Correspondence read-only selectors — pure query functions, no side effects."""

from __future__ import annotations

from typing import TYPE_CHECKING

from django.db.models import Q, QuerySet

from simorgh.apps.correspondence.models import (
    Category,
    Letter,
    LetterAttachment,
    LetterheadTemplate,
    LetterRecipient,
    LetterTemplate,
    NumberingTemplate,
)

if TYPE_CHECKING:
    pass


# ═══════════════════════════════════════════════════════════════════════════
# Letter selectors
# ═══════════════════════════════════════════════════════════════════════════


def letters_for_tenant(
    tenant_id: int,
    *,
    letter_type: str | None = None,
    status: str | None = None,
    priority: str | None = None,
    security: str | None = None,
    category_id: int | None = None,
    sender_id: int | None = None,
    q: str | None = None,
    date_from: str | None = None,
    date_to: str | None = None,
) -> QuerySet[Letter]:
    """Return filtered letters for a tenant."""
    qs = Letter.objects.filter(tenant_id=tenant_id).select_related(
        "category", "template", "sender", "letterhead"
    )
    if letter_type:
        qs = qs.filter(letter_type=letter_type)
    if status:
        qs = qs.filter(status=status)
    if priority:
        qs = qs.filter(priority=priority)
    if security:
        qs = qs.filter(security=security)
    if category_id:
        qs = qs.filter(category_id=category_id)
    if sender_id:
        qs = qs.filter(sender_id=sender_id)
    if q:
        qs = qs.filter(
            Q(subject__icontains=q)
            | Q(body__icontains=q)
            | Q(registration_number__icontains=q)
            | Q(sender_external__icontains=q)
            | Q(external_reference__icontains=q)
        )
    if date_from:
        qs = qs.filter(registration_date__gte=date_from)
    if date_to:
        qs = qs.filter(registration_date__lte=date_to)
    return qs.order_by("-created_at")


def letter_by_pk(tenant_id: int, pk: int) -> Letter | None:
    """Return a single letter by PK, scoped to tenant."""
    try:
        return (
            Letter.objects.filter(tenant_id=tenant_id)
            .select_related("category", "template", "sender", "letterhead", "parent")
            .prefetch_related("attachments", "recipients")
            .get(pk=pk)
        )
    except Letter.DoesNotExist:
        return None


def letter_attachments(letter_id: int) -> QuerySet[LetterAttachment]:
    """Return attachments for a letter."""
    return LetterAttachment.objects.filter(letter_id=letter_id).order_by("sort_order")


def letter_recipients(letter_id: int) -> QuerySet[LetterRecipient]:
    """Return recipients for a letter."""
    return LetterRecipient.objects.filter(letter_id=letter_id).order_by("created_at")


# ═══════════════════════════════════════════════════════════════════════════
# Category selectors
# ═══════════════════════════════════════════════════════════════════════════


def categories_for_tenant(
    tenant_id: int,
    *,
    category_type: str | None = None,
    parent_id: int | None = None,
    is_active: bool | None = None,
) -> QuerySet[Category]:
    """Return categories for a tenant."""
    qs = Category.objects.filter(tenant_id=tenant_id)
    if category_type:
        qs = qs.filter(category_type=category_type)
    if parent_id is not None:
        qs = qs.filter(parent_id=parent_id)
    if is_active is not None:
        qs = qs.filter(is_active=is_active)
    return qs.order_by("sort_order", "name")


# ═══════════════════════════════════════════════════════════════════════════
# Template selectors
# ═══════════════════════════════════════════════════════════════════════════


def letter_templates_for_tenant(
    tenant_id: int,
    *,
    letter_type: str | None = None,
    is_active: bool | None = None,
) -> QuerySet[LetterTemplate]:
    """Return letter templates for a tenant."""
    qs = LetterTemplate.objects.filter(tenant_id=tenant_id).select_related(
        "letterhead", "numbering_template"
    )
    if letter_type:
        qs = qs.filter(letter_type=letter_type)
    if is_active is not None:
        qs = qs.filter(is_active=is_active)
    return qs.order_by("name")


def numbering_templates_for_tenant(
    tenant_id: int,
    *,
    letter_type: str | None = None,
) -> QuerySet[NumberingTemplate]:
    """Return numbering templates for a tenant."""
    qs = NumberingTemplate.objects.filter(tenant_id=tenant_id)
    if letter_type:
        qs = qs.filter(letter_type=letter_type)
    return qs.order_by("name")


def letterhead_templates_for_tenant(
    tenant_id: int,
    *,
    is_active: bool | None = None,
) -> QuerySet[LetterheadTemplate]:
    """Return letterhead templates for a tenant."""
    qs = LetterheadTemplate.objects.filter(tenant_id=tenant_id)
    if is_active is not None:
        qs = qs.filter(is_active=is_active)
    return qs.order_by("name")
