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.OfficialTournamentItem
import de.trainingstagebuch.app.repository.OfficialTournamentDetailData
import de.trainingstagebuch.app.repository.OfficialTournamentSummary
import de.trainingstagebuch.app.repository.OfficialTournamentSummaryResult
import de.trainingstagebuch.app.repository.OfficialTournamentsResult
import de.trainingstagebuch.app.repository.OfficialTournamentUploadResult
import de.trainingstagebuch.app.repository.OfficialTournamentDetailResult
import de.trainingstagebuch.app.repository.OfficialTournamentActionResult
import de.trainingstagebuch.app.repository.MembersResult
import de.trainingstagebuch.app.repository.MemberItem
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 TournamentsViewModel(application: Application) : AndroidViewModel(application) {
    private val authService = AppServices.authService
    private val tournamentService = AppServices.tournamentService

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

    fun setTab(tab: TournamentTopTab) {
        _state.update { it.copy(activeTab = tab) }
        if (tab == TournamentTopTab.Official) {
            loadOfficial()
        }
    }

    fun retryOfficial() = loadOfficial()

    fun loadOfficialDetail(tournamentId: String) {
        viewModelScope.launch {
            val clubId = authService.session.first().currentClub?.trim().orEmpty()
            if (clubId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
                return@launch
            }
            _state.update { it.copy(officialActionLoading = true, selectedOfficialTournamentId = tournamentId) }
            when (val result = tournamentService.loadOfficialTournamentDetail(clubId, tournamentId)) {
                is OfficialTournamentDetailResult.Success -> {
                    _state.update {
                        it.copy(
                            officialActionLoading = false,
                            officialDetail = result.data
                        )
                    }
                }

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

    fun uploadOfficialPdf(fileName: String, bytes: ByteArray) {
        viewModelScope.launch {
            val clubId = authService.session.first().currentClub?.trim().orEmpty()
            if (clubId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
                return@launch
            }
            _state.update { it.copy(officialActionLoading = true, errorMessage = null) }
            when (val result = tournamentService.uploadOfficialTournamentPdf(clubId, fileName, bytes)) {
                is OfficialTournamentUploadResult.Success -> {
                    _state.update {
                        it.copy(
                            officialActionLoading = false,
                            successMessage = UiText(R.string.official_tournaments_upload_success)
                        )
                    }
                    loadOfficial()
                    result.tournamentId?.let { loadOfficialDetail(it) }
                }

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

    fun toggleOfficialWants(competitionId: Int, memberId: String, wants: Boolean) {
        val detail = _state.value.officialDetail ?: return
        val current = detail.participation.firstOrNull { it.competitionId == competitionId && it.memberId == memberId }
        upsertOfficialParticipation(
            competitionId = competitionId,
            memberId = memberId,
            wants = wants,
            registered = current?.registered == true,
            participated = current?.participated == true,
            placement = current?.placement
        )
    }

    fun setOfficialStatus(competitionId: Int, memberId: String, action: String) {
        val tournamentId = _state.value.selectedOfficialTournamentId ?: return
        viewModelScope.launch {
            val clubId = authService.session.first().currentClub?.trim().orEmpty()
            if (clubId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
                return@launch
            }
            _state.update { it.copy(officialActionLoading = true, errorMessage = null) }
            when (
                val result = tournamentService.updateOfficialParticipationStatus(
                    clubId = clubId,
                    tournamentId = tournamentId,
                    competitionId = competitionId,
                    memberId = memberId,
                    action = action
                )
            ) {
                is OfficialTournamentActionResult.Success -> {
                    _state.update {
                        it.copy(
                            officialActionLoading = false,
                            successMessage = ViewModelStateUtils.dynamicOrFallback(
                                result.message,
                                UiText(R.string.official_tournaments_status_updated)
                            )
                        )
                    }
                    loadOfficialDetail(tournamentId)
                }

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

    fun setOfficialPlacement(competitionId: Int, memberId: String, placement: String) {
        val detail = _state.value.officialDetail ?: return
        val current = detail.participation.firstOrNull { it.competitionId == competitionId && it.memberId == memberId }
        upsertOfficialParticipation(
            competitionId = competitionId,
            memberId = memberId,
            wants = current?.wants == true,
            registered = current?.registered == true,
            participated = current?.participated == true,
            placement = placement.trim().ifBlank { null }
        )
    }

    fun deleteOfficialTournament(tournamentId: String) {
        viewModelScope.launch {
            val clubId = authService.session.first().currentClub?.trim().orEmpty()
            if (clubId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
                return@launch
            }
            _state.update { it.copy(officialActionLoading = true, errorMessage = null) }
            when (val result = tournamentService.deleteOfficialTournament(clubId, tournamentId)) {
                is OfficialTournamentActionResult.Success -> {
                    _state.update {
                        it.copy(
                            officialActionLoading = false,
                            selectedOfficialTournamentId = if (it.selectedOfficialTournamentId == tournamentId) null else it.selectedOfficialTournamentId,
                            officialDetail = if (it.selectedOfficialTournamentId == tournamentId) null else it.officialDetail,
                            successMessage = ViewModelStateUtils.dynamicOrFallback(
                                result.message,
                                UiText(R.string.official_tournaments_deleted)
                            )
                        )
                    }
                    loadOfficial()
                }

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

    fun clearMessages() {
        _state.update { it.copy(errorMessage = null, successMessage = null) }
    }

    private fun loadOfficial() {
        viewModelScope.launch {
            val clubId = authService.session.first().currentClub?.trim().orEmpty()
            if (clubId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
                return@launch
            }
            _state.update { it.copy(officialLoading = true, errorMessage = null) }

            val tournaments = when (val result = tournamentService.loadOfficialTournaments(clubId)) {
                is OfficialTournamentsResult.Success -> result.items
                is OfficialTournamentsResult.Error -> {
                    _state.update {
                        it.copy(
                            officialLoading = false,
                            errorMessage = ViewModelStateUtils.normalizeUiText(
                                ErrorMessageFormatter.dynamicWithOptionalCode(result.message, result.code)
                            )
                        )
                    }
                    return@launch
                }
            }

            val summary = when (val result = tournamentService.loadOfficialSummary(clubId)) {
                is OfficialTournamentSummaryResult.Success -> result.data
                is OfficialTournamentSummaryResult.Error -> OfficialTournamentSummary(
                    total = tournaments.size,
                    plannedParticipations = 0
                )
            }

            _state.update {
                it.copy(
                    officialLoading = false,
                    officialTournaments = tournaments,
                    officialSummary = summary
                )
            }
            if (_state.value.officialMembers.isEmpty()) {
                when (val membersResult = tournamentService.loadMembers(clubId)) {
                    is MembersResult.Success -> {
                        _state.update { it.copy(officialMembers = membersResult.members) }
                    }
                    is MembersResult.Error -> Unit
                }
            }
        }
    }

    private fun upsertOfficialParticipation(
        competitionId: Int,
        memberId: String,
        wants: Boolean,
        registered: Boolean,
        participated: Boolean,
        placement: String?
    ) {
        val tournamentId = _state.value.selectedOfficialTournamentId ?: return
        viewModelScope.launch {
            val clubId = authService.session.first().currentClub?.trim().orEmpty()
            if (clubId.isBlank()) {
                _state.update { it.copy(errorMessage = UiText(R.string.error_no_current_club)) }
                return@launch
            }
            _state.update { it.copy(officialActionLoading = true, errorMessage = null) }
            when (
                val result = tournamentService.upsertOfficialParticipation(
                    clubId = clubId,
                    tournamentId = tournamentId,
                    competitionId = competitionId,
                    memberId = memberId,
                    wants = wants,
                    registered = registered,
                    participated = participated,
                    placement = placement
                )
            ) {
                is OfficialTournamentActionResult.Success -> {
                    _state.update {
                        it.copy(
                            officialActionLoading = false,
                            successMessage = ViewModelStateUtils.dynamicOrFallback(
                                result.message,
                                UiText(R.string.official_tournaments_participation_saved)
                            )
                        )
                    }
                    loadOfficialDetail(tournamentId)
                }

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

data class TournamentsUiState(
    val activeTab: TournamentTopTab = TournamentTopTab.Internal,
    val officialLoading: Boolean = false,
    val officialActionLoading: Boolean = false,
    val officialTournaments: List<OfficialTournamentItem> = emptyList(),
    val officialSummary: OfficialTournamentSummary? = null,
    val selectedOfficialTournamentId: String? = null,
    val officialDetail: OfficialTournamentDetailData? = null,
    val officialMembers: List<MemberItem> = emptyList(),
    val errorMessage: UiText? = null,
    val successMessage: UiText? = null
)

enum class TournamentTopTab {
    Internal,
    External,
    Mini,
    Official
}
