package com.pixelized.biblib.ui.screen.home.filter.viewModel

import android.app.Application
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.*
import com.pixelized.biblib.R
import com.pixelized.biblib.model.book.Genre
import com.pixelized.biblib.model.search.FilterType
import com.pixelized.biblib.repository.search.ISearchRepository
import com.pixelized.biblib.ui.screen.home.filter.FilterItemUio
import com.pixelized.biblib.ui.screen.home.filter.IFilterViewModel
import com.pixelized.biblib.ui.screen.home.filter.source.GenreSearchSource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.plus
import javax.inject.Inject

@HiltViewModel
class GenreFilterViewModel @Inject constructor(
    application: Application,
    private val searchRepository: ISearchRepository,
) : ViewModel(), IFilterViewModel {

    override val title: String = application.getString(
        R.string.search_filter_title,
        application.getString(R.string.search_filter_genre),
    )

    private var source: GenreSearchSource? = null
    override val paging: Flow<PagingData<FilterItemUio>>

    private val _search = mutableStateOf("")
    override val search: State<String> = _search

    init {
        val authorFlow = Pager(
            config = PagingConfig(
                pageSize = AUTHOR_FILTER_PAGE_SIZE,
                enablePlaceholders = true,
            ),
            pagingSourceFactory = ::buildSource,
        ).flow
        paging = authorFlow
            .map {
                it.map { data ->
                    FilterItemUio(
                        id = FilterType.Genre,
                        filterId = data.id,
                        filterLabel = data.name,
                    )
                }
            }
            .cachedIn(viewModelScope + Dispatchers.IO)
    }

    override fun updateSearch(criteria: String) {
        _search.value = criteria
        source?.invalidate()
    }

    private fun buildSource(): PagingSource<Int, Genre> {
        return GenreSearchSource(
            searchRepository = searchRepository,
            search = search.value,
            limit = AUTHOR_FILTER_PAGE_SIZE
        ).also {
            source = it
        }
    }

    companion object {
        private const val AUTHOR_FILTER_PAGE_SIZE = 20
    }
}