package top.yeij.cyrene.viewmodel

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import top.yeij.cyrene.data.local.PreferencesDataStore
import top.yeij.cyrene.data.remote.DynamicUrlInterceptor
import top.yeij.cyrene.domain.repository.AuthRepository
import top.yeij.cyrene.domain.repository.ChatRepository
import top.yeij.cyrene.voice.stt.SttManager

class SettingsViewModel(
    private val authRepository: AuthRepository,
    private val preferencesDataStore: PreferencesDataStore,
    private val dynamicUrlInterceptor: DynamicUrlInterceptor,
    private val chatRepository: ChatRepository,
    private val sttManager: SttManager,
) {

    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

    private val _baseUrl = MutableStateFlow("")
    val baseUrl: StateFlow<String> = _baseUrl.asStateFlow()

    private val _themeMode = MutableStateFlow("auto")
    val themeMode: StateFlow<String> = _themeMode.asStateFlow()

    private val _wakeWord = MutableStateFlow("昔涟")
    val wakeWord: StateFlow<String> = _wakeWord.asStateFlow()

    private val _username = MutableStateFlow("")
    val username: StateFlow<String> = _username.asStateFlow()

    private val _dashScopeApiKey = MutableStateFlow("")
    val dashScopeApiKey: StateFlow<String> = _dashScopeApiKey.asStateFlow()

    private val _dashScopeEndpoint = MutableStateFlow("wss://dashscope.aliyuncs.com/api-ws/v1/inference")
    val dashScopeEndpoint: StateFlow<String> = _dashScopeEndpoint.asStateFlow()

    private val _dashScopeModel = MutableStateFlow("fun-asr-realtime")
    val dashScopeModel: StateFlow<String> = _dashScopeModel.asStateFlow()

    private val _autoScreenContext = MutableStateFlow(false)
    val autoScreenContext: StateFlow<Boolean> = _autoScreenContext.asStateFlow()

    private val _themeColor = MutableStateFlow("pink")
    val themeColor: StateFlow<String> = _themeColor.asStateFlow()

    private val _enterToSend = MutableStateFlow(false)
    val enterToSend: StateFlow<Boolean> = _enterToSend.asStateFlow()

    private val _typingIndicatorStyle = MutableStateFlow("bubble")
    val typingIndicatorStyle: StateFlow<String> = _typingIndicatorStyle.asStateFlow()

    private val _rootKeepAlive = MutableStateFlow(false)
    val rootKeepAlive: StateFlow<Boolean> = _rootKeepAlive.asStateFlow()

    private val _isLoggedIn = MutableStateFlow(false)
    val isLoggedIn: StateFlow<Boolean> = _isLoggedIn.asStateFlow()

    init {
        scope.launch {
            _isLoggedIn.value = authRepository.isLoggedIn()
        }
        // Single collector for all DataStore preferences — avoids subscriber explosion
        scope.launch {
            preferencesDataStore.autoScreenContext.collect { value ->
                _autoScreenContext.value = value
            }
        }
        scope.launch {
            preferencesDataStore.typingIndicatorStyle.collect { value ->
                _typingIndicatorStyle.value = value
            }
        }
        scope.launch {
            preferencesDataStore.enterToSend.collect { value ->
                _enterToSend.value = value
            }
        }
        scope.launch {
            preferencesDataStore.rootKeepAlive.collect { value ->
                _rootKeepAlive.value = value
            }
        }
        scope.launch {
            preferencesDataStore.themeColor.collect { value ->
                _themeColor.value = value
            }
        }
        scope.launch {
            combine(
                preferencesDataStore.baseUrl,
                preferencesDataStore.themeMode,
                preferencesDataStore.wakeWord,
                preferencesDataStore.username,
                combine(
                    preferencesDataStore.dashScopeApiKey,
                    preferencesDataStore.dashScopeEndpoint,
                    preferencesDataStore.dashScopeModel,
                ) { apiKey, endpoint, model ->
                    Triple(apiKey, endpoint, model)
                },
            ) { baseUrl, themeMode, wakeWord, username, dashScope ->
                baseUrl?.let { url ->
                    if (url.isNotBlank()) {
                        _baseUrl.value = url
                        dynamicUrlInterceptor.baseUrl = url
                    }
                }
                themeMode?.let { _themeMode.value = it }
                wakeWord?.let { word ->
                    if (word.isNotBlank()) _wakeWord.value = word
                }
                username?.let { _username.value = it }
                val (apiKey, endpoint, model) = dashScope
                apiKey?.let { key ->
                    if (key.isNotBlank()) _dashScopeApiKey.value = key
                    sttManager.updateDashScopeApiKey(key)
                }
                endpoint?.let { ep ->
                    if (ep.isNotBlank()) _dashScopeEndpoint.value = ep
                }
                model?.let { m ->
                    if (m.isNotBlank()) _dashScopeModel.value = m
                }
                // Push full config to STT
                sttManager.configureDashScope(
                    apiKey = _dashScopeApiKey.value,
                    endpoint = _dashScopeEndpoint.value,
                    model = _dashScopeModel.value,
                )
            }.collect { }
        }
    }

    fun updateBaseUrlInput(url: String) {
        _baseUrl.value = url
    }

    fun saveBaseUrl(url: String) {
        _baseUrl.value = url
        dynamicUrlInterceptor.baseUrl = url
        scope.launch {
            preferencesDataStore.saveBaseUrl(url)
            chatRepository.reconnectWebSocket()
        }
    }

    fun saveThemeMode(mode: String) {
        _themeMode.value = mode
        scope.launch { preferencesDataStore.saveThemeMode(mode) }
    }

    fun saveWakeWord(word: String) {
        _wakeWord.value = word
        scope.launch { preferencesDataStore.saveWakeWord(word) }
    }

    fun updateDashScopeApiKeyInput(key: String) {
        _dashScopeApiKey.value = key
    }

    fun saveDashScopeApiKey(key: String) {
        _dashScopeApiKey.value = key
        sttManager.updateDashScopeApiKey(key)
        scope.launch { preferencesDataStore.saveDashScopeApiKey(key) }
    }

    fun updateDashScopeEndpointInput(endpoint: String) {
        _dashScopeEndpoint.value = endpoint
    }

    fun saveDashScopeEndpoint(endpoint: String) {
        _dashScopeEndpoint.value = endpoint
        sttManager.configureDashScope(_dashScopeApiKey.value, endpoint, _dashScopeModel.value)
        scope.launch { preferencesDataStore.saveDashScopeEndpoint(endpoint) }
    }

    fun updateDashScopeModelInput(model: String) {
        _dashScopeModel.value = model
    }

    fun saveDashScopeModel(model: String) {
        _dashScopeModel.value = model
        sttManager.configureDashScope(_dashScopeApiKey.value, _dashScopeEndpoint.value, model)
        scope.launch { preferencesDataStore.saveDashScopeModel(model) }
    }

    fun saveAutoScreenContext(enabled: Boolean) {
        _autoScreenContext.value = enabled
        scope.launch { preferencesDataStore.saveAutoScreenContext(enabled) }
    }

    fun saveTypingIndicatorStyle(style: String) {
        _typingIndicatorStyle.value = style
        scope.launch { preferencesDataStore.saveTypingIndicatorStyle(style) }
    }

    fun saveEnterToSend(enabled: Boolean) {
        _enterToSend.value = enabled
        scope.launch { preferencesDataStore.saveEnterToSend(enabled) }
    }

    fun saveThemeColor(color: String) {
        _themeColor.value = color
        scope.launch { preferencesDataStore.saveThemeColor(color) }
    }

    fun saveRootKeepAlive(enabled: Boolean) {
        _rootKeepAlive.value = enabled
        scope.launch { preferencesDataStore.saveRootKeepAlive(enabled) }
    }

    fun clearLocalMessages() {
        scope.launch {
            chatRepository.clearLocalMessages()
        }
    }

    fun logout() {
        scope.launch {
            authRepository.logout()
            _isLoggedIn.value = false
        }
    }
}
