# DefaultImplementation Attribute

Automatic DI Container registration for interface implementations using attributes.

## Overview

The `#[DefaultImplementation]` attribute enables automatic registration of classes as default implementations for interfaces in the DI container. This eliminates boilerplate container configuration while maintaining framework patterns (readonly, final, composition).

## Features

- **Optional Interface Parameter**: Specify interface explicitly or auto-detect
- **Auto-Detection**: Automatically uses first implemented interface if not specified
- **Validation**: Ensures class actually implements the specified/detected interface
- **Singleton Registration**: All bindings are registered as singletons
- **Framework Integration**: Fully integrated with Discovery system and caching
- **Type Safety**: Full type safety with descriptive validation exceptions

## Usage

### Explicit Interface Specification

```php
interface UserRepository
{
    public function findById(string $id): ?User;
}

#[DefaultImplementation(UserRepository::class)]
final readonly class DatabaseUserRepository implements UserRepository
{
    public function __construct(
        private readonly DatabaseConnection $db
    ) {}

    public function findById(string $id): ?User
    {
        // Implementation
    }
}

// Container automatically binds UserRepository::class => DatabaseUserRepository::class
$userRepo = $container->get(UserRepository::class); // DatabaseUserRepository instance
```

### Auto-Detection (Single Interface)

```php
interface LoggerInterface
{
    public function log(string $message): void;
}

#[DefaultImplementation]  // No explicit interface - auto-detects LoggerInterface
final readonly class FileLogger implements LoggerInterface
{
    public function log(string $message): void
    {
        // Implementation
    }
}

// Container automatically binds LoggerInterface::class => FileLogger::class
$logger = $container->get(LoggerInterface::class); // FileLogger instance
```

### Auto-Detection (Multiple Interfaces)

When a class implements multiple interfaces, the **first interface** is used for auto-detection:

```php
#[DefaultImplementation]  // Auto-detects LoggerInterface (first interface)
final readonly class AppLogger implements LoggerInterface, Stringable
{
    public function log(string $message): void
    {
        echo "[LOG] $message\n";
    }

    public function __toString(): string
    {
        return 'AppLogger';
    }
}

// Binds: LoggerInterface::class => AppLogger::class
```

## Validation

The attribute validates interface implementation at application bootstrap:

### Valid Usage

```php
// ✓ Explicit interface that class implements
#[DefaultImplementation(UserRepository::class)]
final readonly class DatabaseUserRepository implements UserRepository {}

// ✓ Auto-detect with single interface
#[DefaultImplementation]
final readonly class FileLogger implements LoggerInterface {}

// ✓ Auto-detect with multiple interfaces (uses first)
#[DefaultImplementation]
final readonly class AppLogger implements LoggerInterface, Stringable {}
```

### Invalid Usage (Throws Exceptions)

```php
// ✗ Explicit interface NOT implemented
#[DefaultImplementation(LoggerInterface::class)]
final readonly class BadRepository implements UserRepository {}
// Throws: DefaultImplementationException
// "Class 'BadRepository' has #[DefaultImplementation] for interface 'LoggerInterface'
//  but does not implement that interface"

// ✗ Auto-detect with NO interfaces
#[DefaultImplementation]
final readonly class PlainClass {}
// Throws: DefaultImplementationException
// "Class 'PlainClass' has #[DefaultImplementation] without explicit interface but
//  implements no interfaces. Either specify an interface explicitly or ensure the
//  class implements at least one interface."

// ✗ Interface does not exist
#[DefaultImplementation(NonExistentInterface::class)]
final readonly class SomeClass implements ActualInterface {}
// Throws: DefaultImplementationException
// "Class 'SomeClass' has #[DefaultImplementation] for interface 'NonExistentInterface'
//  which does not exist"
```

## How It Works

### 1. Discovery Phase

During application bootstrap, the Discovery system scans for `#[DefaultImplementation]` attributes:

```php
// Automatic discovery via UnifiedDiscoveryService
$discoveryService = $container->get(UnifiedDiscoveryService::class);
$results = $discoveryService->discover();
```

### 2. Processing Phase

