# Error Handling & Debugging

This guide covers error handling patterns and debugging strategies in the framework.

## Exception Handling

All custom exceptions in the framework must extend `FrameworkException` to ensure consistent error handling, logging, and recovery mechanisms.

### The FrameworkException System

The framework provides a sophisticated exception system with:
- **ExceptionContext**: Rich context information for debugging
- **ErrorCode**: Categorized error codes with recovery hints
- **RetryAfter**: Support for recoverable operations
- **Fluent Interface**: Easy context building

### Creating Custom Exceptions

```php
namespace App\Domain\User\Exceptions;

use App\Framework\Exception\FrameworkException;
use App\Framework\Exception\Core\DatabaseErrorCode;
use App\Framework\Exception\ExceptionContext;

final class UserNotFoundException extends FrameworkException
{
    public static function byId(UserId $id): self
    {
        return self::create(
            DatabaseErrorCode::ENTITY_NOT_FOUND,
            "User with ID '{$id->toString()}' not found"
        )->withData([
            'user_id' => $id->toString(),
            'search_type' => 'by_id'
        ]);
    }

    public static function byEmail(Email $email): self
    {
        $context = ExceptionContext::forOperation('user.lookup', 'UserRepository')
            ->withData(['email' => $email->getMasked()]);

        return self::fromContext(
            "User with email not found",
            $context,
            DatabaseErrorCode::ENTITY_NOT_FOUND
        );
    }
}
```

### Using ErrorCode Enums

The framework provides category-specific error code enums for better organization and type safety:

```php
use App\Framework\Exception\Core\DatabaseErrorCode;
use App\Framework\Exception\Core\AuthErrorCode;
use App\Framework\Exception\Core\HttpErrorCode;
use App\Framework\Exception\Core\SecurityErrorCode;
use App\Framework\Exception\Core\ValidationErrorCode;

// Database errors
DatabaseErrorCode::CONNECTION_FAILED
DatabaseErrorCode::QUERY_FAILED
DatabaseErrorCode::TRANSACTION_FAILED
DatabaseErrorCode::CONSTRAINT_VIOLATION

// Authentication errors
AuthErrorCode::CREDENTIALS_INVALID
AuthErrorCode::TOKEN_EXPIRED
AuthErrorCode::SESSION_EXPIRED
AuthErrorCode::ACCOUNT_LOCKED

// HTTP errors
HttpErrorCode::BAD_REQUEST
HttpErrorCode::NOT_FOUND
HttpErrorCode::METHOD_NOT_ALLOWED
HttpErrorCode::RATE_LIMIT_EXCEEDED

// Security errors
SecurityErrorCode::CSRF_TOKEN_INVALID
SecurityErrorCode::SQL_INJECTION_DETECTED
SecurityErrorCode::XSS_DETECTED
SecurityErrorCode::PATH_TRAVERSAL_DETECTED

// Validation errors
ValidationErrorCode::INVALID_INPUT
ValidationErrorCode::REQUIRED_FIELD_MISSING
ValidationErrorCode::BUSINESS_RULE_VIOLATION
ValidationErrorCode::INVALID_FORMAT

// Using error codes in exceptions:
throw FrameworkException::create(
    DatabaseErrorCode::QUERY_FAILED,
    "Failed to execute user query"
)->withContext(
    ExceptionContext::forOperation('user.find', 'UserRepository')
        ->withData(['query' => 'SELECT * FROM users WHERE id = ?'])
        ->withDebug(['bind_params' => [$userId]])
);
```

### Exception Context Building

```php
// Method 1: Using factory methods
$exception = FrameworkException::forOperation(
    'payment.process',
    'PaymentService',
    'Payment processing failed',
    HttpErrorCode::BAD_GATEWAY
)->withData([
    'amount' => $amount->toArray(),
    'gateway' => 'stripe',
    'customer_id' => $customerId
])->withMetadata([
    'attempt' => 1,
    'idempotency_key' => $idempotencyKey
]);

// Method 2: Building context separately
$context = ExceptionContext::empty()
    ->withOperation('order.validate', 'OrderService')
    ->withData([
        'order_id' => $orderId,
        'total' => $total->toDecimal()
    ])
    ->withDebug([
        'validation_rules' => ['min_amount', 'max_items'],
        'failed_rule' => 'min_amount'
    ]);

throw FrameworkException::fromContext(
    'Order validation failed',
    $context,
    ValidationErrorCode::BUSINESS_RULE_VIOLATION
);
```

### Recoverable Exceptions

```php
// Creating recoverable exceptions with retry hints
final class RateLimitException extends FrameworkException
{
    public static function exceeded(int $retryAfter): self
    {
        return self::create(
            HttpErrorCode::RATE_LIMIT_EXCEEDED,
            'API rate limit exceeded'
        )->withRetryAfter($retryAfter)
         ->withData(['retry_after_seconds' => $retryAfter]);
    }
}

// Using in code
try {
    $response = $apiClient->request($endpoint);
} catch (RateLimitException $e) {
    if ($e->isRecoverable()) {
        $waitTime = $e->getRetryAfter();
        // Schedule retry after $waitTime seconds
    }
    throw $e;
}
```

### Exception Categories

```php
// Check exception category for handling strategies
try {
    $result = $operation->execute();
} catch (FrameworkException $e) {
    if ($e->isCategory('AUTH')) {
        // Handle authentication errors
        return $this->redirectToLogin();
    }

    if ($e->isCategory('VAL')) {
        // Handle validation errors
        return $this->validationErrorResponse($e);
    }

    if ($e->isErrorCode(DatabaseErrorCode::CONNECTION_FAILED)) {
        // Handle specific database connection errors
        $this->notifyOps($e);
    }

    throw $e;
}
```

### Simple Exceptions for Quick Use

```php
// When you don't need the full context system
throw FrameworkException::simple('Quick error message');

// With previous exception
} catch (\PDOException $e) {
    throw FrameworkException::simple(
        'Database operation failed',
        $e,
        500
    );
}
```

### Exception Data Sanitization

The framework automatically sanitizes sensitive data in exceptions:

```php
// Sensitive keys are automatically redacted
$exception->withData([
    'username' => 'john@example.com',
    'password' => 'secret123',  // Will be logged as '[REDACTED]'
    'api_key' => 'sk_live_...' // Will be logged as '[REDACTED]'
]);
```

### Best Practices

1. **Always extend FrameworkException** for custom exceptions
2. **Use ErrorCode enum** for categorizable errors
3. **Provide rich context** with operation, component, and data
4. **Use factory methods** for consistent exception creation
5. **Sanitize sensitive data** (automatic for common keys)
6. **Make exceptions domain-specific** (UserNotFoundException vs generic NotFoundException)
7. **Include recovery hints** for recoverable errors

## Logging Best Practices

TODO: Document logging patterns and levels

## Debug Strategies

TODO: Document debugging approaches and tools

## Error Recovery Patterns

TODO: Document error recovery and graceful degradation

## Common Error Scenarios

TODO: List common errors and solutions