package id.iiyh.inatrading.feature.product.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.core.data.local.SessionManager
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 id.iiyh.inatrading.feature.product.data.model.ProductItem
import id.iiyh.inatrading.feature.product.domain.ProductRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.SharingStarted
import javax.inject.Inject

private const val PRODUCT_PAGE_LIMIT = 10

data class ProductsUiState(
    val items: List<ProductItem> = emptyList(),
    val isInitialLoading: Boolean = false,
    val isAppending: Boolean = false,
    val errorMessage: String? = null,
    val currentPage: Int = 0,
    val totalPage: Int = 0,
    val totalItem: Int = 0,
    val pageSize: Int = PRODUCT_PAGE_LIMIT,
    val selectedCategory: ProductCategory = ProductCategory.All,
    val searchQuery: String = "",
    val favoriteIds: Set<String> = emptySet(),
    val isLoggedIn: Boolean = false,
    val favoriteGroups: List<FavoriteGroupSummary> = emptyList(),
    val favoriteProductId: String? = null,
    val favoriteDialogOpen: Boolean = false,
    val favoriteCreateMode: Boolean = false,
    val favoriteActionLoading: Boolean = false,
    val favoriteMessage: String? = null,
    val sessionExpired: Boolean = false,
) {
    val hasMore: Boolean
        get() = totalPage == 0 || currentPage < totalPage || items.size < totalItem

    val filteredItems: List<ProductItem>
        get() = items.filter { product ->
            val matchesCategory = when (selectedCategory) {
                ProductCategory.All -> true
                ProductCategory.Local -> product.market.equals("Local Market", ignoreCase = true)
                ProductCategory.International -> product.market.equals("International", ignoreCase = true)
            }

            val matchesQuery = searchQuery.isBlank() ||
                product.name.contains(searchQuery, ignoreCase = true) ||
                product.market.orEmpty().contains(searchQuery, ignoreCase = true)

            matchesCategory && matchesQuery
        }
}

enum class ProductCategory(val label: String) {
    All("Semua"),
    Local("Lokal"),
    International("Internasional"),
}