The `DefaultImplementationProcessor` processes discovered attributes:

```php
// Automatically called in DiscoveryServiceBootstrapper
$processor = new DefaultImplementationProcessor($container);
$processor->process($results); // Registers all bindings
```

### 3. Container Registration

Each valid attribute creates a singleton binding:

```php
// For each DefaultImplementation attribute:
$container->singleton($interface, $className);
```

### 4. Resolution

Classes are instantiated on-demand by the container:

```php
$instance = $container->get(UserRepository::class);
// Returns: DatabaseUserRepository instance (singleton)
```

## Integration Points

### Discovery System

The attribute is automatically discovered via the framework's Discovery system:

1. **Attribute Scanning**: `UnifiedDiscoveryService` finds all `#[DefaultImplementation]` attributes
2. **Caching**: Discovered attributes are cached along with other discovery results
3. **Processor Execution**: `DefaultImplementationProcessor` runs after discovery
4. **Before Initializers**: Processed **before** `#[Initializer]` methods to ensure dependencies are available

### Bootstrap Flow

```
AppBootstrapper
  └─> ContainerBootstrapper
       └─> DiscoveryServiceBootstrapper
            ├─> UnifiedDiscoveryService::discover()
            ├─> DefaultImplementationProcessor::process()  ← Registers bindings
            └─> InitializerProcessor::processInitializers() ← Can depend on bindings
```

## Framework Compliance

The implementation follows all Custom PHP Framework principles:

✓ **No Inheritance**: `DefaultImplementationProcessor` is final and uses composition
✓ **Readonly Classes**: Attribute and processor are readonly
✓ **Value Objects**: Uses `ClassName`, `DiscoveredAttribute`, `DiscoveryRegistry`
✓ **Explicit DI**: Constructor injection throughout
✓ **Attribute-Driven**: Convention over configuration
✓ **Discovery Integration**: Automatic registration via framework's attribute system

## Testing

Comprehensive tests verify all scenarios:

```bash
# Run test suite
php tests/debug/test-default-implementation.php
```

**Test Coverage**:
- ✓ Explicit interface specification
- ✓ Auto-detect single interface
- ✓ Auto-detect multiple interfaces (uses first)
- ✓ Validation: interface not implemented
- ✓ Validation: no interfaces implemented
- ✓ Validation: interface does not exist
- ✓ Multiple bindings in one registry
- ✓ Singleton registration verification

## File Structure

```
src/Framework/DI/
├── Attributes/
│   └── DefaultImplementation.php          # Attribute class
├── DefaultImplementationProcessor.php     # Registration processor
└── Exceptions/
    └── DefaultImplementationException.php # Validation exceptions

src/Framework/Discovery/
└── DiscoveryServiceBootstrapper.php       # Integration point (modified)

tests/debug/
└── test-default-implementation.php        # Comprehensive test suite
```

## API Reference

### `#[DefaultImplementation]`

**Attribute**

```php
#[Attribute(Attribute::TARGET_CLASS)]
final readonly class DefaultImplementation
{
    public function __construct(
        public ?string $interface = null
    ) {}
}
```

**Parameters**:
- `$interface` (optional): Interface class-string. If `null`, auto-detect first interface.

**Target**: `CLASS`

### `DefaultImplementationProcessor`

**Processor Class**

```php
final readonly class DefaultImplementationProcessor
{
    public function __construct(
        private readonly Container $container
    ) {}

    public function process(DiscoveryRegistry $registry): int;
}
```

**Methods**:
- `process(DiscoveryRegistry $registry): int` - Processes attributes and registers bindings. Returns count of registered bindings.

### `DefaultImplementationException`

**Exception Class**

```php
final class DefaultImplementationException extends RuntimeException
{
    public static function doesNotImplementInterface(
        string $className,
        string $interface
    ): self;

    public static function noInterfacesImplemented(
        string $className
    ): self;

    public static function interfaceDoesNotExist(
        string $className,
        string $interface
    ): self;
}
```

## Best Practices

### When to Use

