package top.yeij.cyrene.di

import org.koin.android.ext.koin.androidContext
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module
import top.yeij.cyrene.data.local.AppDatabase
import top.yeij.cyrene.data.local.PreferencesDataStore
import top.yeij.cyrene.data.remote.ApiService
import top.yeij.cyrene.data.remote.AuthInterceptor
import top.yeij.cyrene.data.remote.DynamicUrlInterceptor
import top.yeij.cyrene.data.remote.RetrofitClient
import top.yeij.cyrene.data.remote.TokenAuthenticator
import top.yeij.cyrene.data.repository.AuthRepositoryImpl
import top.yeij.cyrene.data.repository.ChatRepositoryImpl
import top.yeij.cyrene.data.repository.IoTRepositoryImpl
import top.yeij.cyrene.domain.repository.AuthRepository
import top.yeij.cyrene.domain.repository.ChatRepository
import top.yeij.cyrene.domain.repository.IoTRepository
import top.yeij.cyrene.domain.usecase.GetConversationsUseCase
import top.yeij.cyrene.domain.usecase.LoginUseCase
import top.yeij.cyrene.domain.usecase.SendMessageUseCase
import top.yeij.cyrene.service.WebSocketService
import top.yeij.cyrene.viewmodel.ChatViewModel
import top.yeij.cyrene.viewmodel.IoTViewModel
import top.yeij.cyrene.viewmodel.OverlayViewModel
import top.yeij.cyrene.viewmodel.ProfileViewModel
import top.yeij.cyrene.viewmodel.SettingsViewModel
import top.yeij.cyrene.util.NotificationHelper
import top.yeij.cyrene.util.VoiceRecorder
import top.yeij.cyrene.voice.stt.BackendSttProvider
import top.yeij.cyrene.voice.stt.DashScopeSttService
import top.yeij.cyrene.voice.stt.SpeechRecognizer
import top.yeij.cyrene.voice.stt.SttManager
import top.yeij.cyrene.voice.tts.TextToSpeechEngine

val appModule = module {

    // Notifications
    single { NotificationHelper(androidContext()) }

    // DataStore
    single { PreferencesDataStore(androidContext()) }

    // Database
    single { AppDatabase.getInstance(androidContext()) }
    single { get<AppDatabase>().conversationDao() }
    single { get<AppDatabase>().messageDao() }

    // Network interceptors
    single { AuthInterceptor() }
    single { DynamicUrlInterceptor() }
    single { TokenAuthenticator(get(), get(), get()) }
    single { RetrofitClient.provideOkHttpClient(get(), get(), get()) }
    single { RetrofitClient.provideRetrofit(get()) }
    single { get<retrofit2.Retrofit>().create(ApiService::class.java) }

    // WebSocket
    single { WebSocketService(get()) }

    // Voice
    single { VoiceRecorder(androidContext()) }
    single { SpeechRecognizer(androidContext()) }
    single { TextToSpeechEngine(androidContext()) }
    single { DashScopeSttService(androidContext()) }
    single { BackendSttProvider(androidContext(), get()) }
    single { SttManager(get(), get(), get()) }

    // Repositories
    single<AuthRepository> { AuthRepositoryImpl(get(), get(), get()) }
    single<ChatRepository> { ChatRepositoryImpl(androidContext() as android.app.Application, get(), get(), get(), get(), get(), get()) }
    single<IoTRepository> { IoTRepositoryImpl(get(), get()) }

    // UseCases
    factory { LoginUseCase(get()) }
    factory { SendMessageUseCase(get()) }
    factory { GetConversationsUseCase(get()) }

    // ViewModels
    viewModel { ChatViewModel(androidContext() as android.app.Application, get(), get(), get(), get()) }
    viewModel { IoTViewModel(get()) }
    viewModel { OverlayViewModel(get(), get(), get()) }
    viewModel { ProfileViewModel(get(), get(), get()) }
    single { SettingsViewModel(get(), get(), get(), get(), get()) }
}
