"""Every workflow this deployment can run, by name.

The router answers with a name, and something has to turn that into a definition.
This is that something, and it is also what the decision poller needs — a
decision comes back naming a proposal, and resuming the run requires the
definition it was started from.

Both used to be hand-maintained lists in the container. Two lists of the same
thing drift, and the way this one drifts is a workflow that documents route to
and decisions cannot resume, which looks like the CMS silently ignoring
approvals.

Registration is explicit, for the reason the Tool registry is: a workflow that
becomes available merely by existing on disk is one nobody decided to ship.
"""

from __future__ import annotations

from app.workflow.bank_statement_intake import BANK_STATEMENT_INTAKE
from app.workflow.document_intake import DOCUMENT_INTAKE
from app.workflow.engine import Workflow
from app.workflow.extraction_intake import ALL as EXTRACTION_WORKFLOWS

WORKFLOWS: tuple[Workflow, ...] = (
    DOCUMENT_INTAKE,
    BANK_STATEMENT_INTAKE,
    *EXTRACTION_WORKFLOWS,
)

_BY_NAME: dict[str, Workflow] = {w.name: w for w in WORKFLOWS}


def get(name: str) -> Workflow | None:
    return _BY_NAME.get(name)


def require(name: str) -> Workflow:
    """The definition, or the general reading workflow if there is no such name.

    Falling back rather than raising, and saying so is the point: the caller is
    a daemon loop holding somebody's document, and a KeyError there loses the
    document to a configuration mistake. The reading workflow handles anything
    adequately, so the worst case is a document classified precisely and then
    handled generally.

    `test_every_workflow_named_in_the_registry_exists` is what stops this being
    reached in practice.
    """
    return _BY_NAME.get(name, DOCUMENT_INTAKE)


def names() -> tuple[str, ...]:
    return tuple(_BY_NAME)
