package com.adealink.weparty.playmate.list.viewmodel

import androidx.lifecycle.MutableLiveData
import com.adealink.frame.base.Rlt
import com.adealink.frame.mvvm.livedata.ExtMutableLiveData
import com.adealink.frame.mvvm.viewmodel.BaseViewModel
import com.adealink.frame.network.data.PageReq
import com.adealink.weparty.App
import com.adealink.weparty.module.order.OrderModule
import com.adealink.weparty.network.data.NoMoreDataError
import com.adealink.weparty.playmate.data.PlaymateListData
import com.adealink.weparty.playmate.data.PlaymateListOtherOptions
import com.adealink.weparty.playmate.data.PlaymateListReq
import com.adealink.weparty.playmate.data.PriceSort
import com.adealink.weparty.playmate.data.StarOption
import com.adealink.weparty.playmate.datasource.remote.PlaymateHttpService
import com.adealink.weparty.playmate.findpartner.data.OptionData
import com.adealink.weparty.util.PageHandler
import kotlinx.coroutines.launch

class PlaymateListViewModel : BaseViewModel() {

    private val playmateHttpService by lazy {
        App.instance.networkService.getHttpService(PlaymateHttpService::class.java)
    }

    private val playmateList = mutableListOf<PlaymateListData>()
    val listLD = MutableLiveData<List<PlaymateListData>>()
    val listRltLD = ExtMutableLiveData<Rlt<Any>>()

    private var firstCategoryCode: String? = null
    private var categoryCode: String? = null
    private val pageHandler = PageHandler()

    val starRankLD = ExtMutableLiveData<StarOption>()

    val priceRankLD = ExtMutableLiveData<PriceSort>()

    var optionGender: Int? = null
    var optionAge: Int? = null
    var optionPriceRange: Int? = null
    var otherOptions: List<OptionData>? = null

    fun setCategoryCode(
        firstCategoryCode: String?,
        code: String?,

        optionGender: Int? = null,
        optionAge: Int? = null,
        optionStar: Int? = null,
        optionPriceRange: Int? = null,
        otherOptions: List<OptionData>? = null
    ) {
        this.firstCategoryCode = firstCategoryCode
        categoryCode = code
        this.optionGender = optionGender
        this.optionAge = optionAge
        this.optionPriceRange = optionPriceRange
        this.otherOptions = otherOptions
        starRankLD.send(StarOption.map(optionStar))
        pageHandler.reset()
        playmateList.clear()
    }

    fun changeStarSort() {
        val current = starRankLD.value ?: StarOption.DEFAULT
        val next = when (current) {
            StarOption.ASC -> {
                StarOption.DESC
            }

            StarOption.DESC -> {
                StarOption.DEFAULT
            }

            StarOption.DEFAULT -> {
                StarOption.ASC
            }
        }
        this.starRankLD.send(next)
    }

    fun changePriceSort() {
        val current = priceRankLD.value ?: PriceSort.DEFAULT
        val next = when (current) {
            PriceSort.ASC -> {
                PriceSort.DESC
            }

            PriceSort.DESC -> {
                PriceSort.DEFAULT
            }

            PriceSort.DEFAULT -> {
                PriceSort.ASC
            }
        }
        this.priceRankLD.send(next)
    }

    fun refreshList() {
        viewModelScope.launch {
            pageHandler.reset()
            playmateList.clear()
            pullList()
        }
    }

    fun loadMoreList() {
        viewModelScope.launch {
            pullList()
        }
    }

    fun hasMoreData(): Boolean {
        return !pageHandler.isEnd
    }

    private suspend fun pullList() {
        if (pageHandler.isEnd) {
            listRltLD.send(Rlt.Failed(NoMoreDataError()))
            return
        }
        val rlt = playmateHttpService.getPlaymateList(
            PlaymateListReq(
                firstCode = firstCategoryCode,
                code = categoryCode,

                ageRange = optionAge,
                gender = optionGender,
                priceRange = optionPriceRange,

                sortByStar = starRankLD.value?.value ?: StarOption.DEFAULT.value,
                sortByPrice = priceRankLD.value?.value ?: PriceSort.DEFAULT.value,

                otherOptions = otherOptions?.mapNotNull {
                    if (it.key.isNullOrEmpty() || it.value.isNullOrEmpty()) {
                        null
                    } else {
                        PlaymateListOtherOptions(it.key, listOf(it.value))
                    }
                },

                page = PageReq(size = pageHandler.pageSize, next = pageHandler.currentPage)
            )
        )
        when (rlt) {
            is Rlt.Failed -> {
                listRltLD.send(rlt)
            }

            is Rlt.Success -> {
                pageHandler.nextPage(rlt.data.data?.next)
                playmateList.addAll(rlt.data.data?.list ?: emptyList())
                listRltLD.send(rlt)
                listLD.send(playmateList)
            }
        }
    }

}