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.DiaryActionResult
import de.trainingstagebuch.app.repository.DiaryAccidentItem
import de.trainingstagebuch.app.repository.DiaryAccidentsResult
import de.trainingstagebuch.app.repository.DiaryActivitiesResult
import de.trainingstagebuch.app.repository.DiaryActivityItem
import de.trainingstagebuch.app.repository.DiaryActivityParticipantsResult
import de.trainingstagebuch.app.repository.DiaryAddActivityResult
import de.trainingstagebuch.app.repository.DiaryCreateTagResult
import de.trainingstagebuch.app.repository.DiaryCreateDateResult
import de.trainingstagebuch.app.repository.DiaryDateEntry
import de.trainingstagebuch.app.repository.DiaryDatesResult
import de.trainingstagebuch.app.repository.DiaryGroupItem
import de.trainingstagebuch.app.repository.DiaryGroupsResult
import de.trainingstagebuch.app.repository.DiaryParticipantActionResult
import de.trainingstagebuch.app.repository.DiaryParticipantsResult
import de.trainingstagebuch.app.repository.DiaryPlanItem
import de.trainingstagebuch.app.repository.DiaryPlanResult
import de.trainingstagebuch.app.repository.DiaryTagItem
import de.trainingstagebuch.app.repository.DiaryTagsResult
import de.trainingstagebuch.app.repository.DomainSocketEventType
import de.trainingstagebuch.app.repository.MemberActivityStatItem
import de.trainingstagebuch.app.repository.MemberActivityStatsResult
import de.trainingstagebuch.app.repository.MemberItem
import de.trainingstagebuch.app.repository.MemberNoteItem
import de.trainingstagebuch.app.repository.MemberNotesResult
import de.trainingstagebuch.app.repository.MemberParticipationItem
import de.trainingstagebuch.app.repository.MembersResult
import de.trainingstagebuch.app.repository.PredefinedActivitiesResult
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.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class DiaryViewModel(application: Application) : AndroidViewModel(application) {

    private val authService = AppServices.authService
    private val diaryService = AppServices.diaryService

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

    init {
        load()
        observeSocketEvents()
    }

    fun load() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            _state.update {
                it.copy(
                    status = DiaryStatus.Loading,
                    errorMessage = null,
                    successMessage = null
                )
            }
            when (val result = diaryService.loadDiaryDates(clubId)) {
                is DiaryDatesResult.Success -> {
                    val sorted = result.dates.sortedByDescending { it.date }
                    val selectedId = sorted.firstOrNull()?.id
                    val selectedEntry = sorted.firstOrNull()
                    val members = when (val membersResult = diaryService.loadMembers(clubId)) {
                        is MembersResult.Success -> membersResult.members
                        is MembersResult.Error -> {
                            _state.update {
                                it.copy(
                                    errorMessage = ViewModelStateUtils.dynamicOrFallback(membersResult.message)
                                )
                            }
                            emptyList()
                        }
                    }
                    _state.update {
                        it.copy(
                            status = DiaryStatus.Success,
                            dates = sorted,
                            members = members,
                            selectedDateId = selectedId,
                            selectedDateTags = selectedEntry?.tags.orEmpty(),
                            selectedTrainingStart = selectedEntry?.trainingStart.orEmpty(),
                            selectedTrainingEnd = selectedEntry?.trainingEnd.orEmpty()
                        )
                    }
                    loadAvailableTags()
                    if (!selectedId.isNullOrBlank()) {
                        loadParticipantsForDate(selectedId)
                        loadActivitiesForDate(selectedId)
                        loadPlanForDate(selectedId)
                        loadGroupsForDate(selectedId)
                        refreshAccidents()
                        loadNotesForSelection()
                    }
                }

                is DiaryDatesResult.Error -> {
                    _state.update {
                        it.copy(
                            status = DiaryStatus.Error,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun onNewDateChanged(value: String) {
        _state.update { it.copy(newDate = value) }
    }

    fun onTrainingStartChanged(value: String) {
        _state.update { it.copy(newTrainingStart = value) }
    }

    fun onTrainingEndChanged(value: String) {
        _state.update { it.copy(newTrainingEnd = value) }
    }

    fun onSelectDate(dateId: String) {
        _state.update { current ->
            val selected = current.dates.firstOrNull { it.id == dateId }
            current.copy(
                selectedDateId = dateId,
                selectedDateTags = selected?.tags.orEmpty(),
                selectedTrainingStart = selected?.trainingStart.orEmpty(),
                selectedTrainingEnd = selected?.trainingEnd.orEmpty(),
                activityParticipantIdsByActivityId = emptyMap(),
                accidents = emptyList()
            )
        }
        viewModelScope.launch {
            loadParticipantsForDate(dateId)
            loadActivitiesForDate(dateId)
            loadPlanForDate(dateId)
            loadGroupsForDate(dateId)
            refreshAccidents()
            loadNotesForSelection()
        }
    }

    fun onNewActivityDescriptionChanged(value: String) {
        _state.update { it.copy(newActivityDescription = value) }
    }

    fun onSelectedNoteMemberChanged(memberId: String) {
        _state.update { it.copy(selectedNoteMemberId = memberId) }
        viewModelScope.launch {
            loadNotesForSelection()
        }
    }

    fun onNewNoteContentChanged(value: String) {
        _state.update { it.copy(newNoteContent = value) }
    }

    fun onNewTagNameChanged(value: String) {
        _state.update { it.copy(newTagName = value) }
    }

    fun onNewPlanActivityChanged(value: String) {
        _state.update { it.copy(newPlanActivity = value) }
    }

    fun onNewGroupNameChanged(value: String) {
        _state.update { it.copy(newGroupName = value) }
    }

    fun onNewGroupLeadChanged(value: String) {
        _state.update { it.copy(newGroupLead = value) }
    }

    fun onNewGroupActivityChanged(value: String) {
        _state.update { it.copy(newGroupActivity = value) }
        searchPredefinedActivities(value)
    }

    fun onNewGroupActivityGroupChanged(groupId: String) {
        _state.update { it.copy(newGroupActivityGroupId = groupId) }
    }

    fun onQuickAddFirstNameChanged(value: String) {
        _state.update { it.copy(quickAddFirstName = value) }
    }

    fun onQuickAddLastNameChanged(value: String) {
        _state.update { it.copy(quickAddLastName = value) }
    }

    fun onQuickAddBirthDateChanged(value: String) {
        _state.update { it.copy(quickAddBirthDate = value) }
    }

    fun onQuickAddGenderChanged(value: String) {
        _state.update { it.copy(quickAddGender = value) }
    }

    fun onNewAccidentChanged(value: String) {
        _state.update { it.copy(newAccident = value) }
    }

    fun dismissStatsDialog() {
        _state.update {
            it.copy(
                statsMemberId = null,
                memberActivityStats = emptyList(),
                memberLastParticipations = emptyList()
            )
        }
    }

    fun startEditPlanItem(itemId: String, activity: String) {
        _state.update {
            it.copy(
                editingPlanItemId = itemId,
                editingPlanActivity = activity
            )
        }
    }

    fun onEditingPlanActivityChanged(value: String) {
        _state.update { it.copy(editingPlanActivity = value) }
    }

    fun cancelEditPlanItem() {
        _state.update {
            it.copy(
                editingPlanItemId = null,
                editingPlanActivity = ""
            )
        }
    }

    fun startEditGroup(groupId: String, name: String, lead: String) {
        _state.update {
            it.copy(
                editingGroupId = groupId,
                editingGroupName = name,
                editingGroupLead = lead
            )
        }
    }

    fun onEditingGroupNameChanged(value: String) {
        _state.update { it.copy(editingGroupName = value) }
    }

    fun onEditingGroupLeadChanged(value: String) {
        _state.update { it.copy(editingGroupLead = value) }
    }

    fun cancelEditGroup() {
        _state.update {
            it.copy(
                editingGroupId = null,
                editingGroupName = "",
                editingGroupLead = ""
            )
        }
    }

    fun onSelectedTrainingStartChanged(value: String) {
        _state.update { it.copy(selectedTrainingStart = value) }
    }

    fun onSelectedTrainingEndChanged(value: String) {
        _state.update { it.copy(selectedTrainingEnd = value) }
    }

    fun createDate() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val date = _state.value.newDate.trim()
            if (date.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_date_required)) }
                return@launch
            }
            _state.update { it.copy(createLoading = true, errorMessage = null, successMessage = null) }
            when (
                val result = diaryService.createDiaryDate(
                    clubId = clubId,
                    date = date,
                    trainingStart = _state.value.newTrainingStart.trim().ifBlank { null },
                    trainingEnd = _state.value.newTrainingEnd.trim().ifBlank { null }
                )
            ) {
                is DiaryCreateDateResult.Success -> {
                    _state.update { current ->
                        val updated = (current.dates + result.entry)
                            .distinctBy { it.id }
                            .sortedByDescending { it.date }
                        current.copy(
                            createLoading = false,
                            dates = updated,
                            selectedDateId = result.entry.id,
                            newDate = "",
                            newTrainingStart = "",
                            newTrainingEnd = "",
                            successMessage = UiText(R.string.diary_create_success)
                        )
                    }
                }

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

    fun updateSelectedDateTimes() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (
                val result = diaryService.updateDiaryTrainingTime(
                    clubId = clubId,
                    dateId = dateId,
                    trainingStart = _state.value.selectedTrainingStart.trim().ifBlank { null },
                    trainingEnd = _state.value.selectedTrainingEnd.trim().ifBlank { null }
                )
            ) {
                is DiaryActionResult.Success -> {
                    _state.update { current ->
                        val updated = current.dates.map { entry ->
                            if (entry.id == dateId) {
                                entry.copy(
                                    trainingStart = current.selectedTrainingStart.trim().ifBlank { null },
                                    trainingEnd = current.selectedTrainingEnd.trim().ifBlank { null }
                                )
                            } else {
                                entry
                            }
                        }
                        current.copy(
                            actionLoading = false,
                            dates = updated,
                            successMessage = UiText(R.string.diary_update_success)
                        )
                    }
                }

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

    fun deleteSelectedDate() {
        viewModelScope.launch {
            if (!canDeleteSelectedDate()) {
                _state.update {
                    it.copy(
                        errorMessage = UiText(R.string.diary_date_cannot_be_deleted)
                    )
                }
                return@launch
            }
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.deleteDiaryDate(clubId = clubId, dateId = dateId)) {
                is DiaryActionResult.Success -> {
                    _state.update { current ->
                        val remaining = current.dates.filterNot { it.id == dateId }
                        val nextSelected = remaining.firstOrNull()
                        current.copy(
                            actionLoading = false,
                            dates = remaining,
                            selectedDateId = nextSelected?.id,
                            selectedTrainingStart = nextSelected?.trainingStart.orEmpty(),
                            selectedTrainingEnd = nextSelected?.trainingEnd.orEmpty(),
                            participantMemberIds = emptyList(),
                            participantMapByMemberId = emptyMap(),
                            participantGroupByMemberId = emptyMap(),
                            activities = emptyList(),
                            planItems = emptyList(),
                            availableGroups = emptyList(),
                            accidents = emptyList(),
                            activityParticipantIdsByActivityId = emptyMap(),
                            selectedDateTags = emptyList(),
                            editingPlanItemId = null,
                            editingPlanActivity = "",
                            successMessage = UiText(R.string.diary_delete_success)
                        )
                    }
                    val nextDateId = _state.value.selectedDateId
                    if (!nextDateId.isNullOrBlank()) {
                        loadParticipantsForDate(nextDateId)
                        loadActivitiesForDate(nextDateId)
                        loadPlanForDate(nextDateId)
                        loadGroupsForDate(nextDateId)
                        refreshAccidents()
                        loadNotesForSelection()
                    }
                }

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

    fun notifyDeleteNotAllowed() {
        _state.update {
            it.copy(
                errorMessage = UiText(R.string.diary_date_cannot_be_deleted)
            )
        }
    }

    fun addExistingTagToSelectedDate(tagId: String) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            if (tagId.isBlank()) return@launch
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.addTagToDiaryDate(clubId = clubId, diaryDateId = dateId, tagId = tagId)) {
                is DiaryActionResult.Success -> {
                    val tag = _state.value.availableTags.firstOrNull { it.id == tagId }
                    if (tag != null) {
                        _state.update { current ->
                            current.copy(
                                actionLoading = false,
                                selectedDateTags = (current.selectedDateTags + tag).distinctBy { it.id },
                                successMessage = UiText(R.string.diary_tag_added)
                            )
                        }
                        syncSelectedDateTagsToDates()
                    } else {
                        _state.update { it.copy(actionLoading = false, successMessage = UiText(R.string.diary_tag_added)) }
                    }
                }

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

    fun removeTagFromSelectedDate(tagId: String) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            if (tagId.isBlank()) return@launch
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.removeTagFromDiaryDate(clubId = clubId, diaryDateId = dateId, tagId = tagId)) {
                is DiaryActionResult.Success -> {
                    _state.update { current ->
                        current.copy(
                            actionLoading = false,
                            selectedDateTags = current.selectedDateTags.filterNot { it.id == tagId },
                            successMessage = UiText(R.string.diary_tag_removed)
                        )
                    }
                    syncSelectedDateTagsToDates()
                }

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

    fun createTagAndAddToSelectedDate() {
        viewModelScope.launch {
            val name = _state.value.newTagName.trim()
            if (name.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_tag_name_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.createTag(name)) {
                is DiaryCreateTagResult.Success -> {
                    _state.update { current ->
                        current.copy(
                            actionLoading = false,
                            newTagName = "",
                            availableTags = (current.availableTags + result.tag).distinctBy { it.id }
                        )
                    }
                    addExistingTagToSelectedDate(result.tag.id)
                }

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

    fun createGroup() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            val name = _state.value.newGroupName.trim()
            val lead = _state.value.newGroupLead.trim()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            if (name.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_group_name_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.createDiaryGroup(clubId = clubId, dateId = dateId, name = name, lead = lead)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            newGroupName = "",
                            newGroupLead = "",
                            successMessage = UiText(R.string.diary_group_created)
                        )
                    }
                    loadGroupsForDate(dateId)
                }

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

    fun saveEditGroup() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            val groupId = _state.value.editingGroupId?.trim().orEmpty()
            val name = _state.value.editingGroupName.trim()
            val lead = _state.value.editingGroupLead.trim()
            if (dateId.isBlank() || groupId.isBlank()) return@launch
            if (name.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_group_name_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (
                val result = diaryService.updateDiaryGroup(
                    groupId = groupId,
                    clubId = clubId,
                    dateId = dateId,
                    name = name,
                    lead = lead
                )
            ) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            editingGroupId = null,
                            editingGroupName = "",
                            editingGroupLead = "",
                            successMessage = UiText(R.string.diary_group_updated)
                        )
                    }
                    loadGroupsForDate(dateId)
                }

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

    fun deleteGroup(groupId: String) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank() || groupId.isBlank()) return@launch
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.deleteDiaryGroup(groupId = groupId, clubId = clubId, dateId = dateId)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            successMessage = UiText(R.string.diary_group_deleted)
                        )
                    }
                    loadGroupsForDate(dateId)
                }

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

    fun addGroupActivity() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            val groupId = _state.value.newGroupActivityGroupId.trim()
            val activity = _state.value.newGroupActivity.trim()
            val predefinedActivityId = _state.value.selectedPredefinedActivityId
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            if (groupId.isBlank() || activity.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_group_and_activity)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (
                val result = diaryService.createDiaryGroupActivity(
                    clubId = clubId,
                    dateId = dateId,
                    groupId = groupId,
                    activity = activity,
                    predefinedActivityId = predefinedActivityId
                )
            ) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            newGroupActivity = "",
                            newGroupActivityGroupId = "",
                            selectedPredefinedActivityId = null,
                            predefinedSuggestions = emptyList(),
                            successMessage = UiText(R.string.diary_group_activity_added)
                        )
                    }
                    loadPlanForDate(dateId)
                }

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

    fun toggleActivityMember(activityId: String, memberId: String) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            val participantId = _state.value.participantMapByMemberId[memberId]
            val existingSet = _state.value.activityParticipantIdsByActivityId[activityId].orEmpty()
            val isAssigned = participantId != null && existingSet.contains(participantId)

            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            if (isAssigned) {
                when (val result = diaryService.removeActivityParticipant(clubId, activityId, participantId)) {
                    is DiaryActionResult.Success -> {
                        _state.update {
                            val updated = it.activityParticipantIdsByActivityId.toMutableMap()
                            updated[activityId] = updated[activityId].orEmpty() - participantId
                            it.copy(
                                actionLoading = false,
                                activityParticipantIdsByActivityId = updated,
                                successMessage = UiText(R.string.diary_activity_assignment_updated)
                            )
                        }
                    }
                    is DiaryActionResult.Error -> {
                        _state.update {
                            it.copy(
                                actionLoading = false,
                                errorMessage = ViewModelStateUtils.normalizeUiText(
                                    ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                                )
                            )
                        }
                    }
                }
            } else {
                val resolvedParticipantId = participantId ?: run {
                    when (val addResult = diaryService.addParticipant(dateId, memberId)) {
                        is DiaryParticipantActionResult.Success -> addResult.participant?.id
                        is DiaryParticipantActionResult.Error -> null
                    }
                }
                if (resolvedParticipantId.isNullOrBlank()) {
                    _state.update { it.copy(actionLoading = false, errorMessage = UiText(R.string.diary_participant_add_failed)) }
                    return@launch
                }
                if (participantId == null) {
                    _state.update {
                        it.copy(
                            participantMemberIds = (it.participantMemberIds + memberId).distinct(),
                            participantMapByMemberId = it.participantMapByMemberId + (memberId to resolvedParticipantId)
                        )
                    }
                }
                when (val result = diaryService.assignActivityParticipants(clubId, activityId, listOf(resolvedParticipantId))) {
                    is DiaryActionResult.Success -> {
                        _state.update {
                            val updated = it.activityParticipantIdsByActivityId.toMutableMap()
                            updated[activityId] = updated[activityId].orEmpty() + resolvedParticipantId
                            it.copy(
                                actionLoading = false,
                                activityParticipantIdsByActivityId = updated,
                                successMessage = UiText(R.string.diary_activity_assignment_updated)
                            )
                        }
                    }
                    is DiaryActionResult.Error -> {
                        _state.update {
                            it.copy(
                                actionLoading = false,
                                errorMessage = ViewModelStateUtils.normalizeUiText(
                                    ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                                )
                            )
                        }
                    }
                }
            }
        }
    }

    fun openQuickAddDialog() {
        _state.update {
            it.copy(
                showQuickAddDialog = true,
                quickAddFirstName = "",
                quickAddLastName = "",
                quickAddBirthDate = "",
                quickAddGender = ""
            )
        }
    }

    fun closeQuickAddDialog() {
        _state.update { it.copy(showQuickAddDialog = false) }
    }

    fun createAndAddMember() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            val firstName = _state.value.quickAddFirstName.trim()
            val lastName = _state.value.quickAddLastName.trim()
            if (dateId.isBlank()) return@launch
            if (firstName.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_quick_add_firstname_required)) }
                return@launch
            }

            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (
                val saveResult = AppServices.membersService.saveMember(
                    clubId = clubId,
                    memberId = null,
                    firstName = firstName,
                    lastName = lastName,
                    active = true,
                    testMembership = true,
                    contacts = emptyList()
                )
            ) {
                is de.trainingstagebuch.app.repository.MemberSaveResult.Success -> {
                    when (val membersResult = diaryService.loadMembers(clubId)) {
                        is MembersResult.Success -> {
                            val newMember = membersResult.members.lastOrNull { it.firstName == firstName && it.lastName == lastName }
                                ?: membersResult.members.lastOrNull()
                            if (newMember != null) {
                                toggleParticipant(newMember.id)
                            }
                            _state.update {
                                it.copy(
                                    actionLoading = false,
                                    members = membersResult.members,
                                    showQuickAddDialog = false,
                                    successMessage = UiText(R.string.diary_quick_add_success)
                                )
                            }
                        }
                        is MembersResult.Error -> {
                            _state.update {
                                it.copy(
                                    actionLoading = false,
                                    errorMessage = ViewModelStateUtils.dynamicOrFallback(membersResult.message)
                                )
                            }
                        }
                    }
                }
                is de.trainingstagebuch.app.repository.MemberSaveResult.Error -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(saveResult.message, saveResult.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun refreshAccidents() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) return@launch
            when (val result = diaryService.loadAccidents(clubId, dateId)) {
                is DiaryAccidentsResult.Success -> _state.update { it.copy(accidents = result.items) }
                is DiaryAccidentsResult.Error -> Unit
            }
        }
    }

    fun saveAccident() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            val accident = _state.value.newAccident.trim()
            if (dateId.isBlank()) return@launch
            if (accident.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_accident_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.createAccident(clubId, dateId, accident)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            newAccident = "",
                            successMessage = UiText(R.string.diary_accident_saved)
                        )
                    }
                    refreshAccidents()
                }
                is DiaryActionResult.Error -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun openStatsForMember(memberId: String) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            _state.update { it.copy(actionLoading = true, statsMemberId = memberId) }
            when (val result = diaryService.loadMemberActivityStats(clubId, memberId)) {
                is MemberActivityStatsResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            memberActivityStats = result.stats,
                            memberLastParticipations = result.lastParticipations
                        )
                    }
                }
                is MemberActivityStatsResult.Error -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                }
            }
        }
    }

    fun addPlanItem() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            val activity = _state.value.newPlanActivity.trim()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            if (activity.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_plan_activity_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (
                val result = diaryService.addDiaryPlanItem(
                    clubId = clubId,
                    dateId = dateId,
                    activity = activity,
                    orderId = _state.value.planItems.size
                )
            ) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            newPlanActivity = "",
                            successMessage = UiText(R.string.diary_plan_item_added)
                        )
                    }
                    loadPlanForDate(dateId)
                }

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

    fun saveEditPlanItem() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val planItemId = _state.value.editingPlanItemId?.trim().orEmpty()
            val activity = _state.value.editingPlanActivity.trim()
            if (planItemId.isBlank()) return@launch
            if (activity.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_plan_activity_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.updateDiaryPlanItem(clubId = clubId, planItemId = planItemId, activity = activity)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            editingPlanItemId = null,
                            editingPlanActivity = "",
                            successMessage = UiText(R.string.diary_plan_item_updated)
                        )
                    }
                    val dateId = _state.value.selectedDateId?.trim().orEmpty()
                    if (dateId.isNotBlank()) loadPlanForDate(dateId)
                }

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

    fun deletePlanItem(planItemId: String) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            if (planItemId.isBlank()) return@launch
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.deleteDiaryPlanItem(clubId = clubId, planItemId = planItemId)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            successMessage = UiText(R.string.diary_plan_item_deleted)
                        )
                    }
                    val dateId = _state.value.selectedDateId?.trim().orEmpty()
                    if (dateId.isNotBlank()) loadPlanForDate(dateId)
                }

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

    fun movePlanItemUp(planItemId: String) {
        movePlanItem(planItemId = planItemId, direction = -1)
    }

    fun movePlanItemDown(planItemId: String) {
        movePlanItem(planItemId = planItemId, direction = 1)
    }

    fun addActivity() {
        viewModelScope.launch {
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            val description = _state.value.newActivityDescription.trim()
            if (description.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_activity_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.addActivity(dateId = dateId, description = description)) {
                is DiaryAddActivityResult.Success -> {
                    _state.update { current ->
                        current.copy(
                            actionLoading = false,
                            activities = (current.activities + result.activity).distinctBy { it.id },
                            newActivityDescription = "",
                            successMessage = UiText(R.string.diary_activity_added)
                        )
                    }
                }

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

    fun toggleParticipant(memberId: String) {
        viewModelScope.launch {
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }

            val currentlyParticipant = _state.value.participantMemberIds.contains(memberId)
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }

            if (currentlyParticipant) {
                when (val result = diaryService.removeParticipant(dateId = dateId, memberId = memberId)) {
                    is DiaryActionResult.Success -> {
                        _state.update { current ->
                            current.copy(
                                actionLoading = false,
                                participantMemberIds = current.participantMemberIds.filterNot { it == memberId },
                                participantMapByMemberId = current.participantMapByMemberId - memberId,
                                participantGroupByMemberId = current.participantGroupByMemberId - memberId,
                                selectedNoteMemberId = if (current.selectedNoteMemberId == memberId) {
                                    current.participantMemberIds.filterNot { it == memberId }.firstOrNull()
                                } else {
                                    current.selectedNoteMemberId
                                },
                                successMessage = UiText(R.string.diary_participant_removed)
                            )
                        }
                        loadNotesForSelection()
                    }

                    is DiaryActionResult.Error -> {
                        _state.update {
                            it.copy(
                                actionLoading = false,
                                errorMessage = ViewModelStateUtils.normalizeUiText(
                                    ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                                )
                            )
                        }
                    }
                }
            } else {
                when (val result = diaryService.addParticipant(dateId = dateId, memberId = memberId)) {
                    is DiaryParticipantActionResult.Success -> {
                        _state.update { current ->
                            val updatedParticipants = (current.participantMemberIds + memberId).distinct()
                            current.copy(
                                actionLoading = false,
                                participantMemberIds = updatedParticipants,
                                participantMapByMemberId = if (result.participant != null) {
                                    current.participantMapByMemberId + (memberId to result.participant.id)
                                } else {
                                    current.participantMapByMemberId
                                },
                                participantGroupByMemberId = if (result.participant?.groupId != null) {
                                    current.participantGroupByMemberId + (memberId to result.participant.groupId)
                                } else {
                                    current.participantGroupByMemberId
                                },
                                selectedNoteMemberId = current.selectedNoteMemberId ?: updatedParticipants.firstOrNull(),
                                successMessage = UiText(R.string.diary_participant_added)
                            )
                        }
                        loadNotesForSelection()
                    }

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

    private suspend fun loadParticipantsForDate(dateId: String) {
        when (val result = diaryService.loadParticipants(dateId)) {
            is DiaryParticipantsResult.Success -> {
                _state.update {
                    val memberIds = result.participants.map { participant -> participant.memberId }
                    it.copy(
                        participantMemberIds = memberIds,
                        participantMapByMemberId = result.participants.associate { participant ->
                            participant.memberId to participant.id
                        },
                        participantGroupByMemberId = result.participants.associate { participant ->
                            participant.memberId to participant.groupId
                        },
                        selectedNoteMemberId = it.selectedNoteMemberId
                            ?.takeIf { existing -> memberIds.contains(existing) }
                            ?: memberIds.firstOrNull()
                    )
                }
            }

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

    fun onParticipantGroupChanged(memberId: String, groupId: String?) {
        viewModelScope.launch {
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_date_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.updateParticipantGroup(dateId = dateId, memberId = memberId, groupId = groupId)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            participantGroupByMemberId = it.participantGroupByMemberId + (memberId to groupId),
                            successMessage = UiText(R.string.diary_participant_group_updated)
                        )
                    }
                }

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

    fun addNote() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            val memberId = _state.value.selectedNoteMemberId?.trim().orEmpty()
            val content = _state.value.newNoteContent.trim()
            if (dateId.isBlank() || memberId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_select_note_member_required)) }
                return@launch
            }
            if (content.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.diary_note_required)) }
                return@launch
            }
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (
                val result = diaryService.addDiaryMemberNote(
                    clubId = clubId,
                    diaryDateId = dateId,
                    memberId = memberId,
                    content = content
                )
            ) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            newNoteContent = "",
                            successMessage = UiText(R.string.diary_note_added)
                        )
                    }
                    loadNotesForSelection()
                }

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

    fun deleteNote(noteId: String) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.deleteDiaryMemberNote(clubId = clubId, noteId = noteId)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            successMessage = UiText(R.string.diary_note_deleted)
                        )
                    }
                    loadNotesForSelection()
                }

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

    private suspend fun loadNotesForSelection() {
        val clubId = resolveClubId() ?: return
        val dateId = _state.value.selectedDateId?.trim().orEmpty()
        val memberId = _state.value.selectedNoteMemberId?.trim().orEmpty()
        if (dateId.isBlank() || memberId.isBlank()) {
            _state.update { it.copy(notes = emptyList()) }
            return
        }
        when (
            val result = diaryService.loadDiaryMemberNotes(
                clubId = clubId,
                diaryDateId = dateId,
                memberId = memberId
            )
        ) {
            is MemberNotesResult.Success -> {
                _state.update { it.copy(notes = result.notes) }
            }

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

    private suspend fun loadActivitiesForDate(dateId: String) {
        when (val result = diaryService.loadActivities(dateId)) {
            is DiaryActivitiesResult.Success -> {
                _state.update { it.copy(activities = result.activities) }
            }

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

    private suspend fun loadAvailableTags() {
        when (val result = diaryService.loadTags()) {
            is DiaryTagsResult.Success -> {
                _state.update { it.copy(availableTags = result.tags) }
            }

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

    private fun movePlanItem(planItemId: String, direction: Int) {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val dateId = _state.value.selectedDateId?.trim().orEmpty()
            if (dateId.isBlank()) return@launch
            val items = _state.value.planItems
            val currentIndex = items.indexOfFirst { it.id == planItemId }
            if (currentIndex < 0) return@launch
            val targetIndex = currentIndex + direction
            if (targetIndex !in items.indices) return@launch

            _state.update { it.copy(actionLoading = true, errorMessage = null, successMessage = null) }
            when (val result = diaryService.updateDiaryPlanItemOrder(clubId = clubId, planItemId = planItemId, order = targetIndex)) {
                is DiaryActionResult.Success -> {
                    _state.update {
                        it.copy(
                            actionLoading = false,
                            successMessage = UiText(R.string.diary_plan_order_updated)
                        )
                    }
                    loadPlanForDate(dateId)
                }

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

    private suspend fun loadPlanForDate(dateId: String) {
        val clubId = resolveClubId() ?: return
        when (val result = diaryService.loadDiaryPlan(clubId = clubId, dateId = dateId)) {
            is DiaryPlanResult.Success -> {
                _state.update { it.copy(planItems = result.items) }
                result.items.forEach { item ->
                    when (val assignmentResult = diaryService.loadActivityParticipantIds(clubId = clubId, activityId = item.id)) {
                        is DiaryActivityParticipantsResult.Success -> {
                            _state.update {
                                it.copy(
                                    activityParticipantIdsByActivityId = it.activityParticipantIdsByActivityId + (item.id to assignmentResult.participantIds)
                                )
                            }
                        }
                        is DiaryActivityParticipantsResult.Error -> Unit
                    }
                }
            }

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

    private fun searchPredefinedActivities(term: String) {
        viewModelScope.launch {
            val query = term.trim()
            if (query.length < 2) {
                _state.update { it.copy(predefinedSuggestions = emptyList(), selectedPredefinedActivityId = null) }
                return@launch
            }
            when (val result = diaryService.searchPredefinedActivities(query)) {
                is PredefinedActivitiesResult.Success -> {
                    val chosen = result.items.firstOrNull { item ->
                        item.name.equals(query, ignoreCase = true) ||
                            item.code?.equals(query, ignoreCase = true) == true
                    }
                    _state.update {
                        it.copy(
                            predefinedSuggestions = result.items,
                            selectedPredefinedActivityId = chosen?.id
                        )
                    }
                }
                is PredefinedActivitiesResult.Error -> Unit
            }
        }
    }

    private suspend fun loadGroupsForDate(dateId: String) {
        val clubId = resolveClubId() ?: return
        when (val result = diaryService.loadDiaryGroups(clubId = clubId, dateId = dateId)) {
            is DiaryGroupsResult.Success -> {
                _state.update { it.copy(availableGroups = result.groups) }
            }

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

    private fun observeSocketEvents() {
        viewModelScope.launch {
            diaryService.socketEvents.collect { event ->
                val dateId = _state.value.selectedDateId?.trim().orEmpty()
                if (dateId.isBlank()) return@collect
                when (event.type) {
                    DomainSocketEventType.ParticipantAdded,
                    DomainSocketEventType.ParticipantRemoved,
                    DomainSocketEventType.ParticipantUpdated -> {
                        loadParticipantsForDate(dateId)
                    }
                    DomainSocketEventType.DiaryNoteAdded,
                    DomainSocketEventType.DiaryNoteDeleted,
                    DomainSocketEventType.DiaryNoteUpdated -> {
                        loadNotesForSelection()
                    }
                    DomainSocketEventType.DiaryTagAdded,
                    DomainSocketEventType.DiaryTagRemoved,
                    DomainSocketEventType.DiaryDateUpdated -> {
                        load()
                        refreshAccidents()
                    }
                    DomainSocketEventType.ActivityChanged,
                    DomainSocketEventType.ActivityMemberAdded,
                    DomainSocketEventType.ActivityMemberRemoved -> {
                        loadPlanForDate(dateId)
                    }
                    DomainSocketEventType.GroupChanged -> {
                        loadGroupsForDate(dateId)
                        loadPlanForDate(dateId)
                    }
                    DomainSocketEventType.MemberChanged -> {
                        val clubId = resolveClubId() ?: return@collect
                        when (val membersResult = diaryService.loadMembers(clubId)) {
                            is MembersResult.Success -> _state.update { it.copy(members = membersResult.members) }
                            is MembersResult.Error -> Unit
                        }
                    }
                    DomainSocketEventType.TournamentChanged,
                    DomainSocketEventType.ScheduleMatchUpdated,
                    DomainSocketEventType.ScheduleMatchReportSubmitted,
                    DomainSocketEventType.Unknown -> Unit
                }
            }
        }
    }

    private fun syncSelectedDateTagsToDates() {
        _state.update { current ->
            val selectedDateId = current.selectedDateId ?: return@update current
            current.copy(
                dates = current.dates.map { date ->
                    if (date.id == selectedDateId) {
                        date.copy(tags = current.selectedDateTags)
                    } else {
                        date
                    }
                }
            )
        }
    }

    private fun canDeleteSelectedDate(): Boolean {
        val current = _state.value
        return current.planItems.isEmpty() &&
            current.participantMemberIds.isEmpty() &&
            current.activities.isEmpty() &&
            current.notes.isEmpty()
    }

    private suspend fun resolveClubId(): String? {
        val clubId = authService.session.first().currentClub?.trim().orEmpty()
        if (clubId.isBlank()) {
            _state.update {
                it.copy(
                    status = DiaryStatus.Error,
                    errorMessage = UiText(R.string.error_no_current_club)
                )
            }
            return null
        }
        return clubId
    }
}

data class DiaryUiState(
    val status: DiaryStatus = DiaryStatus.Idle,
    val dates: List<DiaryDateEntry> = emptyList(),
    val members: List<MemberItem> = emptyList(),
    val participantMemberIds: List<String> = emptyList(),
    val participantMapByMemberId: Map<String, String> = emptyMap(),
    val participantGroupByMemberId: Map<String, String?> = emptyMap(),
    val availableGroups: List<DiaryGroupItem> = emptyList(),
    val newGroupName: String = "",
    val newGroupLead: String = "",
    val newGroupActivity: String = "",
    val newGroupActivityGroupId: String = "",
    val predefinedSuggestions: List<PredefinedActivityItem> = emptyList(),
    val selectedPredefinedActivityId: String? = null,
    val editingGroupId: String? = null,
    val editingGroupName: String = "",
    val editingGroupLead: String = "",
    val activities: List<DiaryActivityItem> = emptyList(),
    val newActivityDescription: String = "",
    val selectedNoteMemberId: String? = null,
    val notes: List<MemberNoteItem> = emptyList(),
    val newNoteContent: String = "",
    val availableTags: List<DiaryTagItem> = emptyList(),
    val selectedDateTags: List<DiaryTagItem> = emptyList(),
    val newTagName: String = "",
    val planItems: List<DiaryPlanItem> = emptyList(),
    val activityParticipantIdsByActivityId: Map<String, Set<String>> = emptyMap(),
    val newPlanActivity: String = "",
    val editingPlanItemId: String? = null,
    val editingPlanActivity: String = "",
    val accidents: List<DiaryAccidentItem> = emptyList(),
    val newAccident: String = "",
    val showQuickAddDialog: Boolean = false,
    val quickAddFirstName: String = "",
    val quickAddLastName: String = "",
    val quickAddBirthDate: String = "",
    val quickAddGender: String = "",
    val statsMemberId: String? = null,
    val memberActivityStats: List<MemberActivityStatItem> = emptyList(),
    val memberLastParticipations: List<MemberParticipationItem> = emptyList(),
    val selectedDateId: String? = null,
    val newDate: String = "",
    val newTrainingStart: String = "",
    val newTrainingEnd: String = "",
    val createLoading: Boolean = false,
    val selectedTrainingStart: String = "",
    val selectedTrainingEnd: String = "",
    val actionLoading: Boolean = false,
    val errorMessage: UiText? = null,
    val successMessage: UiText? = null
)

enum class DiaryStatus {
    Idle,
    Loading,
    Success,
    Error
}
