package de.krisenvorrat.app.ui.item

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import de.krisenvorrat.app.data.db.entity.CategoryEntity
import de.krisenvorrat.app.data.db.entity.ItemEntity
import de.krisenvorrat.app.data.db.entity.LocationEntity
import de.krisenvorrat.app.domain.repository.CategoryRepository
import de.krisenvorrat.app.domain.repository.ItemRepository
import de.krisenvorrat.app.domain.repository.LocationRepository
import de.krisenvorrat.app.domain.model.ItemFormPrefill
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.serialization.json.Json
import java.time.LocalDate
import java.util.UUID
import javax.inject.Inject

internal data class ItemFormUiState(
    val isEditMode: Boolean = false,
    val itemId: String = "",
    val name: String = "",
    val categoryId: Int? = null,
    val quantity: String = "",
    val unit: String = "",
    val unitPrice: String = "",
    val kcalPerKg: String = "",
    val expiryDate: LocalDate? = null,
    val locationId: Int? = null,
    val notes: String = "",
    val categories: List<CategoryEntity> = emptyList(),
    val locations: List<LocationEntity> = emptyList(),
    val validationErrors: Map<String, String> = emptyMap(),
    val isSaving: Boolean = false,
    val isSaved: Boolean = false,
    val isLoading: Boolean = false
)

