# ============================================================================
# PATTERN 2: Steps with Optional Actions
# ============================================================================

def process_with_optional_steps(self, invite: InviteModel) -> AppResult:
    processor = StepProcessor(
        model=invite,
        steps=[
            ProcessingStep(
                'user_created',
                lambda: self._create_invite_user(invite),
                description="Create user",
                required=True  # Fail if this fails
            ),
            ProcessingStep(
                'email_sent',
                lambda: self._send_invite_email(invite, False),
                description="Send email",
                required=False  # Continue if this fails
            ),
            ProcessingStep(
                'search_indexed',
                lambda: self._index_in_search(invite),
                description="Add to search",
                required=False  # Continue if this fails
            ),
        ],
        save_handler=lambda m: self.invite_bridge.update(m),
        process_name='process_invite'
    )
    return processor.execute()

# ============================================================================
# PATTERN 3: Wrapping Complex Methods
# ============================================================================

# If your existing method returns Union or doesn't return AppResult:
def _create_invite_relationships_step(self, invite: InviteModel) -> AppResult:
    """Wrapper to make existing method compatible with StepProcessor."""
    main_result = AppResult[InviteModel]('create_relationships')

    # Call existing method
    results = self._create_invite_relationship(invite)

    # Handle Union return type
    if isinstance(results, AppResult):
        main_result.merge(results)
    elif isinstance(results, list):
        for result in results:
            if result.is_error:
                main_result.merge(result)

    return main_result

# Then use in processor:
# ProcessingStep('friends_created', lambda: self._create_invite_relationships_step(invite))

# ============================================================================
# PATTERN 4: Manual Save Control
# ============================================================================

# If you want to control when saves happen:
from flipdare.core.step_processor import SimpleStepProcessor

def process_with_manual_saves(self, invite: InviteModel) -> AppResult:
    processor = SimpleStepProcessor(
        model=invite,
        steps=[
            ProcessingStep('step1', lambda: self._step1(invite)),
            ProcessingStep('step2', lambda: self._step2(invite)),
        ],
        save_handler=lambda m: self.invite_bridge.update(m),
        process_name='manual_process'
    )

    result = processor.execute()

    # Only save at the end if successful
    if result.is_ok:
        save_result = processor.save()
        if save_result.is_error:
            result.merge(save_result)

    return result

# ============================================================================
# PATTERN 5: Add States to Existing Model
# ============================================================================

# In your model file (e.g., friend_model.py):

# Add state constants at top:
FRIEND_CREATED = "friend_created"
FRIEND_EMAIL_SENT = "email_sent"
FRIEND_NOTIF_SENT = "notif_sent"

# In model __init__:
from flipdare.core.internal_model_state import InternalModelState

class FriendModel(DatabaseModel):
    def __init__(self, data: DatabaseDict, from_firestore: bool = False):
        super().__init__(
            required=["fromUid", "toUid", "friendType", "status"],
            internal_state=InternalModelState([
                FRIEND_CREATED,
                FRIEND_EMAIL_SENT,
                FRIEND_NOTIF_SENT,
            ]),
            enum_generators={...},
            data=data,
            from_firestore=from_firestore,
        )