package com.radiola.di

import android.content.Context
import androidx.room.Room
import com.radiola.data.local.AppDatabase
import com.radiola.data.local.LocalStationDataSource
import com.radiola.data.local.MIGRATION_1_2
import com.radiola.data.local.MIGRATION_2_3
import com.radiola.data.local.MIGRATION_3_4
import com.radiola.data.local.MIGRATION_4_5
import com.radiola.data.local.MIGRATION_5_6
import com.radiola.data.local.MIGRATION_6_7
import com.radiola.data.local.dao.AlarmDao
import com.radiola.data.remote.AuthInterceptor
import com.radiola.data.remote.LrcLibApi
import com.radiola.data.remote.LoveApi
import com.radiola.data.remote.RecordApi
import com.radiola.data.remote.RadiolaApi
import com.radiola.data.repository.AuthRepositoryImpl
import com.radiola.data.repository.ChartsRepositoryImpl
import com.radiola.data.repository.FavoritesRepositoryImpl
import com.radiola.data.repository.LyricsRepositoryImpl
import com.radiola.data.repository.NowPlayingRepositoryImpl
import com.radiola.data.repository.RecordingRepositoryImpl
import com.radiola.data.repository.RegionRepositoryImpl
import com.radiola.data.repository.SettingsRepositoryImpl
import com.radiola.data.repository.StationRepositoryImpl
import com.radiola.data.repository.SyncRepositoryImpl
import com.radiola.data.repository.TrackHistoryRepositoryImpl
import com.radiola.domain.repository.AuthRepository
import com.radiola.domain.repository.ChartsRepository
import com.radiola.domain.repository.FavoritesRepository
import com.radiola.domain.repository.LyricsRepository
import com.radiola.domain.repository.SyncRepository
import com.radiola.domain.repository.NowPlayingRepository
import com.radiola.domain.repository.RecordingRepository
import com.radiola.domain.repository.RegionRepository
import com.radiola.domain.repository.SettingsRepository
import com.radiola.domain.repository.StationRepository
import com.radiola.domain.repository.TrackHistoryRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.kotlinx.serialization.asConverterFactory
import javax.inject.Named
import javax.inject.Singleton

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

    @Provides
    @Singleton
    fun provideJson(): Json = Json {
        ignoreUnknownKeys = true
        coerceInputValues = true
    }

    @Provides
    @Singleton
    fun provideBaseOkHttpClient(): OkHttpClient = OkHttpClient.Builder()
        .connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
        .readTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
        .apply {
            // Логирование каждого HTTP-запроса — только в debug. В релизе это лишний
            // оверхед на каждый вызов и утечка URL/деталей в logcat.
            if (com.radiola.BuildConfig.DEBUG) {
                addInterceptor(HttpLoggingInterceptor().apply {
                    level = HttpLoggingInterceptor.Level.BASIC
                })
            }
        }
        .build()

    @Provides
    @Singleton
    @Named("radiolaClient")
    fun provideRadiolaOkHttpClient(
        baseClient: OkHttpClient,
        authInterceptor: AuthInterceptor
    ): OkHttpClient = baseClient.newBuilder()
        .addInterceptor(authInterceptor)
        .build()

    @Provides
    @Singleton
    @Named("record")
    fun provideRecordRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
        .baseUrl("https://www.radiorecord.ru/")
        .client(okHttpClient)
        .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
        .build()

    @Provides
    @Singleton
    @Named("radiola")
    fun provideRadiolaRetrofit(
        @Named("radiolaClient") okHttpClient: OkHttpClient,
        json: Json
    ): Retrofit = Retrofit.Builder()
        .baseUrl("http://121.127.37.212:3000/")
        .client(okHttpClient)
        .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
        .build()

    @Provides
    @Singleton
    @Named("itunes")
    fun provideItunesRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
        .baseUrl("https://itunes.apple.com/")
        .client(okHttpClient)
        .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
        .build()

    @Provides
    @Singleton
    fun provideItunesApi(@Named("itunes") retrofit: Retrofit): com.radiola.data.remote.ItunesApi =
        retrofit.create(com.radiola.data.remote.ItunesApi::class.java)

    @Provides
    @Singleton
    @Named("lrclib")
    fun provideLrcLibRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
        .baseUrl("https://lrclib.net/")
        .client(okHttpClient)
        .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
        .build()

    @Provides
    @Singleton
    @Named("love")
    fun provideLoveRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
        .baseUrl("https://api.loveradio.ru/api/v1/love-radio/")
        .client(okHttpClient)
        .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
        .build()

    @Provides
    @Singleton
    fun provideLoveApi(@Named("love") retrofit: Retrofit): LoveApi = retrofit.create(LoveApi::class.java)

    @Provides
    @Singleton
    fun provideLrcLibApi(@Named("lrclib") retrofit: Retrofit): LrcLibApi = retrofit.create(LrcLibApi::class.java)

    @Provides
    @Singleton
    fun provideRecordApi(@Named("record") retrofit: Retrofit): RecordApi = retrofit.create(RecordApi::class.java)

    @Provides
    @Singleton
    fun provideRadiolaApi(@Named("radiola") retrofit: Retrofit): RadiolaApi = retrofit.create(RadiolaApi::class.java)

    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext context: Context): AppDatabase =
        Room.databaseBuilder(context, AppDatabase::class.java, "radiola.db")
            .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6, MIGRATION_6_7)
            .build()

    @Provides
    @Singleton
    fun provideAlarmDao(db: AppDatabase): AlarmDao = db.alarmDao()

    @Provides
    @Singleton
    fun provideStationDao(db: AppDatabase): com.radiola.data.local.dao.StationDao = db.stationDao()

    @Provides
    @Singleton
    fun provideLocalStationDataSource(
        @ApplicationContext context: Context,
        json: Json
    ): LocalStationDataSource = LocalStationDataSource(context, json)

    @Provides
    @Singleton
    fun provideStationRepository(impl: StationRepositoryImpl): StationRepository = impl

    @Provides
    @Singleton
    fun provideNowPlayingRepository(impl: NowPlayingRepositoryImpl): NowPlayingRepository = impl

    @Provides
    @Singleton
    fun provideFavoritesRepository(impl: FavoritesRepositoryImpl): FavoritesRepository = impl

    @Provides
    @Singleton
    fun provideTrackHistoryRepository(impl: TrackHistoryRepositoryImpl): TrackHistoryRepository = impl

    @Provides
    @Singleton
    fun provideSettingsRepository(impl: SettingsRepositoryImpl): SettingsRepository = impl

    @Provides
    @Singleton
    fun provideRegionRepository(impl: RegionRepositoryImpl): RegionRepository = impl

    @Provides
    @Singleton
    fun provideRecordingRepository(impl: RecordingRepositoryImpl): RecordingRepository = impl

    @Provides
    @Singleton
    fun provideAuthRepository(impl: AuthRepositoryImpl): AuthRepository = impl

    @Provides
    @Singleton
    fun provideSyncRepository(impl: SyncRepositoryImpl): SyncRepository = impl

    @Provides
    @Singleton
    fun provideChartsRepository(impl: ChartsRepositoryImpl): ChartsRepository = impl

    @Provides
    @Singleton
    fun provideLyricsRepository(impl: LyricsRepositoryImpl): LyricsRepository = impl
}
