package com.gh.gamecenter.category2

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.gh.common.util.LogUtils
import com.gh.common.view.CategoryFilterView
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.entity.CategoryEntity
import com.gh.gamecenter.entity.SidebarsEntity
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.livedata.Event
import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.disposables.CompositeDisposable

class CategoryV2ViewModel : ViewModel() {

    private val compositeDisposable = CompositeDisposable()
    private val api = RetrofitManager.getInstance().api
    var sidebarsLiveData = MutableLiveData<SidebarsEntity?>()
    var directoriesLiveData = MutableLiveData<List<CategoryEntity>>()

    var entrance: String = ""
    private var pageId = ""
    var pageName = ""
        private set

    fun init(entrance: String) {
        this.entrance = entrance
    }

    fun loadData(pageId: String, pageName: String) {
        this.pageId = pageId
        this.pageName = pageName

        val sidebarsObservable = api.getSidebars(pageId)
        val directoriesObservable = api.getCategoryDirectories(pageId)
            .onErrorReturnItem(listOf())
        sidebarsObservable.zipWith(directoriesObservable) { t1, t2 ->
            t1 to t2
        }.compose(singleToMain())
            .subscribe(object : BiResponse<Pair<SidebarsEntity, List<CategoryEntity>>>() {
                override fun onSuccess(data: Pair<SidebarsEntity, List<CategoryEntity>>) {
                    val (sidebarsData, directories) = data
                    directoriesLiveData.value = directories
                    sidebarsLiveData.value = sidebarsData
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    sidebarsLiveData.postValue(null)
                }

            }).let(compositeDisposable::add)
    }

    fun clearSelectedTag() {
        logClickReset("全部类别")
        val filteredList = _selectedSubCategories.value
        if (!filteredList.isNullOrEmpty()) {
            _selectedSubCategories.value = mutableListOf()

            val directories = directoriesLiveData.value ?: return
            directories.forEach {
                it.data?.forEach { child ->
                    child.selected = false
                }
            }
            directoriesLiveData.value = directories
        }
    }

    fun logAppearance() {
        LogUtils.logCategoryV2AppearanceEvent(entrance, pageName)
    }

    fun logClickSide() {
        val sidebars = sidebarsLiveData.value?.sidebars
        val selectedPosition = selectedSidebarsPosition.value ?: 0
        val selectedCategoryName = sidebars?.getOrNull(selectedPosition)?.name ?: ""
        LogUtils.logCategoryV2ClickSideEvent(entrance, pageName, selectedCategoryName, selectedPosition)
    }

    private fun logClickClassification(selected: SelectedTags) {
        LogUtils.logCategoryV2ClickClassificationEvent(
            entrance,
            pageName,
            selectedSidebarsName,
            selected.parentName,
            selected.category.name ?: "",
            selected.parentPosition,
            selected.position
        )
    }

    private fun logClickClassificationDelete(directoryName: String, categoryName: String, location: String) {
        LogUtils.logCategoryV2ClickClassificationDeleteEvent(
            entrance,
            pageName,
            directoryName,
            categoryName,
            location
        )
    }

    fun logClickDetermine() {
        val categoryNames = selectedSubCategories.value?.joinToString("+") { it.category.name ?: "" }
        LogUtils.logCategoryV2ClickDetermineEvent(entrance, pageName, categoryNames ?: "")
    }

    fun logClickReset(location: String) {
        val categoryName = selectedSubCategories.value?.joinToString("+") { it.category.name ?: "" }
        LogUtils.logCategoryV2ClickResetEvent(entrance, pageName, categoryName ?: "", location)
    }

    private val _notifySubCategorySelected = MutableLiveData<Event<String>>()
    val notifySubCategorySelected: LiveData<Event<String>> = _notifySubCategorySelected

    private val _selectedSubCategories = MutableLiveData<List<SelectedTags>>()
    val selectedSubCategories: LiveData<List<SelectedTags>> = _selectedSubCategories
    fun addSubCategorySelected(selected: SelectedTags) {
        val list = _selectedSubCategories.value
        val newData = if (list == null) {
            mutableListOf(selected)
        } else {
            list + selected
        }
        selected.category.selected = true
        _selectedSubCategories.value = newData

        // 当搜索条件发生变化时，侧边栏默认选中 “全部”
        selectSidebarsPosition(0, false)

        updateGameFiltered()
        _notifySubCategorySelected.value = Event(selected.parentId)
        logClickClassification(selected)
    }

    fun removeSubCategorySelected(parentId: String, categoryId: String, location: String) {
        val list = _selectedSubCategories.value ?: return
        val position = list.indexOfFirst {
            it.parentId == parentId && categoryId == it.category.id
        }
        if (position != -1) {
            val item = list[position]

            item.category.selected = false
            _selectedSubCategories.value = list - item

            updateGameFiltered()
            _notifySubCategorySelected.value = Event(parentId)

            logClickClassificationDelete(item.parentName, item.category.name ?: "", location)
        }

    }

    private val _selectedSidebarsPosition = MutableLiveData<Int>()
    val selectedSidebarsPosition: LiveData<Int> = _selectedSidebarsPosition
    val selectedSidebarsName: String
        get() = sidebarsLiveData.value?.sidebars?.getOrNull(selectedSidebarsPosition.value ?: 0)?.name ?: ""

    fun selectSidebarsPosition(position: Int, triggerSearch: Boolean = true) {
        val oldPosition = _selectedSidebarsPosition.value ?: INVALID_POSITION
        if (position != oldPosition) {
            _selectedSidebarsPosition.value = position
            // 如果是点击搜索而被动切换到 “全部” tab，则这里不需要更新筛选条件
            if (triggerSearch && position != INVALID_POSITION) {
                updateGameFiltered()
            }
        }
    }

    private val _gameFiltered = MutableLiveData<GameFiltered>()
    val gameFiltered: LiveData<GameFiltered> = _gameFiltered
    fun updateGameFiltered(
        size: SubjectSettingEntity.Size? = null,
        sortType: CategoryFilterView.SortType? = null
    ) {
        val oldFiltered = _gameFiltered.value
        val newSize = size ?: oldFiltered?.size ?: SubjectSettingEntity.Size()
        val newSortType = sortType ?: oldFiltered?.sortType ?: CategoryFilterView.SortType.RECOMMENDED
        val selectedSidebarPosition = selectedSidebarsPosition.value ?: 0
        val categoryIds = selectedSubCategories.value?.joinToString("-") { it.category.id } ?: ""
        val sidebarCategoryId =
            sidebarsLiveData.value?.sidebars?.getOrNull(selectedSidebarPosition)?.categoryId ?: "all"
        _gameFiltered.value = GameFiltered(newSize, newSortType, categoryIds, sidebarCategoryId)
    }

    override fun onCleared() {
        super.onCleared()
        compositeDisposable.clear()
    }

    companion object {
        private const val INVALID_POSITION = -1
    }

    data class SelectedTags(
        val parentId: String,
        val parentName: String,
        val parentPosition: Int,
        val category: CategoryEntity,
        val position: Int
    )

    data class GameFiltered(
        val size: SubjectSettingEntity.Size = SubjectSettingEntity.Size(),
        val sortType: CategoryFilterView.SortType = CategoryFilterView.SortType.RECOMMENDED,
        val categoryIds: String = "",
        val sidebarCategoryId: String = "全部"
    )
}