package de.krisenvorrat.app.ui.camera

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import de.krisenvorrat.app.data.remote.OpenAiVisionService
import de.krisenvorrat.app.di.IoDispatcher
import de.krisenvorrat.app.domain.model.ItemFormPrefill
import de.krisenvorrat.app.domain.model.SettingsKeys
import de.krisenvorrat.app.domain.repository.SettingsRepository
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.util.Base64
import javax.inject.Inject

@HiltViewModel
internal class CameraViewModel @Inject constructor(
    private val openAiVisionService: OpenAiVisionService,
    private val settingsRepository: SettingsRepository,
    @IoDispatcher private val ioDispatcher: CoroutineDispatcher,
    @ApplicationContext private val appContext: Context
) : ViewModel() {

    private val _uiState = MutableStateFlow(CameraUiState())
    val uiState: StateFlow<CameraUiState> = _uiState.asStateFlow()

    init {
        checkApiKey()
    }

    private fun checkApiKey() {
        viewModelScope.launch {
            val apiKey = settingsRepository.getValue(SettingsKeys.OPENAI_API_KEY) ?: ""
            _uiState.update { it.copy(hasApiKey = apiKey.isNotBlank()) }
        }
    }

    fun onPhotoCaptured(uri: Uri) {
        _uiState.update {
            it.copy(
                capturedImageUri = uri,
                capturedBitmap = null,
                recognizedItems = emptyList(),
                selectedItems = emptySet(),
                errorMessage = null
            )
        }
        viewModelScope.launch {
            val bitmap: Bitmap? = withContext(ioDispatcher) {
                try {
                    appContext.contentResolver.openInputStream(uri)?.use { BitmapFactory.decodeStream(it) }
                } catch (_: Exception) {
                    null
                }
            }
            _uiState.update { it.copy(capturedBitmap = bitmap) }
        }
    }

    fun analyzePhoto() {
        val uri = _uiState.value.capturedImageUri
        if (uri == null) {
            _uiState.update { it.copy(errorMessage = "Kein Foto aufgenommen") }
            return
        }
        viewModelScope.launch {
            _uiState.update { it.copy(isAnalyzing = true, errorMessage = null) }
            try {
                val apiKey = settingsRepository.getValue(SettingsKeys.OPENAI_API_KEY) ?: ""
                if (apiKey.isBlank()) {
                    _uiState.update {
                        it.copy(
                            isAnalyzing = false,
                            errorMessage = "Bitte OpenAI API-Key in den Einstellungen hinterlegen"
                        )
                    }
                    return@launch
                }

                val bytes = withContext(ioDispatcher) {
                    try {
                        appContext.contentResolver.openInputStream(uri)?.use { it.readBytes() }
                    } catch (_: Exception) {
                        null
                    }
                }

                if (bytes == null) {
                    _uiState.update {
                        it.copy(isAnalyzing = false, errorMessage = "Foto konnte nicht gelesen werden")
                    }
                    return@launch
                }

                val base64 = Base64.getEncoder().encodeToString(bytes)
                val items = openAiVisionService.analyzeImage(base64, apiKey)

                if (items.isEmpty()) {
                    _uiState.update {
                        it.copy(isAnalyzing = false, errorMessage = "Keine Artikel erkannt")
                    }
                } else {
                    _uiState.update {
                        it.copy(isAnalyzing = false, recognizedItems = items, selectedItems = emptySet())
                    }
                }
            } catch (e: Exception) {
                _uiState.update {
                    it.copy(
                        isAnalyzing = false,
                        errorMessage = "Analyse fehlgeschlagen. Bitte prüfe die Netzwerkverbindung und den API-Key."
                    )
                }
            }
        }
    }

    fun toggleItemSelection(index: Int) {
        _uiState.update { state ->
            val updated = if (state.selectedItems.contains(index)) {
                state.selectedItems - index
            } else {
                state.selectedItems + index
            }
            state.copy(selectedItems = updated)
        }
    }

    fun selectAll() {
        _uiState.update { state ->
            state.copy(selectedItems = state.recognizedItems.indices.toSet())
        }
    }

    fun onAddFirstSelectedItem() {
        val state = _uiState.value
        val firstIndex = state.selectedItems.minOrNull() ?: return
        val item = state.recognizedItems.getOrNull(firstIndex) ?: return
        val json = Json.encodeToString(ItemFormPrefill.serializer(), item)
        _uiState.update { it.copy(navigateToPrefillJson = json) }
    }

    fun onNavigationHandled() {
        _uiState.update { it.copy(navigateToPrefillJson = null) }
    }

    fun clearError() {
        _uiState.update { it.copy(errorMessage = null) }
    }
}
