"""scope(actor, action, stmt) -> Select — the query-side twin of can()
(04-architecture: 'a Select transformer owning the join graph'). Every
list/aggregate query in the app flows through here; no router builds
its own permission WHERE clause (T-AZ-004).

R1 rules (rpcs §3.7 ported):
  entries:read   super-admin / owner  -> tenant-wide
                 manager / worker     -> only rows whose import batch
                                         they uploaded (rows with no
                                         batch are invisible to them)
                 no role              -> nothing
  imports:read   batch METADATA is tenant-visible to any role (parity
                 with the org-wide clockify_imports policy), except a
                 view-as of a non-owner narrows to the target's own
                 batches (parity B48) — and no role sees nothing.

The importer rule is expressed as an IN-(correlated subquery) on
import_batches so callers never join it themselves — the join graph
lives here, one implementation.
"""

from __future__ import annotations

from sqlalchemy import Select, false, select

from app.models import ImportBatch, TimeEntry


def scope(actor, action: str, stmt: Select) -> Select:
    if action == "entries:read":
        return _scope_entries(actor, stmt)
    if action == "imports:read":
        return _scope_imports(actor, stmt)
    raise ValueError(f"scope(): unknown action {action!r}")


def _scope_entries(actor, stmt: Select) -> Select:
    if actor.tenant_id is None:
        return stmt.where(false())
    stmt = stmt.where(TimeEntry.tenant_id == actor.tenant_id)

    if (actor.is_super_admin and not actor.is_viewing_as) or actor.role == "owner":
        return stmt
    if actor.role in ("manager", "worker") and actor.user_id is not None:
        own_batches = select(ImportBatch.id).where(
            ImportBatch.tenant_id == actor.tenant_id,
            ImportBatch.imported_by == actor.user_id,
        )
        # NULL import_id never matches IN(...) — no-batch rows are
        # invisible to non-owners, exactly rpcs §3.7 branch 3.
        return stmt.where(TimeEntry.import_id.in_(own_batches))
    return stmt.where(false())


def _scope_imports(actor, stmt: Select) -> Select:
    if actor.tenant_id is None:
        return stmt.where(false())
    stmt = stmt.where(ImportBatch.tenant_id == actor.tenant_id)

    if actor.is_super_admin and not actor.is_viewing_as:
        return stmt
    if actor.role == "none":
        return stmt.where(false())
    if actor.is_viewing_as and actor.role != "owner" and not actor.is_super_admin:
        return stmt.where(ImportBatch.imported_by == actor.user_id)
    return stmt
