package id.iiyh.inatrading.feature.favorite.presentation

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import id.iiyh.inatrading.core.data.remote.SessionExpiredException
import id.iiyh.inatrading.feature.auth.domain.repository.AuthRepository
import id.iiyh.inatrading.feature.favorite.domain.FavoriteGroupSummary
import id.iiyh.inatrading.feature.favorite.domain.FavoriteRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

data class FavoritesUiState(
    val groups: List<FavoriteGroupSummary> = emptyList(),
    val isLoading: Boolean = false,
    val isSubmitting: Boolean = false,
    val errorMessage: String? = null,
    val sessionExpired: Boolean = false,
)

@HiltViewModel
class FavoritesViewModel @Inject constructor(
    private val favoriteRepository: FavoriteRepository,
    private val authRepository: AuthRepository,
) : ViewModel() {

    private val _uiState = MutableStateFlow(FavoritesUiState())
    val uiState: StateFlow<FavoritesUiState> = _uiState.asStateFlow()

    init {
        loadFavorites()
    }

    fun loadFavorites() {
        viewModelScope.launch {
            _uiState.update { it.copy(isLoading = true, isSubmitting = false, errorMessage = null, sessionExpired = false) }
            favoriteRepository.getFavoriteGroups()
                .onSuccess { groups ->
                    _uiState.update {
                        it.copy(
                            groups = groups.sortedByDescending(FavoriteGroupSummary::isDefault).sortedBy { item -> item.name.lowercase() },
                            isLoading = false,
                            isSubmitting = false,
                            errorMessage = null,
                            sessionExpired = false,
                        )
                    }
                }
                .onFailure { error ->
                    handleFailure(
                        error = error,
                        fallbackMessage = "Gagal memuat koleksi favorit",
                        updateLoading = true,
                    )
                }
        }
    }

    fun createGroup(name: String) {
        mutate {
            favoriteRepository.createFavoriteGroup(name)
        }
    }

    fun renameGroup(favoriteId: String, name: String) {
        mutate {
            favoriteRepository.updateFavoriteGroup(favoriteId = favoriteId, name = name)
        }
    }

    fun deleteGroup(favoriteId: String) {
        mutate {
            favoriteRepository.deleteFavoriteGroup(favoriteId)
        }
    }

    private fun mutate(block: suspend () -> Result<Unit>) {
        viewModelScope.launch {
            _uiState.update { it.copy(isSubmitting = true, errorMessage = null, sessionExpired = false) }
            block()
                .onSuccess { loadFavorites() }
                .onFailure { error ->
                    handleFailure(
                        error = error,
                        fallbackMessage = "Terjadi kesalahan",
                        updateLoading = false,
                    )
                }
        }
    }

    fun consumeSessionExpired() {
        _uiState.update { it.copy(sessionExpired = false) }
    }

    private suspend fun handleFailure(
        error: Throwable,
        fallbackMessage: String,
        updateLoading: Boolean,
    ) {
        if (error is SessionExpiredException) {
            authRepository.logout()
            _uiState.update {
                it.copy(
                    isLoading = false,
                    isSubmitting = false,
                    errorMessage = null,
                    sessionExpired = true,
                )
            }
            return
        }

        _uiState.update {
            it.copy(
                isLoading = if (updateLoading) false else it.isLoading,
                isSubmitting = false,
                errorMessage = error.message ?: fallbackMessage,
                sessionExpired = false,
            )
        }
    }
}
