"""/api/books — the receivables + payables ledger lists and a tiny tenant
meta read behind the Books UI (P4). Thin HTTP layer: every rule lives in
services/books.py, gated on can_see_income (403 INCOME_FORBIDDEN). The
settlement math is a SEPARATE, frozen router (/api/settlement)."""

from __future__ import annotations

from fastapi import APIRouter, Query

from app.routers.deps import ActorDep, ApiError, SessionDep
from app.services import books as books_svc
from app.services.errors import ServiceError

router = APIRouter()


def _run(fn, *args, **kwargs):
    try:
        return fn(*args, **kwargs)
    except ServiceError as exc:
        raise ApiError(exc.status, exc.code, exc.summary, exc.detail) from exc


@router.get("/api/books/meta")
def books_meta(session: SessionDep, actor: ActorDep) -> dict:
    return _run(books_svc.books_meta, session, actor)


@router.get("/api/books/invoices")
def list_invoices(
    session: SessionDep,
    actor: ActorDep,
    month: str | None = None,
    status: str | None = None,
    q: str | None = None,
    page: int = Query(1, ge=1),
    page_size: int = Query(books_svc.DEFAULT_PAGE_SIZE, ge=1),
) -> dict:
    return _run(
        books_svc.list_invoices,
        session,
        actor,
        month=month,
        status=status,
        q=q,
        page=page,
        page_size=page_size,
    )


@router.get("/api/books/expenses")
def list_expenses(
    session: SessionDep,
    actor: ActorDep,
    month: str | None = None,
    category: str | None = None,
    paid_by: str | None = None,
    q: str | None = None,
    page: int = Query(1, ge=1),
    page_size: int = Query(books_svc.DEFAULT_PAGE_SIZE, ge=1),
) -> dict:
    return _run(
        books_svc.list_expenses,
        session,
        actor,
        month=month,
        category=category,
        paid_by=paid_by,
        q=q,
        page=page,
        page_size=page_size,
    )
