# Dependency Injection Architecture

## Provider Dependency Graph

```
┌─────────────────────────────────────────────────────────────────────┐
│                         PRESENTATION LAYER                          │
│                         (UI State Management)                        │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ depends on
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                          DOMAIN LAYER                                │
│                        (Business Logic)                              │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ depends on
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                          DATA LAYER                                  │
│                   (Repositories & Data Sources)                      │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ depends on
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                          CORE LAYER                                  │
│                    (Infrastructure Services)                         │
└─────────────────────────────────────────────────────────────────────┘
```

## Complete Provider Dependency Tree

### Authentication Feature

```
secureStorageProvider (Core - Singleton)
          │
          ├──> apiClientProvider (Core - Singleton)
          │             │
          │             └──> authRemoteDataSourceProvider
          │                             │
          └─────────────────────────────┴──> authRepositoryProvider
                                                      │
                       ┌──────────────────────────────┼────────────────────────────┐
                       │                              │                            │
             loginUseCaseProvider          logoutUseCaseProvider      checkAuthStatusUseCaseProvider
                       │                              │                            │
                       └──────────────────────────────┴────────────────────────────┘
                                                      │
                                              authProvider (StateNotifier)
                                                      │
                       ┌──────────────────────────────┼────────────────────────────┐
                       │                              │                            │
           isAuthenticatedProvider          currentUserProvider          authErrorProvider
```

### Warehouse Feature

```
apiClientProvider (Core - Singleton)
          │
          └──> warehouseRemoteDataSourceProvider
                          │
                          └──> warehouseRepositoryProvider
                                          │
                                          └──> getWarehousesUseCaseProvider
                                                          │
                                                          └──> warehouseProvider (StateNotifier)
                                                                          │
                               ┌──────────────────────────────────────────┼────────────────────────────────┐
                               │                                          │                                │
                   warehousesListProvider                  selectedWarehouseProvider          isWarehouseLoadingProvider
```

### Products Feature

```
apiClientProvider (Core - Singleton)
          │
          └──> productsRemoteDataSourceProvider
                          │
                          └──> productsRepositoryProvider
                                          │
                                          └──> getProductsUseCaseProvider
                                                          │
                                                          └──> productsProvider (StateNotifier)
                                                                          │
                               ┌──────────────────────────────────────────┼────────────────────────────────┐
                               │                                          │                                │
                   productsListProvider                      operationTypeProvider              isProductsLoadingProvider
```

## Layer-by-Layer Architecture

### 1. Core Layer (Infrastructure)

**Purpose**: Provide foundational services that all features depend on

**Providers**:
- `secureStorageProvider` - Manages encrypted storage
- `apiClientProvider` - HTTP client with auth interceptors

**Characteristics**:
- Singleton instances
- No business logic
- Pure infrastructure
- Used by all features

**Example**:
```dart
final secureStorageProvider = Provider<SecureStorage>((ref) {
  return SecureStorage();
});

final apiClientProvider = Provider<ApiClient>((ref) {
  final secureStorage = ref.watch(secureStorageProvider);
  return ApiClient(secureStorage);
});
```

### 2. Data Layer

**Purpose**: Handle data operations - API calls, local storage, caching

**Components**:
- **Remote Data Sources**: Make API calls
- **Repositories**: Coordinate data sources, convert models to entities

**Providers**:
- `xxxRemoteDataSourceProvider` - API client wrappers
- `xxxRepositoryProvider` - Repository implementations

**Characteristics**:
- Depends on Core layer
- Implements Domain interfaces
- Handles data transformation
- Manages errors (exceptions → failures)

**Example**:
```dart
// Data Source
final authRemoteDataSourceProvider = Provider<AuthRemoteDataSource>((ref) {
  final apiClient = ref.watch(apiClientProvider);
  return AuthRemoteDataSourceImpl(apiClient);
});

// Repository
final authRepositoryProvider = Provider<AuthRepository>((ref) {
  final remoteDataSource = ref.watch(authRemoteDataSourceProvider);
  final secureStorage = ref.watch(secureStorageProvider);
  return AuthRepositoryImpl(
    remoteDataSource: remoteDataSource,
    secureStorage: secureStorage,
  );
});
```

### 3. Domain Layer (Business Logic)

**Purpose**: Encapsulate business rules and use cases

**Components**:
- **Entities**: Pure business objects
- **Repository Interfaces**: Define data contracts
- **Use Cases**: Single-purpose business operations

**Providers**:
- `xxxUseCaseProvider` - Business logic encapsulation

**Characteristics**:
- No external dependencies (pure Dart)
- Depends only on abstractions
- Contains business rules
- Reusable across features
- Testable in isolation

