"""/api/invoices — CRUD + detail + paste block. Thin HTTP layer: every
rule lives in services/money/invoices.py + paste_block.py (04 "Money
paths"). Reads are member-visible with scope()-limited sums; writes are
owner-gated (can_transfer) inside the service."""

from __future__ import annotations

import uuid

from fastapi import APIRouter
from pydantic import BaseModel

from app.routers.deps import ActorDep, ApiError, SessionDep
from app.services.errors import ServiceError
from app.services.money import invoices as invoice_svc
from app.services.money import paste_block as paste_svc

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


class InvoiceCreate(BaseModel):
    name: str = ""
    status: str | None = None
    invoice_date: str | None = None
    to_party_id: str | None = None
    manual_total: str | None = None
    notes: str | None = None


class InvoicePatch(BaseModel):
    """PATCH semantics: only the SET fields reach the service (an empty
    invoice_date deliberately writes NULL — B66 parity)."""

    name: str | None = None
    status: str | None = None
    invoice_date: str | None = None
    to_party_id: str | None = None
    manual_total: str | None = None
    notes: str | None = None


@router.get("/api/invoices")
def list_invoices(session: SessionDep, actor: ActorDep) -> dict:
    return {"rows": _run(invoice_svc.list_invoices, session, actor)}


@router.post("/api/invoices")
def create_invoice(session: SessionDep, actor: ActorDep, body: InvoiceCreate) -> dict:
    row = _run(invoice_svc.create_invoice, session, actor, body.model_dump())
    return {"ok": True, "row": row}


@router.get("/api/invoices/{invoice_id}")
def invoice_detail(session: SessionDep, actor: ActorDep, invoice_id: uuid.UUID) -> dict:
    return _run(invoice_svc.invoice_detail, session, actor, invoice_id)


@router.patch("/api/invoices/{invoice_id}")
def update_invoice(
    session: SessionDep, actor: ActorDep, invoice_id: uuid.UUID, body: InvoicePatch
) -> dict:
    patch = {k: getattr(body, k) for k in body.model_fields_set}
    row = _run(invoice_svc.update_invoice, session, actor, invoice_id, patch)
    return {"ok": True, "row": row}


@router.delete("/api/invoices/{invoice_id}")
def delete_invoice(session: SessionDep, actor: ActorDep, invoice_id: uuid.UUID) -> dict:
    return _run(invoice_svc.delete_invoice, session, actor, invoice_id)


@router.get("/api/invoices/{invoice_id}/paste-block")
def paste_block(session: SessionDep, actor: ActorDep, invoice_id: uuid.UUID) -> dict:
    return _run(paste_svc.paste_block_for_invoice, session, actor, invoice_id)
