# State Machine System Documentation

## Overview

The state machine system provides a comprehensive integration between Django's RichChoice system and django-fsm (Finite State Machine). This integration automatically generates state transition methods based on metadata defined in RichChoice objects, eliminating the need for manual state management code.

## Key Features

- **Metadata-Driven**: All state machine behavior is derived from RichChoice metadata
- **Automatic Transition Generation**: Transition methods are automatically created from metadata
- **Permission-Based Guards**: Built-in support for moderator and admin permissions
- **Validation**: Comprehensive validation ensures metadata consistency
- **Centralized Registry**: All transitions are tracked in a central registry
- **Logging Integration**: Automatic integration with django-fsm-log

## Quick Start

### 1. Define Your States with Metadata

```python
from backend.apps.core.choices.base import RichChoice, ChoiceCategory
from backend.apps.core.choices.registry import registry

submission_states = [
    RichChoice(
        value="pending",
        label="Pending Review",
        description="Awaiting moderator review",
        metadata={
            "can_transition_to": ["approved", "rejected", "escalated"],
            "requires_moderator": False,
            "is_actionable": True,
        },
        category=ChoiceCategory.STATUS,
    ),
    RichChoice(
        value="approved",
        label="Approved",
        description="Approved by moderator",
        metadata={
            "can_transition_to": [],
            "is_final": True,
            "requires_moderator": True,
        },
        category=ChoiceCategory.STATUS,
    ),
    RichChoice(
        value="rejected",
        label="Rejected",
        description="Rejected by moderator",
        metadata={
            "can_transition_to": [],
            "is_final": True,
            "requires_moderator": True,
        },
        category=ChoiceCategory.STATUS,
    ),
]

registry.register("submission_status", submission_states, domain="moderation")
```

### 2. Use RichFSMField in Your Model

```python
from django.db import models
from backend.apps.core.state_machine import RichFSMField, StateMachineMixin

class EditSubmission(StateMachineMixin, models.Model):
    status = RichFSMField(
        choice_group="submission_status",
        domain="moderation",
        default="pending",
    )
    
    # ... other fields
```

### 3. Apply State Machine

```python
from backend.apps.core.state_machine import apply_state_machine

# Apply state machine (usually in AppConfig.ready())
apply_state_machine(
    EditSubmission,
    field_name="status",
    choice_group="submission_status",
    domain="moderation"
)
```

### 4. Use Transition Methods

```python
# Get an instance
submission = EditSubmission.objects.get(id=1)

# Check available transitions
available = submission.get_available_state_transitions()
print(f"Can transition to: {[t.target for t in available]}")

# Execute transition
if submission.can_transition_to("approved", user=request.user):
    submission.approve(user=request.user, comment="Looks good!")
    submission.save()
```

## Metadata Reference

### Required Metadata Fields

- **`can_transition_to`** (list): List of valid target states from this state
  ```python
  metadata={"can_transition_to": ["approved", "rejected"]}
  ```

### Optional Metadata Fields

- **`is_final`** (bool): Whether this is a terminal state (no outgoing transitions)
  ```python
  metadata={"is_final": True}
  ```

- **`is_actionable`** (bool): Whether actions can be taken in this state
  ```python
  metadata={"is_actionable": True}
  ```

- **`requires_moderator`** (bool): Whether moderator permission is required
  ```python
  metadata={"requires_moderator": True}
  ```

- **`requires_admin_approval`** (bool): Whether admin permission is required
  ```python
  metadata={"requires_admin_approval": True}
  ```

## Components

### StateTransitionBuilder

Reads RichChoice metadata and generates FSM transition configurations.

```python
from backend.apps.core.state_machine import StateTransitionBuilder

builder = StateTransitionBuilder("submission_status", "moderation")
graph = builder.build_transition_graph()
# Returns: {"pending": ["approved", "rejected"], "approved": [], ...}
```

### TransitionRegistry

Centralized registry for managing and looking up FSM transitions.