**Example**:
```dart
final loginUseCaseProvider = Provider<LoginUseCase>((ref) {
  final repository = ref.watch(authRepositoryProvider);
  return LoginUseCase(repository);
});

final getWarehousesUseCaseProvider = Provider<GetWarehousesUseCase>((ref) {
  final repository = ref.watch(warehouseRepositoryProvider);
  return GetWarehousesUseCase(repository);
});
```

### 4. Presentation Layer (UI State)

**Purpose**: Manage UI state and handle user interactions

**Components**:
- **State Classes**: Immutable state containers
- **State Notifiers**: Mutable state managers
- **Derived Providers**: Computed state values

**Providers**:
- `xxxProvider` (StateNotifier) - Main state management
- `isXxxLoadingProvider` - Loading state
- `xxxErrorProvider` - Error state
- `xxxListProvider` - Data lists

**Characteristics**:
- Depends on Domain layer
- Manages UI state
- Handles user actions
- Notifies UI of changes
- Can depend on multiple use cases

**Example**:
```dart
// Main state notifier
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
  final loginUseCase = ref.watch(loginUseCaseProvider);
  final logoutUseCase = ref.watch(logoutUseCaseProvider);
  final checkAuthStatusUseCase = ref.watch(checkAuthStatusUseCaseProvider);
  final getCurrentUserUseCase = ref.watch(getCurrentUserUseCaseProvider);

  return AuthNotifier(
    loginUseCase: loginUseCase,
    logoutUseCase: logoutUseCase,
    checkAuthStatusUseCase: checkAuthStatusUseCase,
    getCurrentUserUseCase: getCurrentUserUseCase,
  );
});

// Derived providers
final isAuthenticatedProvider = Provider<bool>((ref) {
  final authState = ref.watch(authProvider);
  return authState.isAuthenticated;
});
```

## Data Flow Patterns

### 1. User Action Flow (Write Operation)

```
┌──────────────┐
│   UI Widget  │
└──────┬───────┘
       │ User taps button
       ▼
┌──────────────────────┐
│  ref.read(provider   │
│    .notifier)        │
│    .someMethod()     │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  StateNotifier       │
│  - Set loading state │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  Use Case            │
│  - Validate input    │
│  - Business logic    │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  Repository          │
│  - Coordinate data   │
│  - Error handling    │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  Data Source         │
│  - API call          │
│  - Parse response    │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  API Client          │
│  - HTTP request      │
│  - Add auth token    │
└──────┬───────────────┘
       │
       │ Response ←─────
       ▼
┌──────────────────────┐
│  StateNotifier       │
│  - Update state      │
│  - Notify listeners  │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  UI Widget           │
│  - Rebuild with      │
│    new state         │
└──────────────────────┘
```

### 2. State Observation Flow (Read Operation)

```
┌──────────────────────┐
│  UI Widget           │
│  ref.watch(provider) │
└──────┬───────────────┘
       │ Subscribes to
       ▼
┌──────────────────────┐
│  StateNotifier       │
│  Current State       │
└──────┬───────────────┘
       │ State changes
       ▼
┌──────────────────────┐
│  UI Widget           │
│  Automatically       │
│  rebuilds            │
└──────────────────────┘
```

## Provider Types Usage

### Provider (Immutable Services)

**Use for**: Services, repositories, use cases, utilities

```dart
final myServiceProvider = Provider<MyService>((ref) {
  final dependency = ref.watch(dependencyProvider);
  return MyService(dependency);
});
```

**Lifecycle**: Created once, lives forever (unless autoDispose)

### StateNotifierProvider (Mutable State)

**Use for**: Managing feature state that changes over time

```dart
final myStateProvider = StateNotifierProvider<MyNotifier, MyState>((ref) {
  final useCase = ref.watch(useCaseProvider);
  return MyNotifier(useCase);
});
```

**Lifecycle**: Created on first access, disposed when no longer used

### Derived Providers (Computed Values)

**Use for**: Computed values from other providers

```dart
final derivedProvider = Provider<DerivedData>((ref) {
  final state = ref.watch(stateProvider);
  return computeValue(state);
});
```

**Lifecycle**: Recomputed when dependencies change

## Best Practices by Layer

### Core Layer
✅ Keep providers pure and stateless
✅ Use singleton pattern
✅ No business logic
❌ Don't depend on feature providers
❌ Don't manage mutable state

### Data Layer
✅ Implement domain interfaces
✅ Convert models ↔ entities
✅ Handle all exceptions
✅ Use Either<Failure, T> return type
❌ Don't expose models to domain
❌ Don't contain business logic

### Domain Layer
✅ Pure Dart (no Flutter dependencies)
✅ Single responsibility per use case
✅ Validate input
✅ Return Either<Failure, T>
❌ Don't know about UI
❌ Don't know about data sources

