## Domain-Driven Design (DDD) Rules

### Domain Layer - Actions Return Types

**MANDATORY: Actions Must Return Models, Not HTTP Structures**

The Domain Layer must remain pure and agnostic of HTTP/API concerns. This ensures Actions are reusable across different contexts (CLI, Jobs, API, Tests).

#### ❌ INCORRECT Pattern (HTTP-Coupled)

```php
// BAD: Action returns HTTP-specific array structure
namespace Domain\Ipaas\Nodes\Actions;

class CreateApiNode
{
    public static function create(array $validated)
    {
        $apiNode = ApiNode::create($validated);
        
        // ❌ Domain Layer should NOT know about HTTP concepts
        return [
            'success' => true,
            'message' => 'API Node created successfully',
            'record' => $apiNode
        ];
    }
}
```

#### ✅ CORRECT Pattern (Pure Domain)

```php
// GOOD: Action returns pure model or throws exception
namespace Domain\Ipaas\Nodes\Actions;

class CreateApiNode
{
    public static function create(array $validated): ApiNode
    {
        $apiNode = ApiNode::create($validated);
        
        // Additional domain logic here if needed
        
        return $apiNode; // Pure model
    }
}
```

#### Controller Responsibility (Application Layer)

The Application Layer (Controllers) is responsible for transforming Domain models into HTTP responses:

```php
// Controller handles HTTP transformation
namespace App\Http\Controllers\Ipaas\Nodes;

class ApiNodeController extends Controller
{
    public function store(ApiNodeRequest $request)
    {
        try {
            $validated = $request->validated();
            
            // Domain Action returns pure model
            $apiNode = CreateApiNode::create($validated);
            
            // Controller builds HTTP response
            Log::info('Api node created successfully', [
                'node_id' => $apiNode->id,
                'name' => $validated['name'],
                'user_id' => auth()->id(),
                'ip' => request()->ip(),
                'user_agent' => request()->userAgent(),
            ]);
            
            return response()->json([
                'success' => true,
                'record' => $apiNode,
                'message' => 'Api node created successfully'
            ], 201);
            
        } catch (\Exception $e) {
            Log::error('Failed to create api node', [
                'error' => $e->getMessage(),
                'user_id' => auth()->id(),
                'ip' => request()->ip(),
                'user_agent' => request()->userAgent(),
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to create api node: ' . $e->getMessage()
            ], 500);
        }
    }
}
```

#### Exception Handling in Domain Layer

Actions should throw specific exceptions instead of returning error arrays:

```php
// Domain Action throws exceptions
namespace Domain\Ipaas\Nodes\Actions;

use Illuminate\Database\Eloquent\ModelNotFoundException;

class UpdateApiNode
{
    public static function update(array $validated): ApiNode
    {
        $apiNode = ApiNode::findOrFail($validated['id']); // Throws ModelNotFoundException
        
        $apiNode->update($validated);
        
        return $apiNode;
    }
}
```

```php
// Controller catches and transforms to HTTP response
public function update(ApiNodeRequest $request)
{
    try {
        $validated = $request->validated();
        $apiNode = UpdateApiNode::update($validated);
        
        return response()->json([
            'success' => true,
            'record' => $apiNode,
            'message' => 'Api node updated successfully'
        ], 200);
        
    } catch (ModelNotFoundException $e) {
        return response()->json([
            'success' => false,
            'message' => 'Api node not found'
        ], 404);
        
    } catch (\Exception $e) {
        Log::error('Failed to update api node', ['error' => $e->getMessage()]);
        
        return response()->json([
            'success' => false,
            'message' => 'Failed to update api node'
        ], 500);
    }
}
```

#### Benefits of Pure Domain Actions

**✅ Reusability:**
```php
// Same Action works in different contexts

// 1. HTTP Controller
$apiNode = CreateApiNode::create($request->validated());

// 2. Artisan Command
$apiNode = CreateApiNode::create($commandData);

// 3. Queue Job
$apiNode = CreateApiNode::create($jobPayload);

// 4. Unit Test
$apiNode = CreateApiNode::create($testData);
```

**✅ Testability:**
```php
// Unit test focuses on domain logic only
test('creates api node with valid data', function () {
    $data = [
        'name' => 'Test Node',
        'flow_id' => 1,
        'request_type' => 'request',
        // ...
    ];
    
    $apiNode = CreateApiNode::create($data);
    
    expect($apiNode)->toBeInstanceOf(ApiNode::class);
    expect($apiNode->name)->toBe('Test Node');
});
```

**✅ Maintainability:**
- Domain logic changes don't affect HTTP layer
- HTTP response format changes don't affect Domain layer
- Clear separation of concerns

#### Summary: Domain Layer Rules

**MUST:**
- ✅ Return models or collections
- ✅ Throw specific exceptions for errors
- ✅ Contain only business logic
- ✅ Be framework-agnostic (could work outside Laravel)

**MUST NOT:**
- ❌ Return arrays with `success`, `message`, `error` keys
- ❌ Build HTTP responses
- ❌ Access `request()` or `response()` helpers
- ❌ Know about status codes (200, 404, 500)
- ❌ Format data for API consumption

**Application Layer (Controllers) Handles:**
- HTTP request validation
- Domain Action invocation
- Exception catching
- HTTP response building
- Logging with HTTP context (IP, User Agent)
- Status code determination

---

