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.ClubActionResult
import de.trainingstagebuch.app.repository.ClubSettingsActionResult
import de.trainingstagebuch.app.repository.ClubSettingsResult
import de.trainingstagebuch.app.repository.ClubTrainingGroup
import de.trainingstagebuch.app.repository.ClubTrainingGroupsResult
import de.trainingstagebuch.app.repository.ClubTrainingTimeGroup
import de.trainingstagebuch.app.repository.ClubTrainingTimesResult
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 ClubSettingsViewModel(application: Application) : AndroidViewModel(application) {

    private val authService = AppServices.authService
    private val clubSettingsService = AppServices.clubSettingsService

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

    init {
        load()
    }

    fun onTabChanged(tab: ClubSettingsTab) {
        _state.update { it.copy(activeTab = tab) }
    }

    fun onGreetingTextChanged(value: String) {
        _state.update { it.copy(greetingText = value) }
    }

    fun onAssociationMemberNumberChanged(value: String) {
        _state.update { it.copy(associationMemberNumber = value) }
    }

    fun onNewTrainingGroupNameChanged(value: String) {
        _state.update { it.copy(newTrainingGroupName = value) }
    }

    fun onEditingTrainingGroupNameChanged(value: String) {
        _state.update { it.copy(editingTrainingGroupName = value) }
    }

    fun onNewTrainingTimeGroupIdChanged(value: String) {
        _state.update { it.copy(newTrainingTimeGroupId = value) }
    }

    fun onNewTrainingTimeWeekdayChanged(value: String) {
        _state.update { it.copy(newTrainingTimeWeekday = value) }
    }

    fun onNewTrainingTimeStartChanged(value: String) {
        _state.update { it.copy(newTrainingTimeStart = value) }
    }

    fun onNewTrainingTimeEndChanged(value: String) {
        _state.update { it.copy(newTrainingTimeEnd = value) }
    }

    fun onEditingTrainingTimeWeekdayChanged(value: String) {
        _state.update { it.copy(editingTrainingTimeWeekday = value) }
    }

    fun onEditingTrainingTimeStartChanged(value: String) {
        _state.update { it.copy(editingTrainingTimeStart = value) }
    }

    fun onEditingTrainingTimeEndChanged(value: String) {
        _state.update { it.copy(editingTrainingTimeEnd = value) }
    }

    fun load() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            _state.update { it.copy(status = ClubSettingsStatus.Loading, errorMessage = null, loadingClubId = clubId) }
            loadSettings(clubId)
            loadTrainingGroups(clubId)
            loadTrainingTimes(clubId)
            _state.update { it.copy(status = ClubSettingsStatus.Success) }
        }
    }

    fun refreshTrainingGroups() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            loadTrainingGroups(clubId)
        }
    }

    fun refreshTrainingTimes() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            loadTrainingTimes(clubId)
        }
    }

    fun saveSettings() {
        val clubId = _state.value.loadingClubId?.trim().orEmpty()
        if (clubId.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
            return
        }

        viewModelScope.launch {
            _state.update { it.copy(saving = true, errorMessage = null, successMessage = null) }
            when (
                val result = clubSettingsService.saveClubSettings(
                    clubId = clubId,
                    greetingText = _state.value.greetingText,
                    associationMemberNumber = _state.value.associationMemberNumber
                )
            ) {
                is ClubSettingsActionResult.Success -> {
                    val msg = result.message?.trim().orEmpty()
                    _state.update {
                        it.copy(
                            saving = false,
                            successMessage = if (msg.isBlank()) {
                                UiText(R.string.club_settings_saved_default)
                            } else {
                                UiText(R.string.message_dynamic, args = listOf(msg))
                            }
                        )
                    }
                }

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

    fun createTrainingGroup() {
        val clubId = _state.value.loadingClubId?.trim().orEmpty()
        val name = _state.value.newTrainingGroupName.trim()
        if (clubId.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
            return
        }
        if (name.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.club_settings_group_name_required)) }
            return
        }

        viewModelScope.launch {
            _state.update { it.copy(groupActionLoading = true, errorMessage = null) }
            when (val result = clubSettingsService.createTrainingGroup(clubId, name)) {
                is ClubActionResult.Success -> {
                    _state.update {
                        it.copy(
                            groupActionLoading = false,
                            newTrainingGroupName = "",
                            successMessage = UiText(R.string.club_settings_group_created)
                        )
                    }
                    loadTrainingGroups(clubId)
                }

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

    fun deleteTrainingGroup(groupId: String) {
        val clubId = _state.value.loadingClubId?.trim().orEmpty()
        if (clubId.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
            return
        }

        viewModelScope.launch {
            _state.update { it.copy(groupActionLoading = true, errorMessage = null) }
            when (val result = clubSettingsService.deleteTrainingGroup(clubId, groupId)) {
                is ClubActionResult.Success -> {
                    _state.update {
                        it.copy(
                            groupActionLoading = false,
                            successMessage = UiText(R.string.club_settings_group_deleted)
                        )
                    }
                    loadTrainingGroups(clubId)
                    loadTrainingTimes(clubId)
                }

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

    fun startEditTrainingGroup(groupId: String, currentName: String) {
        _state.update {
            it.copy(
                editingTrainingGroupId = groupId,
                editingTrainingGroupName = currentName
            )
        }
    }

    fun cancelEditTrainingGroup() {
        _state.update {
            it.copy(
                editingTrainingGroupId = null,
                editingTrainingGroupName = ""
            )
        }
    }

    fun saveEditTrainingGroup() {
        val current = _state.value
        val clubId = current.loadingClubId?.trim().orEmpty()
        val groupId = current.editingTrainingGroupId?.trim().orEmpty()
        val name = current.editingTrainingGroupName.trim()
        if (clubId.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
            return
        }
        if (groupId.isBlank() || name.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.club_settings_group_name_required)) }
            return
        }

        viewModelScope.launch {
            _state.update { it.copy(groupActionLoading = true, errorMessage = null) }
            when (val result = clubSettingsService.updateTrainingGroup(clubId, groupId, name)) {
                is ClubActionResult.Success -> {
                    _state.update {
                        it.copy(
                            groupActionLoading = false,
                            editingTrainingGroupId = null,
                            editingTrainingGroupName = "",
                            successMessage = UiText(R.string.club_settings_group_updated)
                        )
                    }
                    loadTrainingGroups(clubId)
                }

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

    fun createTrainingTime() {
        val current = _state.value
        val clubId = current.loadingClubId?.trim().orEmpty()
        val groupId = current.newTrainingTimeGroupId.trim()
        val weekday = current.newTrainingTimeWeekday.toIntOrNull()
        val start = current.newTrainingTimeStart.trim()
        val end = current.newTrainingTimeEnd.trim()

        if (clubId.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
            return
        }
        if (groupId.isBlank() || weekday == null || weekday !in 0..6 || start.isBlank() || end.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.club_settings_time_required)) }
            return
        }

        viewModelScope.launch {
            _state.update { it.copy(timeActionLoading = true, errorMessage = null) }
            when (val result = clubSettingsService.createTrainingTime(clubId, groupId, weekday, start, end)) {
                is ClubActionResult.Success -> {
                    _state.update {
                        it.copy(
                            timeActionLoading = false,
                            newTrainingTimeWeekday = "1",
                            newTrainingTimeStart = "",
                            newTrainingTimeEnd = "",
                            successMessage = UiText(R.string.club_settings_time_created)
                        )
                    }
                    loadTrainingTimes(clubId)
                }

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

    fun deleteTrainingTime(timeId: String) {
        val clubId = _state.value.loadingClubId?.trim().orEmpty()
        if (clubId.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
            return
        }

        viewModelScope.launch {
            _state.update { it.copy(timeActionLoading = true, errorMessage = null) }
            when (val result = clubSettingsService.deleteTrainingTime(clubId, timeId)) {
                is ClubActionResult.Success -> {
                    _state.update {
                        it.copy(
                            timeActionLoading = false,
                            successMessage = UiText(R.string.club_settings_time_deleted)
                        )
                    }
                    loadTrainingTimes(clubId)
                }

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

    fun startEditTrainingTime(timeId: String, weekday: Int, start: String, end: String) {
        _state.update {
            it.copy(
                editingTrainingTimeId = timeId,
                editingTrainingTimeWeekday = weekday.toString(),
                editingTrainingTimeStart = start.take(5),
                editingTrainingTimeEnd = end.take(5)
            )
        }
    }

    fun cancelEditTrainingTime() {
        _state.update {
            it.copy(
                editingTrainingTimeId = null,
                editingTrainingTimeWeekday = "1",
                editingTrainingTimeStart = "",
                editingTrainingTimeEnd = ""
            )
        }
    }

    fun saveEditTrainingTime() {
        val current = _state.value
        val clubId = current.loadingClubId?.trim().orEmpty()
        val timeId = current.editingTrainingTimeId?.trim().orEmpty()
        val weekday = current.editingTrainingTimeWeekday.toIntOrNull()
        val start = current.editingTrainingTimeStart.trim()
        val end = current.editingTrainingTimeEnd.trim()
        if (clubId.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
            return
        }
        if (timeId.isBlank() || weekday == null || weekday !in 0..6 || start.isBlank() || end.isBlank()) {
            _state.update { it.copy(errorMessage = UiText(R.string.club_settings_time_required)) }
            return
        }

        viewModelScope.launch {
            _state.update { it.copy(timeActionLoading = true, errorMessage = null) }
            when (val result = clubSettingsService.updateTrainingTime(clubId, timeId, weekday, start, end)) {
                is ClubActionResult.Success -> {
                    _state.update {
                        it.copy(
                            timeActionLoading = false,
                            editingTrainingTimeId = null,
                            editingTrainingTimeWeekday = "1",
                            editingTrainingTimeStart = "",
                            editingTrainingTimeEnd = "",
                            successMessage = UiText(R.string.club_settings_time_updated)
                        )
                    }
                    loadTrainingTimes(clubId)
                }

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

    private suspend fun resolveClubId(): String? {
        val existing = _state.value.loadingClubId?.trim().orEmpty()
        if (existing.isNotBlank()) return existing

        val clubId = authService.session.first().currentClub?.trim().orEmpty()
        if (clubId.isBlank()) {
            _state.update {
                it.copy(
                    status = ClubSettingsStatus.Error,
                    errorMessage = UiText(R.string.error_no_current_club)
                )
            }
            return null
        }
        return clubId
    }

    private suspend fun loadSettings(clubId: String) {
        when (val result = clubSettingsService.loadClubSettings(clubId)) {
            is ClubSettingsResult.Success -> {
                _state.update {
                    it.copy(
                        greetingText = result.settings.greetingText,
                        associationMemberNumber = result.settings.associationMemberNumber,
                        loadingClubId = clubId,
                        successMessage = null
                    )
                }
            }

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

    private suspend fun loadTrainingGroups(clubId: String) {
        when (val result = clubSettingsService.loadTrainingGroups(clubId)) {
            is ClubTrainingGroupsResult.Success -> {
                _state.update { current ->
                    val selectedGroup = current.newTrainingTimeGroupId.takeIf { it.isNotBlank() }
                        ?: result.groups.firstOrNull()?.id.orEmpty()
                    current.copy(trainingGroups = result.groups, newTrainingTimeGroupId = selectedGroup)
                }
            }

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

    private suspend fun loadTrainingTimes(clubId: String) {
        when (val result = clubSettingsService.loadTrainingTimes(clubId)) {
            is ClubTrainingTimesResult.Success -> {
                _state.update { it.copy(trainingTimeGroups = result.groups) }
            }

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

data class ClubSettingsUiState(
    val status: ClubSettingsStatus = ClubSettingsStatus.Idle,
    val activeTab: ClubSettingsTab = ClubSettingsTab.Settings,
    val loadingClubId: String? = null,
    val greetingText: String = "",
    val associationMemberNumber: String = "",
    val saving: Boolean = false,
    val trainingGroups: List<ClubTrainingGroup> = emptyList(),
    val newTrainingGroupName: String = "",
    val editingTrainingGroupId: String? = null,
    val editingTrainingGroupName: String = "",
    val groupActionLoading: Boolean = false,
    val trainingTimeGroups: List<ClubTrainingTimeGroup> = emptyList(),
    val newTrainingTimeGroupId: String = "",
    val newTrainingTimeWeekday: String = "1",
    val newTrainingTimeStart: String = "",
    val newTrainingTimeEnd: String = "",
    val editingTrainingTimeId: String? = null,
    val editingTrainingTimeWeekday: String = "1",
    val editingTrainingTimeStart: String = "",
    val editingTrainingTimeEnd: String = "",
    val timeActionLoading: Boolean = false,
    val errorMessage: UiText? = null,
    val successMessage: UiText? = null
)

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

enum class ClubSettingsTab {
    Settings,
    TrainingGroups,
    TrainingTimes
}
