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

from __future__ import annotations

from django.db.models import QuerySet

from simorgh.apps.reporting.models import (
    DashboardDefinition,
    KPIDefinition,
    ReportDefinition,
    ReportExecution,
    ScheduledReport,
)

# ---------------------------------------------------------------------------
# Report definitions
# ---------------------------------------------------------------------------

def list_reports(*, tenant_id: int, module: str = "", is_active: bool | None = None) -> QuerySet:
    """Return report definitions for a tenant, optionally filtered by module."""
    qs = ReportDefinition.objects.filter(tenant_id=tenant_id)
    if module:
        qs = qs.filter(module=module)
    if is_active is not None:
        qs = qs.filter(is_active=is_active)
    return qs.order_by("module", "name")


def get_report(*, tenant_id: int, code: str) -> ReportDefinition | None:
    """Return a report definition by tenant and code."""
    return ReportDefinition.objects.filter(tenant_id=tenant_id, code=code).first()


def get_report_by_id(*, tenant_id: int, report_id: int) -> ReportDefinition | None:
    """Return a report definition by tenant and PK."""
    return ReportDefinition.objects.filter(tenant_id=tenant_id, pk=report_id).first()


# ---------------------------------------------------------------------------
# Scheduled reports
# ---------------------------------------------------------------------------

def list_schedules(
    *, tenant_id: int, report_id: int | None = None, is_active: bool | None = None,
) -> QuerySet:
    """Return scheduled reports for a tenant."""
    qs = ScheduledReport.objects.filter(tenant_id=tenant_id)
    if report_id is not None:
        qs = qs.filter(report_id=report_id)
    if is_active is not None:
        qs = qs.filter(is_active=is_active)
    return qs.order_by("-created_at")


def get_schedule(*, tenant_id: int, schedule_id: int) -> ScheduledReport | None:
    """Return a scheduled report by tenant and PK."""
    return ScheduledReport.objects.filter(tenant_id=tenant_id, pk=schedule_id).first()


def get_due_schedules() -> QuerySet:
    """Return active schedules whose ``next_run_at`` is in the past."""
    from django.utils import timezone

    return ScheduledReport.objects.filter(
        is_active=True,
        next_run_at__lte=timezone.now(),
    ).select_related("report")


# ---------------------------------------------------------------------------
# KPI definitions
# ---------------------------------------------------------------------------

def list_kpis(*, tenant_id: int, module: str = "", is_active: bool | None = None) -> QuerySet:
    """Return KPI definitions for a tenant."""
    qs = KPIDefinition.objects.filter(tenant_id=tenant_id)
    if module:
        qs = qs.filter(module=module)
    if is_active is not None:
        qs = qs.filter(is_active=is_active)
    return qs.order_by("module", "name")


def get_kpi(*, tenant_id: int, code: str) -> KPIDefinition | None:
    """Return a KPI definition by tenant and code."""
    return KPIDefinition.objects.filter(tenant_id=tenant_id, code=code).first()


def get_kpi_by_id(*, tenant_id: int, kpi_id: int) -> KPIDefinition | None:
    """Return a KPI definition by tenant and PK."""
    return KPIDefinition.objects.filter(tenant_id=tenant_id, pk=kpi_id).first()


# ---------------------------------------------------------------------------
# Dashboard definitions
# ---------------------------------------------------------------------------

def list_dashboards(
    *, tenant_id: int, module: str = "", is_active: bool | None = None,
) -> QuerySet:
    """Return dashboard definitions for a tenant."""
    qs = DashboardDefinition.objects.filter(tenant_id=tenant_id)
    if module:
        qs = qs.filter(module=module)
    if is_active is not None:
        qs = qs.filter(is_active=is_active)
    return qs.order_by("-is_default", "name")


def get_dashboard(*, tenant_id: int, code: str) -> DashboardDefinition | None:
    """Return a dashboard definition by tenant and code."""
    return DashboardDefinition.objects.filter(tenant_id=tenant_id, code=code).first()


def get_dashboard_by_id(*, tenant_id: int, dashboard_id: int) -> DashboardDefinition | None:
    """Return a dashboard definition by tenant and PK."""
    return DashboardDefinition.objects.filter(tenant_id=tenant_id, pk=dashboard_id).first()


# ---------------------------------------------------------------------------
# Report executions
# ---------------------------------------------------------------------------

def list_executions(
    *,
    tenant_id: int,
    report_id: int | None = None,
    status: str = "",
    limit: int = 50,
) -> QuerySet:
    """Return report executions, newest first."""
    qs = ReportExecution.objects.filter(tenant_id=tenant_id)
    if report_id is not None:
        qs = qs.filter(report_id=report_id)
    if status:
        qs = qs.filter(status=status)
    return qs.order_by("-started_at")[:limit]


def get_execution(*, tenant_id: int, execution_id: int) -> ReportExecution | None:
    """Return a single execution record."""
    return ReportExecution.objects.filter(tenant_id=tenant_id, pk=execution_id).first()
