"""Approval Engine selectors — read-only queries."""

from __future__ import annotations

from django.db.models import Q, QuerySet
from django.utils import timezone

from simorgh.apps.approval_engine.models import (
    ApprovalRequest,
    ApprovalStep,
    ApprovalMatrix,
    ApprovalStatus,
    StepStatus,
)


def requests_for_tenant(tenant_id: int) -> QuerySet[ApprovalRequest]:
    return ApprovalRequest.objects.filter(tenant_id=tenant_id)


def requests_pending_my(tenant_id: int, user_id: int) -> QuerySet[ApprovalRequest]:
    """Approval requests where the user has pending steps to decide."""
    step_requests = ApprovalStep.objects.filter(
        approver_id=user_id,
        status__in=(StepStatus.PENDING, StepStatus.IN_PROGRESS),
    ).values_list("request_id", flat=True)
    return (
        requests_for_tenant(tenant_id)
        .filter(pk__in=step_requests)
        .order_by("due_date", "-priority")
    )


def requests_my(tenant_id: int, user_id: int) -> QuerySet[ApprovalRequest]:
    """All approval requests created by the user."""
    return (
        requests_for_tenant(tenant_id)
        .filter(requested_by_id=user_id)
        .order_by("-created_at")
    )


def requests_overdue(tenant_id: int, user_id: int | None = None) -> QuerySet[ApprovalRequest]:
    """Overdue approval requests, optionally filtered by user."""
    qs = (
        requests_for_tenant(tenant_id)
        .filter(due_date__lt=timezone.now())
        .exclude(status__in=(ApprovalStatus.APPROVED, ApprovalStatus.REJECTED, ApprovalStatus.CANCELLED, ApprovalStatus.EXPIRED))
    )
    if user_id is not None:
        step_requests = ApprovalStep.objects.filter(
            approver_id=user_id,
        ).values_list("request_id", flat=True)
        qs = qs.filter(pk__in=step_requests)
    return qs.order_by("due_date")


def requests_approved(tenant_id: int) -> QuerySet[ApprovalRequest]:
    return requests_for_tenant(tenant_id).filter(status=ApprovalStatus.APPROVED)


def requests_rejected(tenant_id: int) -> QuerySet[ApprovalRequest]:
    return requests_for_tenant(tenant_id).filter(status=ApprovalStatus.REJECTED)


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


def steps_for_request(request_id: int) -> QuerySet[ApprovalStep]:
    return ApprovalStep.objects.filter(request_id=request_id).order_by("step_order")


def step_by_public_id(public_id: str) -> ApprovalStep:
    return ApprovalStep.objects.get(public_id=public_id)


def steps_for_user(tenant_id: int, user_id: int) -> QuerySet[ApprovalStep]:
    """All steps assigned to a user."""
    return ApprovalStep.objects.filter(
        request__tenant_id=tenant_id,
        approver_id=user_id,
    ).order_by("-created_at")


def steps_pending_for_user(tenant_id: int, user_id: int) -> QuerySet[ApprovalStep]:
    return steps_for_user(tenant_id, user_id).filter(
        status__in=(StepStatus.PENDING, StepStatus.IN_PROGRESS),
    )


def matrices_for_tenant(tenant_id: int) -> QuerySet[ApprovalMatrix]:
    return ApprovalMatrix.objects.filter(tenant_id=tenant_id).order_by("name")


def active_matrices_for_entity(tenant_id: int, content_type_id: int) -> QuerySet[ApprovalMatrix]:
    return matrices_for_tenant(tenant_id).filter(
        content_type_id=content_type_id,
        is_active=True,
    )


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


def search_requests(tenant_id: int, query: str) -> QuerySet[ApprovalRequest]:
    return (
        requests_for_tenant(tenant_id)
        .filter(
            Q(title__icontains=query)
            | Q(description__icontains=query)
        )
        .distinct()
    )