```python
from backend.apps.core.state_machine import registry_instance

# Get available transitions
transitions = registry_instance.get_available_transitions(
    "submission_status", "moderation", "pending"
)

# Export graph for visualization
mermaid = registry_instance.export_transition_graph(
    "submission_status", "moderation", format="mermaid"
)
```

### MetadataValidator

Validates RichChoice metadata meets state machine requirements.

```python
from backend.apps.core.state_machine import MetadataValidator

validator = MetadataValidator("submission_status", "moderation")
result = validator.validate_choice_group()

if not result.is_valid:
    for error in result.errors:
        print(error)
```

### PermissionGuard

Guards for checking permissions on state transitions.

```python
from backend.apps.core.state_machine import PermissionGuard

guard = PermissionGuard(requires_moderator=True)
allowed = guard(instance, user=request.user)
```

## Common Patterns

### Pattern 1: Basic Approval Flow

```python
states = [
    RichChoice("pending", "Pending", metadata={
        "can_transition_to": ["approved", "rejected"]
    }),
    RichChoice("approved", "Approved", metadata={
        "is_final": True,
        "requires_moderator": True,
    }),
    RichChoice("rejected", "Rejected", metadata={
        "is_final": True,
        "requires_moderator": True,
    }),
]
```

### Pattern 2: Multi-Level Approval

```python
states = [
    RichChoice("pending", "Pending", metadata={
        "can_transition_to": ["moderator_review"]
    }),
    RichChoice("moderator_review", "Under Review", metadata={
        "can_transition_to": ["admin_review", "rejected"],
        "requires_moderator": True,
    }),
    RichChoice("admin_review", "Admin Review", metadata={
        "can_transition_to": ["approved", "rejected"],
        "requires_admin_approval": True,
    }),
    RichChoice("approved", "Approved", metadata={"is_final": True}),
    RichChoice("rejected", "Rejected", metadata={"is_final": True}),
]
```

### Pattern 3: With Escalation

```python
states = [
    RichChoice("pending", "Pending", metadata={
        "can_transition_to": ["approved", "rejected", "escalated"]
    }),
    RichChoice("escalated", "Escalated", metadata={
        "can_transition_to": ["approved", "rejected"],
        "requires_admin_approval": True,
    }),
    # ... final states
]
```

## Best Practices

1. **Always define `can_transition_to`**: Every state should explicitly list its valid transitions
2. **Mark terminal states**: Use `is_final: True` for states with no outgoing transitions
3. **Use permission flags**: Leverage `requires_moderator` and `requires_admin_approval` for access control
4. **Validate early**: Run validation during development to catch metadata issues
5. **Document transitions**: Use clear labels and descriptions for each state
6. **Test transitions**: Write tests for all transition paths

## Troubleshooting

### Issue: "Validation failed" error

**Cause**: Metadata references non-existent states or has inconsistencies

**Solution**: Run validation report to see specific errors:
```python
validator = MetadataValidator("your_group", "your_domain")
print(validator.generate_validation_report())
```

### Issue: Transition method not found

**Cause**: State machine not applied to model

**Solution**: Ensure `apply_state_machine()` is called in AppConfig.ready():
```python
from django.apps import AppConfig

class ModerationConfig(AppConfig):
    def ready(self):
        from backend.apps.core.state_machine import apply_state_machine
        from .models import EditSubmission
        
        apply_state_machine(
            EditSubmission, "status", "submission_status", "moderation"
        )
```

### Issue: Permission denied on transition

**Cause**: User doesn't have required permissions

**Solution**: Check permission requirements in metadata and ensure user has appropriate role/permissions

## API Reference

See individual component documentation:
- [StateTransitionBuilder](builder.py)
- [TransitionRegistry](registry.py)
- [MetadataValidator](validators.py)
- [PermissionGuard](guards.py)
- [Integration Utilities](integration.py)

## Testing

The system includes comprehensive tests:
```bash
pytest backend/apps/core/state_machine/tests/
```

Test coverage includes:
- Builder functionality
- Decorator generation
- Registry operations
- Metadata validation
- Guard functionality
- Model integration
