"""Recipe "workflow-state": read a document's workflow states and transitions, then move it to
another state.

Usage: python recipes/workflow_state.py [workflow ID, default 107] [initial state ID, default
137] [target state ID, default 141] [--keep]

With --keep the test document stays in the vault; otherwise it is deleted at the end.
"""

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from mfiles_client import run  # noqa: E402
from mfiles_values import lookup, obj_ver, property_value  # noqa: E402
from recipe_helpers import (connect, create_test_document, delete, describe,  # noqa: E402
                            format_value, int_arg, keep)

from mfiles import IRPCObjectOperations_pb2 as ops  # noqa: E402
from mfiles import IRPCObjectOperations_pb2_grpc  # noqa: E402


def main() -> None:
    workflow_id = int_arg(0, 107)    # "Contract Approval Workflow" in the Sample Vault
    initial_state = int_arg(1, 137)  # "Draft"
    # "Rejected". "Waiting for Approval" (138) has a precondition: the Owner property is set.
    target_state = int_arg(2, 141)
    with connect() as client:
        objects = client.stub(IRPCObjectOperations_pb2_grpc.IRPCObjectOperationsStub)

        # A test document in the workflow: property 38 "Workflow" (value list 7) and
        # property 39 "Workflow State" (value list 8).
        created = create_test_document(client, "workflow-state",
                                       property_value(38, lookup(7, workflow_id)),
                                       property_value(39, lookup(8, initial_state)))
        object_id = created.object_info.obj_id
        print(f"Created {describe(created)}")
        try:
            # [START workflow-state]
            # The states and transitions of the workflow, with what this user may select for
            # this object in its current state.
            version = obj_ver(object_id.type, object_id.item_id.internal_id,
                              created.version_info.version.internal_version)
            workflow = objects.GetWorkflowStatesAndTransitions(
                ops.GetWorkflowStatesAndTransitionsRequest(
                    workflow_id=workflow_id,
                    current_state=lookup(8, initial_state),
                    obj_ver=version))
            for state in workflow.states:
                print(f"  State {state.id} {state.name}: "
                      f"selectable {state.can_current_user_select}")
            for transition in workflow.transitions:
                print(f"  Transition {transition.id} {transition.name}: "
                      f"{transition.from_state_id} -> {transition.to_state_id}, "
                      f"selectable {transition.can_current_user_select}")

            # Change the state by setting property 39 "Workflow State" on the version just read.
            updated = objects.SetProperties(ops.SetPropertiesRequest(
                obj_ver=version,
                allow_modifying_checked_in_object=True,
                fail_if_newer_version_exists=True,
                properties=[property_value(39, lookup(8, target_state))]))
            # [END workflow-state]

            latest = updated.object_info.latest_version
            state = next(p for p in latest.properties if p.property_def == 39)
            print(f"State is now {format_value(state.value)}, version "
                  f"{latest.object_version.version_info.version.internal_version}")
        finally:
            if not keep():
                delete(client, object_id)


if __name__ == "__main__":
    run(main)