@HiltViewModel
internal class ItemFormViewModel @Inject constructor(
    private val itemRepository: ItemRepository,
    private val categoryRepository: CategoryRepository,
    private val locationRepository: LocationRepository,
    savedStateHandle: SavedStateHandle
) : ViewModel() {

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

    private val editItemId: String? = savedStateHandle.get<String>("itemId")
    private val prefillJson: String? = savedStateHandle.get<String>("prefillJson")
    private var _pendingCategoryName: String? = null
    private val jsonParser = Json { ignoreUnknownKeys = true }

    init {
        loadDropdownData()
        if (editItemId != null) {
            loadItem(editItemId)
        } else if (prefillJson != null) {
            applyPrefill(prefillJson)
        }
    }

    private fun loadDropdownData() {
        viewModelScope.launch {
            categoryRepository.getAll().collect { categories ->
                _uiState.update { it.copy(categories = categories) }
                val pending = _pendingCategoryName
                if (pending != null) {
                    val match = categories.find { it.name.equals(pending, ignoreCase = true) }
                    if (match != null) {
                        _uiState.update { it.copy(categoryId = match.id) }
                        _pendingCategoryName = null
                    }
                }
            }
        }
        viewModelScope.launch {
            locationRepository.getAll().collect { locations ->
                _uiState.update { state ->
                    val autoLocationId = if (locations.size == 1 && state.locationId == null) {
                        locations.first().id
                    } else {
                        state.locationId
                    }
                    state.copy(locations = locations, locationId = autoLocationId)
                }
            }
        }
        if (editItemId == null) {
            viewModelScope.launch {
                try {
                    val lastLocationId = itemRepository.getLastUsedLocationId()
                    if (lastLocationId != null) {
                        _uiState.update { state ->
                            val isValid = state.locations.any { it.id == lastLocationId }
                            if (state.locationId == null && isValid) state.copy(locationId = lastLocationId)
                            else state
                        }
                    }
                } catch (_: Exception) {}
            }
        }
    }

    private fun applyPrefill(json: String) {
        try {
            val prefill = jsonParser.decodeFromString<ItemFormPrefill>(json)
            _uiState.update { state ->
                state.copy(
                    name = prefill.name,
                    unit = prefill.unit,
                    kcalPerKg = prefill.kcalPerKg?.toString() ?: "",
                    notes = prefill.notes
                )
            }
            if (prefill.suggestedCategoryName.isNotBlank()) {
                _pendingCategoryName = prefill.suggestedCategoryName
            }
        } catch (_: Exception) {
            // Prefill-Fehler ignorieren
        }
    }

    private fun loadItem(itemId: String) {
        _uiState.update { it.copy(isLoading = true) }
        viewModelScope.launch {
            try {
                val item = itemRepository.getById(itemId)
                if (item != null) {
                    _uiState.update {
                        it.copy(
                            isEditMode = true,
                            itemId = item.id,
                            name = item.name,
                            categoryId = item.categoryId,
                            quantity = item.quantity.toBigDecimal().stripTrailingZeros().toPlainString(),
                            unit = item.unit,
                            unitPrice = item.unitPrice.toBigDecimal().stripTrailingZeros().toPlainString(),
                            kcalPerKg = item.kcalPerKg?.toString() ?: "",
                            expiryDate = item.expiryDate,
                            locationId = item.locationId,
                            notes = item.notes,
                            isLoading = false
                        )
                    }
                } else {
                    _uiState.update { it.copy(isLoading = false) }
                }
            } catch (_: Exception) {
                _uiState.update { it.copy(isLoading = false) }
            }
        }
    }

    fun updateName(value: String) {
        _uiState.update { it.copy(name = value, validationErrors = it.validationErrors - "name") }
    }

    fun updateCategoryId(value: Int) {
        _uiState.update { it.copy(categoryId = value, validationErrors = it.validationErrors - "categoryId") }
    }

    fun updateQuantity(value: String) {
        _uiState.update { it.copy(quantity = value, validationErrors = it.validationErrors - "quantity") }
    }

    fun updateUnit(value: String) {
        _uiState.update { it.copy(unit = value) }
    }

    fun updateUnitPrice(value: String) {
        _uiState.update { it.copy(unitPrice = value) }
    }

    fun updateKcalPerKg(value: String) {
        _uiState.update { it.copy(kcalPerKg = value) }
    }

    fun updateExpiryDate(value: LocalDate?) {
        _uiState.update { it.copy(expiryDate = value) }
    }

    fun updateLocationId(value: Int) {
        _uiState.update { it.copy(locationId = value, validationErrors = it.validationErrors - "locationId") }
    }

    fun updateNotes(value: String) {
        _uiState.update { it.copy(notes = value) }
    }

    fun save() {
        val state = _uiState.value
        val errors = validate(state)
        if (errors.isNotEmpty()) {
            _uiState.update { it.copy(validationErrors = errors) }
            return
        }

        _uiState.update { it.copy(isSaving = true) }

        val item = ItemEntity(
            id = if (state.isEditMode) state.itemId else UUID.randomUUID().toString(),
            name = state.name.trim(),
            categoryId = state.categoryId!!,
            quantity = state.quantity.toDouble(),
            unit = state.unit.trim(),
            unitPrice = state.unitPrice.toDoubleOrNull() ?: 0.0,
            kcalPerKg = state.kcalPerKg.toIntOrNull(),
            expiryDate = state.expiryDate,
            locationId = state.locationId!!,
            notes = state.notes.trim(),
            lastUpdated = System.currentTimeMillis()
        )

        viewModelScope.launch {
            try {
                if (state.isEditMode) {
                    itemRepository.update(item)
                } else {
                    itemRepository.insert(item)
                }
                _uiState.update { it.copy(isSaving = false, isSaved = true) }
            } catch (_: Exception) {
                _uiState.update { it.copy(isSaving = false) }
            }
        }
    }

    private fun validate(state: ItemFormUiState): Map<String, String> {
        val errors = mutableMapOf<String, String>()

        if (state.name.isBlank()) {
            errors["name"] = "Name ist erforderlich"
        }

        val quantity = state.quantity.toDoubleOrNull()
        if (quantity == null || quantity <= 0) {
            errors["quantity"] = "Menge muss größer als 0 sein"
        }

        if (state.categoryId == null) {
            errors["categoryId"] = "Kategorie ist erforderlich"
        }

        if (state.locationId == null) {
            errors["locationId"] = "Lagerort ist erforderlich"
        }

        return errors
    }
}
