package de.ypchat.android.ui

import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import de.ypchat.android.data.repository.ChatRepository
import de.ypchat.android.data.repository.ChatState
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.toRequestBody

class ChatViewModel(private val repository: ChatRepository) : ViewModel() {
    val state: StateFlow<ChatState> = repository.state

    init {
        viewModelScope.launch { repository.restoreSession() }
    }

    fun login(userName: String, gender: String, age: Int, country: String) {
        viewModelScope.launch { repository.login(userName, gender, age, country) }
    }

    fun loadCountries() {
        viewModelScope.launch { repository.loadCountries() }
    }

    fun logout() {
        viewModelScope.launch { repository.logout() }
    }

    fun openConversation(userName: String) = repository.openConversation(userName)
    fun closeConversation() = repository.closeConversation()
    fun sendMessage(text: String) = repository.sendMessage(text)
    fun setImageUploadMessage(message: String) = repository.setImageUploadState(false, message)
    fun sendImage(context: Context, uri: Uri) {
        val target = state.value.currentConversation ?: return
        viewModelScope.launch {
            val resolver = context.applicationContext.contentResolver
            val mimeType = resolver.getType(uri) ?: "image/*"
            repository.setImageUploadState(true)
            val bytes = resolver.openInputStream(uri)?.use { it.readBytes() }
            if (bytes == null) {
                repository.setImageUploadState(false, "Image could not be opened")
                return@launch
            }
            if (bytes.size > MAX_IMAGE_BYTES) {
                repository.setImageUploadState(false, "Image exceeds 5 MB")
                return@launch
            }

            val fileName = resolver.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null)?.use { cursor ->
                val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                if (cursor.moveToFirst() && nameIndex >= 0) cursor.getString(nameIndex) else null
            } ?: "ypchat-image"

            val body = bytes.toRequestBody(mimeType.toMediaTypeOrNull())
            val part = MultipartBody.Part.createFormData("image", fileName, body)
            runCatching { repository.uploadImage(part) }
                .onSuccess { response ->
                    val payload = response.body()
                    if (response.isSuccessful && payload?.success == true && !payload.code.isNullOrBlank() && !payload.url.isNullOrBlank()) {
                        repository.sendImage(target, payload.code, payload.url)
                        repository.setImageUploadState(false, "Image uploaded")
                    } else {
                        repository.setImageUploadState(false, payload?.error ?: "Image upload failed")
                    }
                }
                .onFailure { error ->
                    repository.setImageUploadState(false, error.message ?: "Image upload failed")
                }
        }
    }

    fun search(name: String, minAge: Int?, maxAge: Int?, countries: List<String>, genders: List<String>) {
        repository.search(name.takeIf { it.isNotBlank() }, minAge, maxAge, countries, genders)
    }
    fun requestInbox() = repository.requestInbox()
    fun requestHistory() = repository.requestHistory()
    fun loadFeedback() {
        viewModelScope.launch { repository.loadFeedback() }
    }

    fun submitFeedback(comment: String) {
        viewModelScope.launch { repository.submitFeedback(comment) }
    }

    fun loadFeedbackAdminStatus() {
        viewModelScope.launch { repository.loadFeedbackAdminStatus() }
    }

    fun loginFeedbackAdmin(username: String, password: String) {
        viewModelScope.launch { repository.loginFeedbackAdmin(username, password) }
    }

    fun logoutFeedbackAdmin() {
        viewModelScope.launch { repository.logoutFeedbackAdmin() }
    }

    fun deleteFeedback(id: String) {
        viewModelScope.launch { repository.deleteFeedback(id) }
    }

    fun loadPartners() {
        viewModelScope.launch { repository.loadPartners() }
    }

    fun blockCurrentUser() = state.value.currentConversation?.let(repository::blockUser)
    fun unblockCurrentUser() = state.value.currentConversation?.let(repository::unblockUser)

    private companion object {
        const val MAX_IMAGE_BYTES = 5 * 1024 * 1024
    }
}

class ChatViewModelFactory(private val repository: ChatRepository) : ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return ChatViewModel(repository) as T
    }
}