@HiltViewModel
class ProductsViewModel @Inject constructor(
    private val productRepository: ProductRepository,
    private val favoriteRepository: FavoriteRepository,
    private val authRepository: AuthRepository,
    sessionManager: SessionManager,
) : ViewModel() {

    private val baseState = MutableStateFlow(ProductsUiState())
    val uiState: StateFlow<ProductsUiState> = combine(
        baseState,
        sessionManager.token,
    ) { state, token ->
        state.copy(isLoggedIn = !token.isNullOrBlank())
    }.stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5_000),
        initialValue = ProductsUiState(),
    )

    init {
        loadInitial()
    }

    fun loadInitial() {
        baseState.update {
            it.copy(
                items = emptyList(),
                isInitialLoading = true,
                isAppending = false,
                errorMessage = null,
                currentPage = 0,
                totalPage = 0,
                totalItem = 0,
            )
        }
        loadPage(1)
    }

    fun loadNextPage() {
        val state = baseState.value
        if (state.isInitialLoading || state.isAppending || !state.hasMore) return
        loadPage(state.currentPage + 1)
    }

    fun onSearchQueryChange(value: String) {
        baseState.update { it.copy(searchQuery = value) }
    }

    fun onCategorySelected(category: ProductCategory) {
        baseState.update { it.copy(selectedCategory = category) }
    }

    fun toggleFavorite(productId: String) {
        if (baseState.value.favoriteIds.contains(productId)) {
            removeProductFromFavorite(productId)
            return
        }
        openFavoriteDialog(productId)
    }

    fun dismissFavoriteDialog() {
        baseState.update {
            it.copy(
                favoriteDialogOpen = false,
                favoriteCreateMode = false,
                favoriteActionLoading = false,
                favoriteGroups = emptyList(),
                favoriteProductId = null,
            )
        }
    }

    fun showCreateFavoriteGroup() {
        baseState.update { it.copy(favoriteCreateMode = true) }
    }

    fun hideCreateFavoriteGroup() {
        baseState.update { it.copy(favoriteCreateMode = false) }
    }

    fun consumeFavoriteMessage() {
        baseState.update { it.copy(favoriteMessage = null) }
    }

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

    fun createFavoriteGroup(name: String) {
        val productId = baseState.value.favoriteProductId ?: return
        viewModelScope.launch {
            baseState.update { it.copy(favoriteActionLoading = true, favoriteMessage = null) }
            favoriteRepository.createFavoriteGroup(name)
                .onSuccess {
                    favoriteRepository.getFavoriteGroups()
                        .onSuccess { groups ->
                            baseState.update {
                                it.copy(
                                    favoriteGroups = groups,
                                    favoriteCreateMode = false,
                                    favoriteActionLoading = false,
                                    favoriteProductId = productId,
                                )
                            }
                        }
                        .onFailure { handleFavoriteFailure(it, "Gagal memuat koleksi favorit") }
                }
                .onFailure { handleFavoriteFailure(it, "Gagal membuat koleksi favorit") }
        }
    }

    fun addProductToFavorite(favoriteId: String) {
        val productId = baseState.value.favoriteProductId ?: return
        viewModelScope.launch {
            baseState.update { it.copy(favoriteActionLoading = true, favoriteMessage = null) }
            favoriteRepository.addProductToFavorite(
                favoriteId = favoriteId,
                productId = productId,
            ).onSuccess {
                baseState.update { state ->
                    state.copy(
                        favoriteIds = state.favoriteIds + productId,
                        favoriteDialogOpen = false,
                        favoriteCreateMode = false,
                        favoriteActionLoading = false,
                        favoriteGroups = emptyList(),
                        favoriteProductId = null,
                        favoriteMessage = PRODUCT_FAVORITE_ADDED_MESSAGE,
                    )
                }
            }.onFailure {
                handleFavoriteFailure(it, "Gagal menambahkan produk ke favorit")
            }
        }
    }

    private fun removeProductFromFavorite(productId: String) {
        viewModelScope.launch {
            baseState.update { it.copy(favoriteActionLoading = true, favoriteMessage = null) }
            favoriteRepository.removeProductFromFavorite(productId)
                .onSuccess {
                    baseState.update { state ->
                        state.copy(
                            favoriteIds = state.favoriteIds - productId,
                            favoriteActionLoading = false,
                            favoriteMessage = PRODUCT_FAVORITE_REMOVED_MESSAGE,
                        )
                    }
                }
                .onFailure {
                    handleFavoriteFailure(it, "Gagal menghapus produk dari favorit")
                }
        }
    }

    private fun loadPage(page: Int) {
        viewModelScope.launch {
            baseState.update {
                it.copy(
                    isInitialLoading = page == 1,
                    isAppending = page > 1,
                    errorMessage = if (page == 1) null else it.errorMessage,
                )
            }

            productRepository.getProducts(page = page, limit = PRODUCT_PAGE_LIMIT)
                .onSuccess { result ->
                    baseState.update { state ->
                        val mergedItems = if (page == 1) result.items else state.items + result.items
                        val responseFavoriteIds = result.items
                            .filter(ProductItem::isFavorite)
                            .map(ProductItem::id)
                            .toSet()
                        val favoriteIds = if (page == 1) {
                            mergedItems.filter(ProductItem::isFavorite).map(ProductItem::id).toSet()
                        } else {
                            state.favoriteIds + responseFavoriteIds
                        }

                        state.copy(
                            items = mergedItems,
                            isInitialLoading = false,
                            isAppending = false,
                            errorMessage = null,
                            currentPage = page,
                            totalPage = result.totalPage,
                            totalItem = result.totalItem,
                            favoriteIds = favoriteIds,
                        )
                    }
                }
                .onFailure { error ->
                    baseState.update { state ->
                        state.copy(
                            isInitialLoading = false,
                            isAppending = false,
                            errorMessage = error.message ?: "Gagal memuat produk",
                        )
                    }
                }
        }
    }

    private fun openFavoriteDialog(productId: String) {
        viewModelScope.launch {
            baseState.update {
                it.copy(
                    favoriteDialogOpen = true,
                    favoriteProductId = productId,
                    favoriteCreateMode = false,
                    favoriteActionLoading = true,
                    favoriteMessage = null,
                    sessionExpired = false,
                )
            }
            favoriteRepository.getFavoriteGroups()
                .onSuccess { groups ->
                    baseState.update {
                        it.copy(
                            favoriteGroups = groups,
                            favoriteCreateMode = groups.isEmpty(),
                            favoriteActionLoading = false,
                        )
                    }
                }
                .onFailure {
                    handleFavoriteFailure(it, "Gagal memuat koleksi favorit")
                }
        }
    }

    private suspend fun handleFavoriteFailure(
        error: Throwable,
        fallbackMessage: String,
    ) {
        if (error is SessionExpiredException) {
            authRepository.logout()
            baseState.update {
                it.copy(
                    favoriteDialogOpen = false,
                    favoriteCreateMode = false,
                    favoriteActionLoading = false,
                    favoriteGroups = emptyList(),
                    favoriteProductId = null,
                    favoriteMessage = null,
                    sessionExpired = true,
                )
            }
            return
        }

        baseState.update {
            it.copy(
                favoriteActionLoading = false,
                favoriteMessage = error.message ?: fallbackMessage,
            )
        }
    }
}

const val PRODUCT_FAVORITE_ADDED_MESSAGE = "PRODUCT_FAVORITE_ADDED"
const val PRODUCT_FAVORITE_REMOVED_MESSAGE = "PRODUCT_FAVORITE_REMOVED"
