# Dependency Injection Setup

This guide explains how to instantiate and manage the repositories provided by the `redsys-tpv-business-lib`. While you can instantiate repositories manually, the library is designed to work seamlessly with Dependency Injection (DI) frameworks like Dagger Hilt.

The core of the instantiation process is the `RepositoryProvider` helper class, which supplies the specific implementations for all library features.

## Option 1: Using Dagger Hilt (Recommended)

If your application uses Hilt, you should provide the repositories as **Singletons**. This ensures you have a single, shared instance of each repository throughout your application lifecycle.

### 1. Create a Hilt Module

Create a new module file (e.g., `AppModule.kt`) annotated with `@Module` and `@InstallIn(SingletonComponent::class)`.

### 2. Provide the Repositories

Copy the following code to provide the `RepositoryProvider` and all available feature repositories.

<Callout type="note">

The `RepositoryProvider` requires the Application Context and a `DEBUG` flag (to enable internal logging with Timber).

</Callout>

```
@Module
@InstallIn(SingletonComponent::class)
class AppModule {

    @Provides
    @Singleton
    fun provideRepositoryProvider(@ApplicationContext context: Context): RepositoryProvider {
        // Pass BuildConfig.DEBUG to enable internal Smart SDK logging
        return RepositoryProvider(context, BuildConfig.DEBUG)
    }

    // --- Core Payments & Transactions ---

    @Provides
    @Singleton
    fun provideInitializationRepository(provider: RepositoryProvider): InitializationRepository =
        provider.initializationRepository

    @Provides
    @Singleton
    fun providePaymentRepository(provider: RepositoryProvider): PaymentRepository =
        provider.paymentRepository

    @Provides
    @Singleton
    fun provideTransactionRepository(provider: RepositoryProvider): TransactionRepository =
        provider.transactionRepository

    @Provides
    @Singleton
    fun providePreauthorizationRepository(provider: RepositoryProvider): PreauthorizationRepository =
        provider.preauthorizationRepository

    @Provides
    @Singleton
    fun provideRefundRepository(provider: RepositoryProvider): RefundRepository =
        provider.refundRepository

    // --- Management & Peripherals ---

    @Provides
    @Singleton
    fun provideSessionRepository(provider: RepositoryProvider): SessionRepository =
        provider.sessionRepository

    @Provides
    @Singleton
    fun provideShiftRepository(provider: RepositoryProvider): ShiftRepository =
        provider.shiftRepository

    @Provides
    @Singleton
    fun provideTotalsRepository(provider: RepositoryProvider): TotalsRepository =
        provider.totalsRepository

    @Provides
    @Singleton
    fun providePrinterRepository(provider: RepositoryProvider): PrinterRepository =
        provider.printerRepository

    @Provides
    @Singleton
    fun provideSettingsRepository(provider: RepositoryProvider): SettingsRepository =
        provider.settingsRepository

    // --- Alternative Payment Methods (APMs) & Digital Services ---

    @Provides
    @Singleton
    fun provideBizumRepository(provider: RepositoryProvider): BizumRepository =
        provider.bizumRepository

    @Provides
    @Singleton
    fun provideAlipayRepository(provider: RepositoryProvider): AlipayRepository =
        provider.alipayRepository

    @Provides
    @Singleton
    fun provideWeChatRepository(provider: RepositoryProvider): WeChatRepository =
        provider.weChatRepository

    @Provides
    @Singleton
    fun provideTicketDigitalRepository(provider: RepositoryProvider): TicketDigitalRepository =
        provider.ticketDigitalRepository

    @Provides
    @Singleton
    fun provideAuthRepository(provider: RepositoryProvider): AuthRepository =
        provider.authRepository
}
```

You can now inject these interfaces directly into your ViewModels or UseCases.

**Example Usage:**

```
@HiltViewModel
class PaymentViewModel @Inject constructor(
    private val paymentRepository: PaymentRepository
) : ViewModel() {
    // ...
}
```

## Option 2: Manual Injection

If your project does not use a Dependency Injection framework, you can instantiate the repositories manually using the `RepositoryProvider` or the static `newInstance` methods on the implementation classes.

### Using RepositoryProvider

You can create a single instance of `RepositoryProvider` (e.g., in your `Application` class) and access the repositories through its properties.

```
// In your Application class or a Singleton container
val provider = RepositoryProvider(context, BuildConfig.DEBUG)

val paymentRepo = provider.paymentRepository
val printerRepo = provider.printerRepository
```

### Direct Instantiation

Alternatively, you can create instances directly using the `newInstance` static method provided by the implementation classes (prefixed with `Psa` for Payment Service Adapter).

```
// Example: Creating a TransactionRepository manually
val transactionRepo = PsaTransactionRepository.newInstance(context)

// Example: Creating a PaymentRepository manually
val paymentRepo = PsaPaymentRepository.newInstance(context)
```

<Callout type="note">

While manual instantiation works for simple tests, using `RepositoryProvider` or DI is recommended for production apps to better manage memory and dependencies.

</Callout>

## Next Steps

Now that your repositories are ready, you should proceed to the most critical step:

* [**Handling Responses and Errors**](/en/get-smart/get-smart-sdk/core-concepts/handle-responses-and-errors): Learn how to handle the `RepositoryResult` wrapper returned by all these repositories.