package com.isidroid.job_sender.di

import android.content.Context
import com.google.gson.Gson
import com.isidroid.core.DiDebuggableBuild
import com.isidroid.core.DiMock
import com.isidroid.job.repository.JobRepository
import com.isidroid.job_sender.SendJobEventCollectorFlow
import com.isidroid.job_sender.data.source.local.SendJobDao
import com.isidroid.job_sender.data.source.local.SendJobLocalSource
import com.isidroid.job_sender.data.source.remote.MockInterceptor
import com.isidroid.job_sender.data.source.remote.SendJobNetworkSource
import com.isidroid.job_sender.data.source.remote.api.ApiCommand
import com.isidroid.job_sender.data.source.remote.api.ApiUpload
import com.isidroid.job_sender.repository.JobSendRepository
import com.isidroid.job_sender.repository.JobSendRepositoryImpl
import com.isidroid.network.ApiCacheControlInterceptor
import com.isidroid.network.ApiServerUrl
import com.isidroid.network.ApiTokenInterceptor
import com.isidroid.network.createRetrofitApiClient
import com.isidroid.rendering.repository.RenderRepository
import com.isidroid.spot.repository.SpotRepository
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
object JobSenderModule {
    @Provides @Singleton
    fun provideSendJobLocalSource(dao: SendJobDao) = SendJobLocalSource(dao)

    @Provides @Singleton
    fun provideSendJobNetworkSource(apiUpload: ApiUpload, apiCommand: ApiCommand, @DiMock isMock: Boolean) = SendJobNetworkSource(apiUpload, apiCommand, isMock)

    @Provides @Singleton
    fun provideJobSendRepository(
        @ApplicationContext context: Context,
        renderRepository: RenderRepository,
        spotRepository: SpotRepository,
        printJobRepository: JobRepository,
        sendJobLocalSource: SendJobLocalSource,
        sendJobNetworkSource: SendJobNetworkSource,
        eventCollector: SendJobEventCollectorFlow,
    ): JobSendRepository = JobSendRepositoryImpl(context, renderRepository, spotRepository, printJobRepository, sendJobLocalSource, sendJobNetworkSource, eventCollector)

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

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

    @Singleton @Provides
    fun provideApiUpload(
        @ApiServerUrl serverUrl: String,
        @DiDebuggableBuild isDebugBuild: Boolean,
        @ApiTokenInterceptor authInterceptor: Interceptor,
        @DiJobSenderMockInterceptor mockInterceptor: Interceptor,
        @ApiCacheControlInterceptor cacheInterceptor: Interceptor,
        gson: Gson
    ) = createRetrofitApiClient(
        baseUrl = serverUrl,
        cl = ApiUpload::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 DiJobSenderMockInterceptor