package id.iiyh.inatrading.feature.cart.presentation

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import id.iiyh.inatrading.core.data.local.SessionManager
import id.iiyh.inatrading.core.data.remote.SessionExpiredException
import id.iiyh.inatrading.feature.auth.domain.repository.AuthRepository
import id.iiyh.inatrading.feature.cart.data.model.CartGroup
import id.iiyh.inatrading.feature.cart.domain.CartRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

data class CartUiState(
    val itemCount: Int = 0,
    val isLoggedIn: Boolean = false,
    val isLoadingCart: Boolean = false,
    val updatingItemIds: Set<String> = emptySet(),
    val cartGroups: List<CartGroup> = emptyList(),
    val totalPrice: Double = 0.0,
    val errorMessage: String? = null,
)

@HiltViewModel
class CartViewModel @Inject constructor(
    private val cartRepository: CartRepository,
    private val authRepository: AuthRepository,
    sessionManager: SessionManager,
) : ViewModel() {

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

    init {
        sessionManager.token
            .distinctUntilChanged()
            .onEach { token ->
                val isLoggedIn = !token.isNullOrBlank()
                _uiState.update {
                    it.copy(
                        isLoggedIn = isLoggedIn,
                        itemCount = if (isLoggedIn) it.itemCount else 0,
                        cartGroups = if (isLoggedIn) it.cartGroups else emptyList(),
                        totalPrice = if (isLoggedIn) it.totalPrice else 0.0,
                        errorMessage = null,
                    )
                }
                if (isLoggedIn) {
                    refreshCartCount()
                }
            }
            .launchIn(viewModelScope)
    }

    fun refreshCartCount() {
        if (!_uiState.value.isLoggedIn) {
            _uiState.update { it.copy(itemCount = 0) }
            return
        }

        viewModelScope.launch {
            cartRepository.getCartCount()
                .onSuccess { count ->
                    _uiState.update { it.copy(itemCount = count) }
                }
                .onFailure(::handleFailure)
        }
    }

    fun onItemAdded(quantity: Int = 1) {
        if (!_uiState.value.isLoggedIn || quantity <= 0) return
        _uiState.update { state ->
            state.copy(itemCount = state.itemCount + quantity)
        }
    }

    fun loadCart() {
        if (!_uiState.value.isLoggedIn) {
            _uiState.update {
                it.copy(
                    isLoadingCart = false,
                    updatingItemIds = emptySet(),
                    cartGroups = emptyList(),
                    totalPrice = 0.0,
                    errorMessage = null,
                )
            }
            return
        }

        viewModelScope.launch {
            _uiState.update { it.copy(isLoadingCart = true, errorMessage = null) }
            cartRepository.getCartGroups()
                .onSuccess { groups ->
                    val totalPrice = groups.sumOf { group ->
                        group.cartItems.sumOf { item ->
                            (item.productModel?.price ?: 0.0) * (item.quantity ?: 0)
                        }
                    }
                    val count = groups.sumOf { group ->
                        group.cartItems.sumOf { item -> item.quantity ?: 0 }
                    }
                    _uiState.update {
                        it.copy(
                            isLoadingCart = false,
                            cartGroups = groups,
                            totalPrice = totalPrice,
                            itemCount = count,
                            updatingItemIds = emptySet(),
                            errorMessage = null,
                        )
                    }
                }
                .onFailure { error ->
                    _uiState.update { it.copy(isLoadingCart = false) }
                    handleFailure(error)
                }
        }
    }

    fun changeQuantity(
        cartItemId: String,
        currentQuantity: Int,
        quantityDelta: Int,
    ) {
        if (!_uiState.value.isLoggedIn) return
        if (cartItemId.isBlank()) return
        if (currentQuantity + quantityDelta < 1) {
            _uiState.update {
                it.copy(errorMessage = "Jumlah minimum produk di keranjang adalah 1")
            }
            return
        }
        if (_uiState.value.updatingItemIds.contains(cartItemId)) return

        viewModelScope.launch {
            _uiState.update {
                it.copy(updatingItemIds = it.updatingItemIds + cartItemId)
            }
            cartRepository.updateCartQuantity(
                cartItemId = cartItemId,
                quantityDelta = quantityDelta,
            ).onSuccess {
                loadCart()
            }.onFailure { error ->
                _uiState.update {
                    it.copy(updatingItemIds = it.updatingItemIds - cartItemId)
                }
                handleFailure(error)
            }
        }
    }

    fun clearError() {
        _uiState.update { it.copy(errorMessage = null) }
    }

    private fun handleFailure(error: Throwable) {
        if (error is SessionExpiredException) {
            viewModelScope.launch { authRepository.logout() }
            _uiState.update {
                it.copy(
                    itemCount = 0,
                isLoggedIn = false,
                isLoadingCart = false,
                updatingItemIds = emptySet(),
                cartGroups = emptyList(),
                totalPrice = 0.0,
                errorMessage = null,
                )
            }
            return
        }

        _uiState.update {
            it.copy(
                isLoadingCart = false,
                errorMessage = error.message ?: "Gagal memuat keranjang",
            )
        }
    }
}
