# State Transition API Endpoints

This document describes the API endpoints for performing state transitions on various models in ThrillWiki.

## Overview

State transitions are performed via POST requests to specific action endpoints. All transition endpoints:

- Require authentication
- Return the updated object on success
- Return appropriate error codes on failure
- Log the transition in the StateLog

## Authentication

All endpoints require a valid JWT token in the Authorization header:

```
Authorization: Bearer <token>
```

## Error Responses

| Status Code | Meaning |
|-------------|---------|
| 400 | Invalid transition (state not allowed) |
| 401 | Not authenticated |
| 403 | Permission denied (insufficient role) |
| 404 | Object not found |
| 422 | Validation error (missing required fields) |

---

## EditSubmission Transitions

### Approve Submission

Approve an edit submission and apply changes to the target object.

```http
POST /api/moderation/submissions/{id}/approve/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "notes": "Optional approval notes"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "status": "APPROVED",
  "handled_by": {
    "id": 456,
    "username": "moderator"
  },
  "handled_at": "2025-01-15T10:30:00Z",
  "notes": "Looks good, approved"
}
```

### Reject Submission

Reject an edit submission with a reason.

```http
POST /api/moderation/submissions/{id}/reject/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "reason": "Required rejection reason"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "status": "REJECTED",
  "handled_by": {
    "id": 456,
    "username": "moderator"
  },
  "handled_at": "2025-01-15T10:30:00Z",
  "notes": "Rejected: Insufficient evidence"
}
```

### Escalate Submission

Escalate a submission to admin review.

```http
POST /api/moderation/submissions/{id}/escalate/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "reason": "Reason for escalation"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "status": "ESCALATED",
  "handled_by": {
    "id": 456,
    "username": "moderator"
  },
  "handled_at": "2025-01-15T10:30:00Z",
  "notes": "Escalated: Needs admin approval for sensitive change"
}
```

---

## ModerationReport Transitions

### Start Review

Claim a report and start reviewing it.

```http
POST /api/moderation/reports/{id}/start_review/
```

**Permissions**: MODERATOR or above

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "status": "UNDER_REVIEW",
  "assigned_moderator": {
    "id": 456,
    "username": "moderator"
  }
}
```

### Resolve Report

Mark a report as resolved.

```http
POST /api/moderation/reports/{id}/resolve/
```

**Permissions**: MODERATOR or above (must be assigned)

**Request Body**:
```json
{
  "resolution_action": "CONTENT_REMOVED",
  "resolution_notes": "Description of action taken"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "status": "RESOLVED",
  "resolution_action": "CONTENT_REMOVED",
  "resolution_notes": "Description of action taken",
  "resolved_at": "2025-01-15T10:30:00Z"
}
```

### Dismiss Report

Dismiss a report as invalid.

```http
POST /api/moderation/reports/{id}/dismiss/
```

**Permissions**: MODERATOR or above (must be assigned)

**Request Body**:
```json
{
  "resolution_notes": "Reason for dismissal"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "status": "DISMISSED",
  "resolution_notes": "Report did not violate guidelines",
  "resolved_at": "2025-01-15T10:30:00Z"
}
```

---

## Park Transitions

### Close Temporarily

Temporarily close a park.

```http
POST /api/parks/{slug}/close_temporarily/
```

**Permissions**: Authenticated user

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-park",
  "name": "Example Park",
  "status": "CLOSED_TEMP"
}
```

### Reopen

Reopen a temporarily closed park.

```http
POST /api/parks/{slug}/reopen/
```

**Permissions**: Authenticated user

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-park",
  "name": "Example Park",
  "status": "OPERATING"
}
```

### Close Permanently

Permanently close a park.

```http
POST /api/parks/{slug}/close_permanently/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "closing_date": "2025-12-31"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-park",
  "name": "Example Park",
  "status": "CLOSED_PERM",
  "closing_date": "2025-12-31"
}
```

### Demolish

Mark a park as demolished.

```http
POST /api/parks/{slug}/demolish/
```

**Permissions**: MODERATOR or above

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-park",
  "name": "Example Park",
  "status": "DEMOLISHED"
}
```

### Relocate

Mark a park as relocated.

```http
POST /api/parks/{slug}/relocate/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "new_location_notes": "Optional notes about new location"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-park",
  "name": "Example Park",
  "status": "RELOCATED"
}
```

---

## Ride Transitions

### Open

Open a ride (from CLOSED_TEMP, SBNO, or UNDER_CONSTRUCTION).

```http
POST /api/parks/{park_slug}/rides/{ride_slug}/open/
```

**Permissions**: Authenticated user (CLOSED_TEMP), MODERATOR+ (SBNO)

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-ride",
  "name": "Example Coaster",
  "status": "OPERATING"
}
```

### Close Temporarily

Temporarily close a ride.

```http
POST /api/parks/{park_slug}/rides/{ride_slug}/close_temporarily/
```

**Permissions**: Authenticated user

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-ride",
  "name": "Example Coaster",
  "status": "CLOSED_TEMP"
}
```

