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.MIGRATION_7_8 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.RecognizedTrackRepositoryImpl import com.radiola.data.repository.ShazamRepositoryImpl import com.radiola.data.repository.TrackHistoryRepositoryImpl import com.radiola.domain.repository.AuthRepository import com.radiola.domain.repository.RecognizedTrackRepository import com.radiola.domain.repository.ShazamRepository 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) // Распознавание Shazam на бэкенде асинхронное (тянет аудио из потока + // поллит результат ~до 18с) — базового readTimeout 10с не хватает. // Поднимаем таймаут точечно только для этого пути. .addInterceptor { chain -> val req = chain.request() if (req.url.encodedPath.contains("shazam/recognize")) { chain.withReadTimeout(30, java.util.concurrent.TimeUnit.SECONDS) .withConnectTimeout(10, java.util.concurrent.TimeUnit.SECONDS) .proceed(req) } else { chain.proceed(req) } } .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, MIGRATION_7_8) .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 @Provides @Singleton fun provideRecognizedTrackRepository(impl: RecognizedTrackRepositoryImpl): RecognizedTrackRepository = impl @Provides @Singleton fun provideShazamRepository(impl: ShazamRepositoryImpl): ShazamRepository = impl }