✓ **Service Implementations**: Default implementations for repository, service interfaces
✓ **Infrastructure Adapters**: Database, cache, HTTP client implementations
✓ **Domain Services**: Business logic services implementing domain interfaces
✓ **Framework Extensions**: Custom implementations of framework interfaces

### When NOT to Use

✗ **Multiple Implementations**: When you need multiple implementations of same interface (use explicit binding)
✗ **Conditional Logic**: When implementation choice depends on runtime configuration (use Initializers)
✗ **Non-Singleton Scopes**: When you need per-request or transient instances (use factories)

### Combining with Initializers

For complex setup, combine with `#[Initializer]`:

```php
interface CacheService {}

#[DefaultImplementation(CacheService::class)]
final readonly class RedisCacheService implements CacheService
{
    public function __construct(
        private readonly RedisConnection $redis
    ) {}
}

final readonly class CacheServiceInitializer
{
    #[Initializer]
    public function initializeRedisConnection(): RedisConnection
    {
        // Complex Redis connection setup
        return new RedisConnection(/* config */);
    }
}

// DefaultImplementation registered first, then Initializer runs
// RedisCacheService can depend on RedisConnection from Initializer
```

## Performance

- **Discovery Overhead**: Negligible - scanned once during bootstrap and cached
- **Resolution Overhead**: Zero - standard container resolution (singleton pattern)
- **Memory Impact**: Minimal - only stores bindings in container registry
- **Cache Integration**: Full cache support - discovered once, cached for subsequent requests

## Troubleshooting

### "Class does not implement interface"

**Problem**: Class marked with explicit interface but doesn't actually implement it.

**Solution**: Either implement the interface or remove the explicit parameter to auto-detect.

### "Must implement at least one interface"

**Problem**: Class marked with `#[DefaultImplementation]` but implements no interfaces.

**Solution**: Either implement an interface or remove the attribute.

### "Interface does not exist"

**Problem**: Explicit interface parameter references non-existent interface.

**Solution**: Fix the interface class-string or ensure the interface is loaded.

### "Multiple implementations conflict"

**Problem**: Multiple classes have `#[DefaultImplementation]` for same interface.

**Behavior**: Last processed binding wins (discovery order dependent).

**Solution**: Remove attribute from all but one implementation, or use explicit container binding.

## Migration Guide

### From Manual Container Binding

**Before**:
```php
// In Initializer or bootstrap
$container->singleton(UserRepository::class, DatabaseUserRepository::class);
$container->singleton(LoggerInterface::class, FileLogger::class);
```

**After**:
```php
// Add attributes to implementation classes
#[DefaultImplementation(UserRepository::class)]
final readonly class DatabaseUserRepository implements UserRepository {}

#[DefaultImplementation(LoggerInterface::class)]
final readonly class FileLogger implements LoggerInterface {}

// Bindings happen automatically - remove manual registration
```

### From Service Provider Pattern

**Before**:
```php
final readonly class ServiceProvider
{
    public function register(Container $container): void
    {
        $container->singleton(UserRepository::class, DatabaseUserRepository::class);
        $container->singleton(LoggerInterface::class, FileLogger::class);
    }
}
```

**After**:
```php
// Add attributes to implementation classes
#[DefaultImplementation(UserRepository::class)]
final readonly class DatabaseUserRepository implements UserRepository {}

#[DefaultImplementation]  // Auto-detect
final readonly class FileLogger implements LoggerInterface {}

// Remove ServiceProvider - attribute handles registration
```

## Future Enhancements

Potential future improvements:

- **Conditional Registration**: `#[DefaultImplementation(when: 'production')]`
- **Priority System**: `#[DefaultImplementation(priority: 10)]` for multiple implementations
- **Scope Control**: `#[DefaultImplementation(scope: 'transient')]` for non-singleton instances
- **Tag System**: `#[DefaultImplementation(tags: ['database', 'read-only'])]` for grouped registration

## Related Documentation

- [Framework Architecture](architecture.md)
- [Dependency Injection](../Framework/DI/README.md)
- [Discovery System](../Framework/Discovery/README.md)
- [Attribute Patterns](naming-conventions.md#attributes)
