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.ClubAccessRequestResult
import de.trainingstagebuch.app.repository.ClubDetails
import de.trainingstagebuch.app.repository.ClubResult
import de.trainingstagebuch.app.repository.MemberItem
import de.trainingstagebuch.app.repository.MembersResult
import de.trainingstagebuch.app.services.AppServices
import de.trainingstagebuch.app.utils.ErrorMessageFormatter
import de.trainingstagebuch.app.utils.UiText
import de.trainingstagebuch.app.utils.ViewModelStateUtils
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

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

    private val homeService = AppServices.homeService

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

    fun load(clubId: String) {
        if (clubId.isBlank()) {
            _state.update {
                it.copy(
                    status = ShowClubStatus.Error,
                    errorMessage = UiText(R.string.error_unknown)
                )
            }
            return
        }
        if (_state.value.loadingClubId == clubId && _state.value.status == ShowClubStatus.Success) return

        viewModelScope.launch {
            _state.update {
                it.copy(
                    status = ShowClubStatus.Loading,
                    errorMessage = null,
                    infoMessage = null,
                    loadingClubId = clubId
                )
            }

            when (val result = homeService.loadClub(clubId)) {
                is ClubResult.Success -> {
                    val openRequests = when (val pendingResult = homeService.loadNotApprovedMembers(clubId)) {
                        is MembersResult.Success -> pendingResult.members
                        is MembersResult.Error -> emptyList()
                    }
                    _state.update {
                        it.copy(
                            status = ShowClubStatus.Success,
                            club = result.data,
                            openAccessRequests = openRequests,
                            accessRequested = false,
                            requestingAccess = false,
                            loadingClubId = clubId
                        )
                    }
                }

                is ClubResult.AccessDenied -> {
                    _state.update {
                        it.copy(
                            status = ShowClubStatus.AccessDenied,
                            club = null,
                            accessRequested = result.requested,
                            requestingAccess = false,
                            infoMessage = if (result.requested) UiText(R.string.show_club_access_request_pending) else null,
                            errorMessage = result.message
                                ?.takeIf { msg -> msg.isNotBlank() }
                                ?.let { msg -> UiText(R.string.error_dynamic, args = listOf(msg)) },
                            loadingClubId = clubId
                        )
                    }
                }

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

    fun requestAccess() {
        val clubId = _state.value.loadingClubId?.trim().orEmpty()
        if (clubId.isBlank()) return

        viewModelScope.launch {
            _state.update { it.copy(requestingAccess = true, errorMessage = null) }
            when (val result = homeService.requestClubAccess(clubId)) {
                is ClubAccessRequestResult.Success,
                is ClubAccessRequestResult.AlreadyRequested -> {
                    _state.update {
                        it.copy(
                            status = ShowClubStatus.AccessDenied,
                            requestingAccess = false,
                            accessRequested = true,
                            infoMessage = UiText(R.string.show_club_access_request_pending)
                        )
                    }
                }

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

data class ShowClubUiState(
    val status: ShowClubStatus = ShowClubStatus.Idle,
    val club: ClubDetails? = null,
    val openAccessRequests: List<MemberItem> = emptyList(),
    val errorMessage: UiText? = null,
    val infoMessage: UiText? = null,
    val loadingClubId: String? = null,
    val accessRequested: Boolean = false,
    val requestingAccess: Boolean = false
)

enum class ShowClubStatus {
    Idle,
    Loading,
    Success,
    AccessDenied,
    Error
}
