# Bulk Catalog Delete Endpoint Documentation

## Overview
Generic bulk delete endpoint for catalog entities (makes, models, years, trims, engines) in the admin panel.

## Endpoint
```
DELETE /api/admin/catalog/{entity}/bulk-delete
```

## Path Parameters
- `entity`: Entity type - one of: `makes`, `models`, `years`, `trims`, `engines`

## Request Body
```json
{
  "ids": [1, 2, 3, 4, 5]
}
```

### Validation Rules
- IDs must be an array of positive integers
- At least 1 ID required
- Maximum 100 IDs per batch
- All IDs must be valid integers (not strings or floats)

## Response Codes
- `204 No Content`: All deletions succeeded (no response body)
- `207 Multi-Status`: Some deletions failed (includes response body with details)
- `400 Bad Request`: Invalid entity type or invalid request body
- `401 Unauthorized`: Missing or invalid authentication
- `500 Internal Server Error`: Unexpected server error

## Response Body (207 Multi-Status only)
```json
{
  "deleted": [1, 3, 5],
  "failed": [
    {
      "id": 2,
      "error": "Make 2 not found"
    },
    {
      "id": 4,
      "error": "Cannot delete make with existing models"
    }
  ]
}
```

## Cascade Behavior
The endpoint uses existing single-delete methods which have the following behavior:

### Makes
- **Blocks deletion** if models exist under the make
- Error: "Cannot delete make with existing models"
- **Solution**: Delete all dependent models first

### Models
- **Blocks deletion** if years exist under the model
- Error: "Cannot delete model with existing years"
- **Solution**: Delete all dependent years first

### Years
- **Blocks deletion** if trims exist under the year
- Error: "Cannot delete year with existing trims"
- **Solution**: Delete all dependent trims first

### Trims
- **Blocks deletion** if engines exist under the trim
- Error: "Cannot delete trim with existing engines"
- **Solution**: Delete all dependent engines first

### Engines
- **No cascade restrictions** (leaf entity in hierarchy)

## Deletion Order for Hierarchy
To delete an entire make and all its dependencies:
1. Delete engines first
2. Delete trims
3. Delete years
4. Delete models
5. Delete make last

## Examples

### Example 1: Delete Multiple Engines (Success)
```bash
DELETE /api/admin/catalog/engines/bulk-delete
{
  "ids": [101, 102, 103]
}

Response: 204 No Content
```

### Example 2: Delete Multiple Makes (Partial Failure)
```bash
DELETE /api/admin/catalog/makes/bulk-delete
{
  "ids": [1, 2, 3]
}

Response: 207 Multi-Status
{
  "deleted": [3],
  "failed": [
    {
      "id": 1,
      "error": "Cannot delete make with existing models"
    },
    {
      "id": 2,
      "error": "Make 2 not found"
    }
  ]
}
```

### Example 3: Invalid Entity Type
```bash
DELETE /api/admin/catalog/invalid/bulk-delete
{
  "ids": [1, 2, 3]
}

Response: 400 Bad Request
{
  "error": "Invalid entity type",
  "message": "Entity must be one of: makes, models, years, trims, engines"
}
```

### Example 4: Invalid IDs
```bash
DELETE /api/admin/catalog/makes/bulk-delete
{
  "ids": ["abc", "def"]
}

Response: 400 Bad Request
{
  "error": "Invalid IDs",
  "message": "All IDs must be positive integers"
}
```

## Implementation Details

### Files Modified
1. `/backend/src/features/admin/api/admin.routes.ts` (line 209-212)
   - Added route: `DELETE /admin/catalog/:entity/bulk-delete`
   - Requires admin authentication

2. `/backend/src/features/admin/api/catalog.controller.ts` (line 542-638)
   - Added method: `bulkDeleteCatalogEntity()`
   - Maps entity type to appropriate delete method
   - Processes deletions sequentially
   - Collects successes and failures

3. `/backend/src/features/admin/api/admin.validation.ts` (line 43-49, 57-58)
   - Added `catalogEntitySchema`: Validates entity type
   - Added `bulkDeleteCatalogSchema`: Validates request body
   - Exported types: `CatalogEntity`, `BulkDeleteCatalogInput`

4. `/backend/src/features/admin/domain/admin.types.ts` (line 97-103)
   - Added `BulkDeleteCatalogResponse` interface

### Continue-on-Failure Pattern
The endpoint uses a continue-on-failure pattern:
- One deletion failure does NOT stop the batch
- All deletions are attempted
- Successes and failures are tracked separately
- Final response includes both lists

### Transaction Behavior
- Each individual deletion runs in its own transaction (via service layer)
- If one delete fails, it doesn't affect others
- No rollback of previously successful deletions

## Testing

### Manual Testing with cURL
```bash
# Test valid request (requires auth token)
curl -X DELETE "http://localhost/api/admin/catalog/makes/bulk-delete" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{"ids": [1, 2, 3]}'

# Test invalid entity type
curl -X DELETE "http://localhost/api/admin/catalog/invalid/bulk-delete" \
  -H "Content-Type: application/json" \
  -d '{"ids": [1, 2, 3]}'

# Test empty IDs
curl -X DELETE "http://localhost/api/admin/catalog/makes/bulk-delete" \
  -H "Content-Type: application/json" \
  -d '{"ids": []}'
```

### Expected Audit Log Behavior
Each successful deletion creates a platform change log entry:
- `changeType`: "DELETE"
- `resourceType`: Entity type (makes, models, years, trims, engines)
- `resourceId`: ID of deleted entity
- `changedBy`: Actor's user ID
- `oldValue`: Entity data before deletion
- `newValue`: null

## Security
- Endpoint requires admin authentication (via `fastify.requireAdmin`)
- Actor ID is logged for all operations
- All deletions are audited in platform_change_log table

## Performance Considerations
- Deletions are processed sequentially (not in parallel)
- Each deletion queries the database separately
- Cache invalidation occurs after each successful deletion
- For large batches (50+ items), consider breaking into smaller batches

## Future Enhancements
Potential improvements:
1. Add cascade delete option to automatically delete dependent entities
2. Add dry-run mode to preview what would be deleted
3. Add batch size optimization for better performance
4. Add progress tracking for long-running batches