### Presentation Layer
✅ Manage UI-specific state
✅ Call multiple use cases if needed
✅ Transform data for display
✅ Handle navigation logic
❌ Don't access data sources directly
❌ Don't perform business logic

## Testing Strategy

### Unit Testing

**Core Layer**: Test utilities and services
```dart
test('SecureStorage saves token', () async {
  final storage = SecureStorage();
  await storage.saveAccessToken('token');
  expect(await storage.getAccessToken(), 'token');
});
```

**Domain Layer**: Test use cases with mock repositories
```dart
test('LoginUseCase returns user on success', () async {
  final mockRepo = MockAuthRepository();
  when(mockRepo.login(any)).thenAnswer((_) async => Right(mockUser));

  final useCase = LoginUseCase(mockRepo);
  final result = await useCase(loginRequest);

  expect(result.isRight(), true);
});
```

**Presentation Layer**: Test state notifiers
```dart
test('AuthNotifier sets authenticated on login', () async {
  final container = ProviderContainer(
    overrides: [
      loginUseCaseProvider.overrideWithValue(mockLoginUseCase),
    ],
  );

  await container.read(authProvider.notifier).login('user', 'pass');

  expect(container.read(isAuthenticatedProvider), true);
});
```

### Widget Testing

```dart
testWidgets('Login page shows error on failure', (tester) async {
  await tester.pumpWidget(
    ProviderScope(
      overrides: [
        authRepositoryProvider.overrideWithValue(mockAuthRepository),
      ],
      child: MaterialApp(home: LoginPage()),
    ),
  );

  // Interact with widget
  await tester.tap(find.text('Login'));
  await tester.pump();

  // Verify error is shown
  expect(find.text('Invalid credentials'), findsOneWidget);
});
```

## Performance Optimization

### 1. Use Derived Providers
Instead of computing in build():
```dart
// ❌ Bad - computes every rebuild
@override
Widget build(BuildContext context, WidgetRef ref) {
  final warehouses = ref.watch(warehousesListProvider);
  final ngWarehouses = warehouses.where((w) => w.isNGWareHouse).toList();
  return ListView(...);
}

// ✅ Good - computed once per state change
final ngWarehousesProvider = Provider<List<WarehouseEntity>>((ref) {
  final warehouses = ref.watch(warehousesListProvider);
  return warehouses.where((w) => w.isNGWareHouse).toList();
});

@override
Widget build(BuildContext context, WidgetRef ref) {
  final ngWarehouses = ref.watch(ngWarehousesProvider);
  return ListView(...);
}
```

### 2. Use select() for Partial State
```dart
// ❌ Bad - rebuilds on any state change
final authState = ref.watch(authProvider);
final isLoading = authState.isLoading;

// ✅ Good - rebuilds only when isLoading changes
final isLoading = ref.watch(authProvider.select((s) => s.isLoading));
```

### 3. Use autoDispose for Temporary Providers
```dart
final temporaryProvider = Provider.autoDispose<MyService>((ref) {
  final service = MyService();

  ref.onDispose(() {
    service.dispose();
  });

  return service;
});
```

## Common Patterns

### Pattern: Feature Initialization
```dart
@override
void initState() {
  super.initState();
  Future.microtask(() {
    ref.read(warehouseProvider.notifier).loadWarehouses();
  });
}
```

### Pattern: Conditional Navigation
```dart
ref.listen<AuthState>(authProvider, (previous, next) {
  if (next.isAuthenticated && !(previous?.isAuthenticated ?? false)) {
    Navigator.pushReplacementNamed(context, '/home');
  }
});
```

### Pattern: Error Handling
```dart
ref.listen<String?>(authErrorProvider, (previous, next) {
  if (next != null) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(next)),
    );
  }
});
```

### Pattern: Pull-to-Refresh
```dart
RefreshIndicator(
  onRefresh: () async {
    await ref.read(warehouseProvider.notifier).refresh();
  },
  child: ListView(...),
)
```

## Dependency Injection Benefits

1. **Testability**: Easy to mock dependencies
2. **Maintainability**: Clear dependency tree
3. **Scalability**: Add features without touching existing code
4. **Flexibility**: Swap implementations easily
5. **Readability**: Explicit dependencies
6. **Type Safety**: Compile-time checks
7. **Hot Reload**: Works seamlessly with Flutter
8. **DevTools**: Inspect state in real-time

## Summary

This DI architecture provides:
- Clear separation of concerns
- Predictable data flow
- Easy testing at all levels
- Type-safe dependency injection
- Reactive state management
- Scalable feature structure

For more details, see:
- [README.md](./README.md) - Comprehensive guide
- [QUICK_REFERENCE.md](./QUICK_REFERENCE.md) - Quick lookup
