# Configuración de la inyección de dependencias

Esta guía explica cómo instanciar y gestionar los repositorios proporcionados por la `redsys-tpv-business-lib`. Aunque puedes instanciar repositorios manualmente, la librería está diseñada para trabajar fluidamente con frameworks de Inyección de Dependencias (DI) como Dagger Hilt.

El núcleo del proceso de instanciación es la clase auxiliar `RepositoryProvider`, que suministra las implementaciones específicas para todas las funcionalidades de la librería.

## Opción 1: Usar Dagger Hilt (Recomendado)

Si tu aplicación utiliza Hilt, debes proporcionar los repositorios como **Singletons**. Esto asegura que tengas una instancia única y compartida de cada repositorio durante todo el ciclo de vida de tu aplicación.

### 1. Crear un módulo Hilt

Crea un nuevo archivo de módulo (p. ej., `AppModule.kt`) anotado con `@Module` y `@InstallIn(SingletonComponent::class)`.

### 2. Proporcionar los repositorios

Copia el siguiente código para proporcionar el `RepositoryProvider` y todos los repositorios de funcionalidades disponibles.

<Callout type="note">

El `RepositoryProvider` requiere el Contexto de la Aplicación y un flag `DEBUG` (para habilitar el registro interno con Timber).

</Callout>

```kotlin
@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
}
```

Ahora puedes inyectar estas interfaces directamente en tus ViewModels o UseCases.

**Ejemplo de uso:**

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

## Opción 2: Inyección manual

Si tu proyecto no utiliza un framework de Inyección de Dependencias, puedes instanciar los repositorios manualmente usando el `RepositoryProvider` o los métodos estáticos `newInstance` en las clases de implementación.

### Usando RepositoryProvider

Puedes crear una instancia única de `RepositoryProvider` (p. ej., en tu clase `Application`) y acceder a los repositorios a través de sus propiedades.

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

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

### Instanciación directa

Alternativamente, puedes crear instancias directamente usando el método estático `newInstance` proporcionado por las clases de implementación (con el prefijo `Psa` por Payment Service Adapter).

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

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

<Callout type="note">

Aunque la instanciación manual funciona para pruebas sencillas, se recomienda usar `RepositoryProvider` o DI para aplicaciones en producción para gestionar mejor la memoria y las dependencias.

</Callout>

## Siguientes pasos

Ahora que tus repositorios están listos, debes proceder al paso más crítico:

* [**Gestión de respuestas y errores**](/es/get-smart/get-smart-sdk/core-concepts/handle-responses-and-errors): Aprende cómo gestionar el envoltorio `RepositoryResult` devuelto por todos estos repositorios.