### Mark SBNO

Mark a ride as Standing But Not Operating.

```http
POST /api/parks/{park_slug}/rides/{ride_slug}/mark_sbno/
```

**Permissions**: MODERATOR or above

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-ride",
  "name": "Example Coaster",
  "status": "SBNO"
}
```

### Mark Closing

Mark a ride as scheduled for closure.

```http
POST /api/parks/{park_slug}/rides/{ride_slug}/mark_closing/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "closing_date": "2025-12-31",
  "post_closing_status": "DEMOLISHED"
}
```

**Valid post_closing_status values**:
- `SBNO` - Will become Standing But Not Operating
- `CLOSED_PERM` - Will be permanently closed
- `DEMOLISHED` - Will be demolished
- `RELOCATED` - Will be relocated

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-ride",
  "name": "Example Coaster",
  "status": "CLOSING",
  "closing_date": "2025-12-31",
  "post_closing_status": "DEMOLISHED"
}
```

### Close Permanently

Permanently close a ride.

```http
POST /api/parks/{park_slug}/rides/{ride_slug}/close_permanently/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "closing_date": "2025-12-31"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-ride",
  "name": "Example Coaster",
  "status": "CLOSED_PERM",
  "closing_date": "2025-12-31"
}
```

### Demolish

Mark a ride as demolished.

```http
POST /api/parks/{park_slug}/rides/{ride_slug}/demolish/
```

**Permissions**: MODERATOR or above

**Request Body**: None

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-ride",
  "name": "Example Coaster",
  "status": "DEMOLISHED"
}
```

### Relocate

Mark a ride as relocated.

```http
POST /api/parks/{park_slug}/rides/{ride_slug}/relocate/
```

**Permissions**: MODERATOR or above

**Request Body**:
```json
{
  "new_park_slug": "destination-park",
  "notes": "Optional relocation notes"
}
```

**Response** (200 OK):
```json
{
  "id": 123,
  "slug": "example-ride",
  "name": "Example Coaster",
  "status": "RELOCATED"
}
```

---

## Transition History

### Get Object History

Get the state transition history for any object.

```http
GET /api/moderation/history/{content_type}/{object_id}/
```

**Permissions**: MODERATOR or above

**Response** (200 OK):
```json
{
  "count": 3,
  "results": [
    {
      "id": 1,
      "timestamp": "2025-01-10T08:00:00Z",
      "source_state": "PENDING",
      "state": "ESCALATED",
      "transition": "transition_to_escalated",
      "by": {
        "id": 456,
        "username": "moderator"
      },
      "description": null
    },
    {
      "id": 2,
      "timestamp": "2025-01-15T10:30:00Z",
      "source_state": "ESCALATED",
      "state": "APPROVED",
      "transition": "transition_to_approved",
      "by": {
        "id": 789,
        "username": "admin"
      },
      "description": "Approved after escalation review"
    }
  ]
}
```

### Get All History (Admin)

Get all recent transition history across all models.

```http
GET /api/moderation/reports/all_history/
```

**Permissions**: ADMIN or above

**Query Parameters**:
- `page` - Page number (default: 1)
- `page_size` - Items per page (default: 20)
- `model` - Filter by model name (optional)
- `user` - Filter by user ID (optional)
- `from_date` - Filter from date (optional)
- `to_date` - Filter to date (optional)

**Response** (200 OK):
```json
{
  "count": 100,
  "next": "/api/moderation/reports/all_history/?page=2",
  "previous": null,
  "results": [
    {
      "id": 1,
      "content_type": "moderation.editsubmission",
      "object_id": 123,
      "timestamp": "2025-01-15T10:30:00Z",
      "source_state": "PENDING",
      "state": "APPROVED",
      "transition": "transition_to_approved",
      "by": {
        "id": 456,
        "username": "moderator"
      }
    }
  ]
}
```

---

## Mandatory API Rules

1. **Trailing Slashes**: All endpoints MUST include trailing forward slashes
2. **HTTP Methods**: All transitions use POST
3. **Authentication**: All endpoints require valid JWT token
4. **Content-Type**: Request bodies must be `application/json`

## Error Response Format

All error responses follow this format:

```json
{
  "error": "Error code",
  "message": "Human-readable error message",
  "details": {
    "field_name": ["Specific field errors"]
  }
}
```

### Example Error Responses

**Invalid Transition (400)**:
```json
{
  "error": "TRANSITION_NOT_ALLOWED",
  "message": "Cannot transition from APPROVED to REJECTED"
}
```

**Permission Denied (403)**:
```json
{
  "error": "PERMISSION_DENIED",
  "message": "This action requires moderator privileges"
}
```

**Validation Error (422)**:
```json
{
  "error": "VALIDATION_ERROR",
  "message": "Missing required fields",
  "details": {
    "post_closing_status": ["This field is required when marking as CLOSING"]
  }
}
