package de.trainingstagebuch.app.viewmodel

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import de.trainingstagebuch.app.R
import de.trainingstagebuch.app.repository.PredefinedActivitiesResult
import de.trainingstagebuch.app.repository.PredefinedActivityActionResult
import de.trainingstagebuch.app.repository.PredefinedActivityDetailResult
import de.trainingstagebuch.app.repository.PredefinedActivityInput
import de.trainingstagebuch.app.repository.PredefinedActivityItem
import de.trainingstagebuch.app.services.AppServices
import de.trainingstagebuch.app.utils.ErrorMessageFormatter
import de.trainingstagebuch.app.utils.UiText
import de.trainingstagebuch.app.utils.ViewModelStateUtils
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class PredefinedActivitiesViewModel(application: Application) : AndroidViewModel(application) {
    private val predefinedService = AppServices.predefinedActivitiesService

    private val _state = MutableStateFlow(PredefinedActivitiesUiState())
    val state: StateFlow<PredefinedActivitiesUiState> = _state.asStateFlow()

    init {
        load()
    }

    fun load() {
        viewModelScope.launch {
            _state.update { it.copy(loading = true, errorMessage = null) }
            when (val result = predefinedService.loadAll()) {
                is PredefinedActivitiesResult.Success -> {
                    _state.update {
                        it.copy(
                            loading = false,
                            activities = sortActivities(result.items),
                            successMessage = null
                        )
                    }
                }

                is PredefinedActivitiesResult.Error -> {
                    _state.update {
                        it.copy(
                            loading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun onSearchQueryChanged(value: String) {
        _state.update { it.copy(searchQuery = value) }
        val query = value.trim()
        if (query.length < 2) {
            _state.update { it.copy(searchResults = emptyList(), searching = false) }
            return
        }
        viewModelScope.launch {
            _state.update { it.copy(searching = true) }
            when (val result = predefinedService.search(query, limit = 50)) {
                is PredefinedActivitiesResult.Success -> {
                    _state.update {
                        it.copy(
                            searching = false,
                            searchResults = sortActivities(result.items)
                        )
                    }
                }
                is PredefinedActivitiesResult.Error -> {
                    _state.update {
                        it.copy(
                            searching = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun clearSearch() {
        _state.update { it.copy(searchQuery = "", searchResults = emptyList(), searching = false) }
    }

    fun startCreate() {
        _state.update {
            it.copy(
                selectedActivityId = null,
                editModel = PredefinedActivityEditor(),
                mergeSourceId = "",
                mergeTargetId = ""
            )
        }
    }

    fun selectActivity(activityId: String) {
        viewModelScope.launch {
            _state.update { it.copy(loadingDetail = true) }
            when (val result = predefinedService.loadOne(activityId)) {
                is PredefinedActivityDetailResult.Success -> {
                    _state.update {
                        it.copy(
                            loadingDetail = false,
                            selectedActivityId = activityId,
                            editModel = result.item.toEditor()
                        )
                    }
                }
                is PredefinedActivityDetailResult.Error -> {
                    _state.update {
                        it.copy(
                            loadingDetail = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun onEditNameChanged(value: String) = updateEditor { it.copy(name = value) }
    fun onEditCodeChanged(value: String) = updateEditor { it.copy(code = value) }
    fun onEditDurationChanged(value: String) = updateEditor { it.copy(duration = value) }
    fun onEditDurationTextChanged(value: String) = updateEditor { it.copy(durationText = value) }
    fun onEditDescriptionChanged(value: String) = updateEditor { it.copy(description = value) }
    fun onEditImageLinkChanged(value: String) = updateEditor { it.copy(imageLink = value) }
    fun onEditDrawingDataChanged(value: String) = updateEditor { it.copy(drawingData = value) }

    fun cancelEdit() {
        _state.update { it.copy(selectedActivityId = null, editModel = null) }
    }

    fun save() {
        save(forceDuplicate = false)
    }

    fun confirmSaveDuplicateCode() {
        save(forceDuplicate = true)
    }

    fun dismissDuplicateCodeDialog() {
        _state.update {
            it.copy(
                pendingDuplicateCode = null,
                pendingDuplicateExistingLabel = null
            )
        }
    }

    private fun save(forceDuplicate: Boolean) {
        val model = _state.value.editModel ?: return
        if (model.name.trim().isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.predefined_name_required)) }
            return
        }
        val normalizedCode = model.code.trim().lowercase()
        if (
            !forceDuplicate &&
            model.id.isNullOrBlank() &&
            normalizedCode.isNotBlank()
        ) {
            val duplicate = _state.value.activities.firstOrNull { existing ->
                existing.code?.trim()?.lowercase() == normalizedCode
            }
            if (duplicate != null) {
                _state.update {
                    it.copy(
                        pendingDuplicateCode = model.code.trim(),
                        pendingDuplicateExistingLabel = buildString {
                            if (!duplicate.code.isNullOrBlank()) {
                                append("[")
                                append(duplicate.code)
                                append("] ")
                            }
                            append(duplicate.name)
                        }
                    )
                }
                return
            }
        }
        val input = PredefinedActivityInput(
            name = model.name.trim(),
            code = model.code.trim().ifBlank { null },
            duration = model.duration.trim().ifBlank { null },
            durationText = model.durationText.trim().ifBlank { null },
            description = model.description.trim().ifBlank { null },
            imageLink = model.imageLink.trim().ifBlank { null },
            drawingData = model.drawingData.trim().ifBlank { null }
        )
        viewModelScope.launch {
            _state.update { it.copy(actionLoading = true, errorMessage = null) }
            val result = if (model.id.isNullOrBlank()) {
                predefinedService.create(input)
            } else {
                predefinedService.update(model.id, input)
            }
            when (result) {
                is PredefinedActivityDetailResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            editModel = result.item.toEditor(),
                            selectedActivityId = result.item.id,
                            successMessage = UiText(R.string.predefined_saved),
                            pendingDuplicateCode = null,
                            pendingDuplicateExistingLabel = null
                        )
                    }
                    load()
                }
                is PredefinedActivityDetailResult.Error -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun onMergeSourceChanged(value: String) {
        _state.update { it.copy(mergeSourceId = value) }
    }

    fun onMergeTargetChanged(value: String) {
        _state.update { it.copy(mergeTargetId = value) }
    }

    fun mergeSelected() {
        val sourceId = _state.value.mergeSourceId
        val targetId = _state.value.mergeTargetId
        if (sourceId.isBlank() || targetId.isBlank() || sourceId == targetId) {
            _state.update { it.copy(errorMessage = UiText(R.string.predefined_merge_invalid)) }
            return
        }
        viewModelScope.launch {
            _state.update { it.copy(actionLoading = true, errorMessage = null) }
            when (val result = predefinedService.merge(sourceId, targetId)) {
                is PredefinedActivityActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            mergeSourceId = "",
                            mergeTargetId = "",
                            successMessage = UiText(R.string.predefined_merge_success)
                        )
                    }
                    load()
                }
                is PredefinedActivityActionResult.Error -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun deduplicate() {
        viewModelScope.launch {
            _state.update { it.copy(actionLoading = true, errorMessage = null) }
            when (val result = predefinedService.deduplicate()) {
                is PredefinedActivityActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            successMessage = UiText(R.string.predefined_deduplicate_success)
                        )
                    }
                    load()
                }
                is PredefinedActivityActionResult.Error -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun deleteImage(imageId: String) {
        val activityId = _state.value.editModel?.id ?: return
        viewModelScope.launch {
            _state.update { it.copy(actionLoading = true, errorMessage = null) }
            when (val result = predefinedService.deleteImage(activityId, imageId)) {
                is PredefinedActivityActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            successMessage = UiText(R.string.predefined_image_deleted)
                        )
                    }
                    selectActivity(activityId)
                    load()
                }
                is PredefinedActivityActionResult.Error -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    private fun updateEditor(mapper: (PredefinedActivityEditor) -> PredefinedActivityEditor) {
        _state.update { state ->
            val current = state.editModel ?: PredefinedActivityEditor()
            state.copy(editModel = mapper(current))
        }
    }

    private fun sortActivities(items: List<PredefinedActivityItem>): List<PredefinedActivityItem> {
        return items.sortedWith(
            compareBy<PredefinedActivityItem> {
                it.code.isNullOrBlank()
            }.thenBy { it.code?.lowercase().orEmpty() }
                .thenBy { it.name.lowercase() }
        )
    }

    private fun PredefinedActivityItem.toEditor(): PredefinedActivityEditor {
        return PredefinedActivityEditor(
            id = id,
            name = name,
            code = code.orEmpty(),
            duration = duration.orEmpty(),
            durationText = durationText.orEmpty(),
            description = description.orEmpty(),
            imageLink = imageLink.orEmpty(),
            drawingData = drawingData.orEmpty(),
            images = images
        )
    }
}

data class PredefinedActivitiesUiState(
    val loading: Boolean = false,
    val loadingDetail: Boolean = false,
    val actionLoading: Boolean = false,
    val activities: List<PredefinedActivityItem> = emptyList(),
    val searchQuery: String = "",
    val searchResults: List<PredefinedActivityItem> = emptyList(),
    val searching: Boolean = false,
    val selectedActivityId: String? = null,
    val editModel: PredefinedActivityEditor? = null,
    val mergeSourceId: String = "",
    val mergeTargetId: String = "",
    val errorMessage: UiText? = null,
    val successMessage: UiText? = null,
    val pendingDuplicateCode: String? = null,
    val pendingDuplicateExistingLabel: String? = null
)

data class PredefinedActivityEditor(
    val id: String? = null,
    val name: String = "",
    val code: String = "",
    val duration: String = "",
    val durationText: String = "",
    val description: String = "",
    val imageLink: String = "",
    val drawingData: String = "",
    val images: List<de.trainingstagebuch.app.repository.PredefinedActivityImage> = emptyList()
)
