package com.isidroid.spot.di

import android.content.Context
import android.content.SharedPreferences
import com.google.gson.Gson
import com.isidroid.core.DiDebuggableBuild
import com.isidroid.core.DiMock
import com.isidroid.network.ApiCacheControlInterceptor
import com.isidroid.network.ApiServerUrl
import com.isidroid.network.ApiTokenInterceptor
import com.isidroid.network.createRetrofitApiClient
import com.isidroid.spot.data.source.local.dao.PrintProfileDao
import com.isidroid.spot.data.source.local.dao.SpotDao
import com.isidroid.spot.data.source.local.source.PrintProfileLocalSource
import com.isidroid.spot.data.source.local.source.SpotLocalSource
import com.isidroid.spot.data.source.remote.ApiSpot
import com.isidroid.spot.data.source.remote.MockInterceptor
import com.isidroid.spot.data.source.remote.source.SpotNetworkSource
import com.isidroid.spot.repository.ActiveSpotRepository
import com.isidroid.spot.repository.ActiveSpotRepositoryImpl
import com.isidroid.spot.repository.SpotRepository
import com.isidroid.spot.repository.SpotRepositoryImpl
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import javax.inject.Qualifier
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
internal object SpotModule {
    @Provides @Singleton
    fun provideSpotNetworkSource(api: ApiSpot) = SpotNetworkSource(api)

    @Provides @Singleton
    fun provideSpotLocalSource(dao: SpotDao) = SpotLocalSource(dao)

    @Provides @Singleton
    fun providePrintProfileLocalSource(dao: PrintProfileDao) = PrintProfileLocalSource(dao)

    @Provides @Singleton
    fun provideSpotRepository(
        spotLocalSource: SpotLocalSource,
        spotNetworkSource: SpotNetworkSource,
        printProfileLocalSource: PrintProfileLocalSource
    ): SpotRepository = SpotRepositoryImpl(spotNetworkSource, spotLocalSource, printProfileLocalSource)

    @Provides @Singleton
    fun provideActiveSpotRepository(
        spotLocalSource: SpotLocalSource,
        printProfileLocalSource: PrintProfileLocalSource,
        prefs: SharedPreferences
    ): ActiveSpotRepository = ActiveSpotRepositoryImpl(spotLocalSource, printProfileLocalSource, prefs)

    @Provides @DiSpotMockInterceptor
    fun provideMockInterceptor(
        @ApplicationContext context: Context,
        @DiMock isMock: Boolean
    ): Interceptor = MockInterceptor(context, isMock)

    @Singleton @Provides
    fun provideApiSpot(
        @ApiServerUrl serverUrl: String,
        @DiDebuggableBuild isDebugBuild: Boolean,
        @ApiTokenInterceptor authInterceptor: Interceptor,
        @DiSpotMockInterceptor mockInterceptor: Interceptor,
        @ApiCacheControlInterceptor cacheInterceptor: Interceptor,
        gson: Gson
    ) = createRetrofitApiClient(
        baseUrl = serverUrl,
        cl = ApiSpot::class.java,
        logLevel = HttpLoggingInterceptor.Level.BODY,
        gson = gson,
        isDebugBuild = isDebugBuild,
        interceptors = listOf(authInterceptor, mockInterceptor, cacheInterceptor)
    )
}

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
internal annotation class DiSpotMockInterceptor