package com.develop.main.init.ui.viewmodel

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.blankj.utilcode.util.NetworkUtils
import com.develop.food.base.api.FoodRepository
import com.develop.food.base.data.CategoryType
import com.develop.food.base.data.DataFactory
import com.develop.food.base.data.SortedType
import com.develop.food.base.data.model.CategoryModel
import com.develop.food.base.data.model.CommonSearchItem
import com.develop.food.base.data.model.FilterSortModel
import com.develop.food.base.data.model.FoodContentModel
import com.develop.food.base.data.model.NewsModel
import com.develop.food.base.http.observeStatus
import com.develop.food.base.repo.CURRENT_USER_ID
import com.develop.food.base.repo.FoodDataProvider
import com.develop.food.base.repo.entity.DevRecipe
import com.develop.food.base.repo.entity.DevRecipeCategory
import com.develop.food.base.utils.GlobalApp
import com.develop.food.base.utils.GlobalToast
import com.develop.food.base.utils.MmkvUtils
import com.develop.food.base.utils.ThreadUtils
import com.develop.main.R
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.lang.reflect.Type

class HomeViewModel : ViewModel() {
    val netFoodLiveData = MutableLiveData<Boolean>()
    val refreshRecipesLiveData = MutableLiveData<Boolean>()
    val localCategoryLiveData = MutableLiveData<MutableList<DevRecipeCategory>>()
    val localRecipesLiveData = MutableLiveData<MutableList<Any>>()
    val onlineCategoryLiveData = MutableLiveData<MutableList<DevRecipeCategory>>()
    val onLineRecipesLiveData = MutableLiveData<MutableList<Any>>()
    val hotWordSearchRecipesLiveData = MutableLiveData<MutableList<Any>>()
    var currCategoryName = ""
    private val userId = CURRENT_USER_ID

    val onLineHotTagsLiveData = MutableLiveData<MutableList<String>>()

    var noticesLiveData = MutableLiveData<MutableList<NewsModel>>()

    var recipesType = RecipesType.LOCAL

    var currentPage = 1
    var currentPageSize = 10
    var totalPageSize = 1

    var sortedType = SortedType.A2Z

    var tempOnLineRecipes = mutableListOf<DevRecipe>()
    private var requestVersion = 0
    var categorySizeList = HashMap<String, String>()
    var errorLiveData = MutableLiveData<Boolean>()

    fun queryRecipesCategory() {
        var allSize = 0
        FoodDataProvider.getDatabase().runInTransaction {
            val result = FoodDataProvider.getDatabase().recipeDao().queryCategory().toMutableList()
            categorySizeList.clear()
            result.forEach {
                val size = FoodDataProvider.getDatabase().recipeDao()
                    .queryRecipesByCategory(it.number ?: "").size
                categorySizeList[it.number ?: ""] = if (size.toString() == "null") {
                    "0"
                } else {
                    size.toString()
                }
            }
            result.sortBy {
                it.name
            }
            categorySizeList.forEach {
                allSize += it.value.toInt()
            }
            categorySizeList[GlobalApp().getString(R.string.all)] =
                allSize.toString()
            localCategoryLiveData.postValue(result)
        }
    }

    fun queryLocalRecipes(categoryNum: String) {
        ThreadUtils.runOnWorkThread({
            if (categoryNum.isEmpty()) {
                //获取所有的分类
                val favoriteRecipesList =
                    FoodDataProvider.getUserDatabase().userInfoDao().queryFavoriteRecipes(userId)
                        .toMutableList()
                val localRecipeList =
                    FoodDataProvider.getDatabase().recipeDao().queryAllRecipe().toMutableList()
                val starList = mutableListOf<Int>()
                localRecipeList.forEach {
                    val userTag = FoodDataProvider.getUserDatabase().userInfoDao().queryUserTag(
                        CURRENT_USER_ID, it.number ?: ""
                    )
                    starList.add(it.score?.toInt() ?: 0)
                }
                localRecipesLiveData.postValue(
                    DataFactory.genLocalRecipes(
                        currCategoryName,
                        localRecipeList,
                        favoriteRecipesList,
                        starList,
                        sortedType
                    )
                )
            } else {
                //获取当前分类
                val favoriteRecipesList =
                    FoodDataProvider.getUserDatabase().userInfoDao().queryFavoriteRecipes(userId)
                        .toMutableList()
                val localRecipeList =
                    FoodDataProvider.getDatabase().recipeDao().queryRecipesByCategory(categoryNum)
                        .toMutableList()
                val starList = mutableListOf<Int>()
                localRecipeList.forEach {
                    val userTag = FoodDataProvider.getUserDatabase().userInfoDao().queryUserTag(
                        CURRENT_USER_ID, it.number ?: ""
                    )
                    starList.add(it.score?.toInt() ?: 0)
                }
                localRecipesLiveData.postValue(
                    DataFactory.genLocalRecipes(
                        currCategoryName,
                        localRecipeList,
                        favoriteRecipesList,
                        starList,
                        sortedType
                    )
                )
            }
        })
    }

    fun queryRecipesByHotWord(hotWord: String, categoryType: CategoryType) {
        val result = mutableListOf<Any>()
        result.add(FilterSortModel(""))
        FoodDataProvider.getDatabase().runInTransaction {
            val recipeDao = FoodDataProvider.getDatabase().recipeDao()
            val recipesList = recipeDao.queryRecipeByName(hotWord)
            val foodList = mutableListOf<DevRecipe>()
            val allList = mutableListOf<DevRecipe>()
            recipeDao.queryFoodByFoodName(hotWord).forEach {
                it.recipeNumber?.apply {
                    recipeDao.queryRecipe(this)?.let { devRecipe ->
                        foodList.add(devRecipe)
                    }
                }
            }
            val recipeCount = recipesList.size
            val foodCount = foodList.size
            allList.addAll(recipesList)
            allList.addAll(foodList)
            result.add(CategoryModel(recipeCount + foodCount, recipeCount, foodCount))
            val favoriteRecipesList =
                FoodDataProvider.getUserDatabase().userInfoDao().queryFavoriteRecipes(userId)
                    .toMutableList()
            val favoriteRecipesIds = mutableListOf<String>()
            favoriteRecipesList.forEach {
                favoriteRecipesIds.add(it.favoriteRecipesId)
            }
            when (categoryType) {
                CategoryType.All -> {
                    allList.forEach {
                        result.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                it.score?.toInt() ?: 0,
                                DataFactory.getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                isLike = favoriteRecipesIds.contains(it.number),
                                foodId = it.number ?: "",
                                useNum = it.useNum?.toInt() ?: 0
                            )
                        )
                    }
                }

                CategoryType.Recipes -> {
                    recipesList.forEach {
                        result.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                it.score?.toInt() ?: 0,
                                DataFactory.getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                isLike = favoriteRecipesIds.contains(it.number),
                                foodId = it.number ?: "",
                                useNum = it.useNum?.toInt() ?: 0
                            )
                        )
                    }
                }

                CategoryType.Ingredients -> {
                    foodList.forEach {
                        result.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                it.score?.toInt() ?: 0,
                                DataFactory.getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                isLike = favoriteRecipesIds.contains(it.number),
                                foodId = it.number ?: "",
                                useNum = it.useNum?.toInt() ?: 0
                            )
                        )
                    }
                }
            }
            hotWordSearchRecipesLiveData.postValue(result)
        }
    }

    fun getOnLineCategoryList() {
        resetOnlineConfig()
        val version = ++requestVersion
        FoodRepository.getRecipesCategory().observeStatus(onSuccess = {
            if (version != requestVersion) {
                return@observeStatus
            }
            it?.categorys?.toMutableList()?.apply {
                onlineCategoryLiveData.postValue(this)
            }

        }, onFailed = {

        })
    }

    var loadIndex = 1
    fun getOnLineRecipeList(
        category: String,
        name: String,
        pageIndex: Int = 1,
        pageSize: Int = 10,
        isLoadMore: Boolean = false
    ) {
        if (!NetworkUtils.isConnected()){
            GlobalToast.showToast(GlobalApp().getString(R.string.network_wifi_status_disconnected))
            return
        }
        if (!isLoadMore) resetOnlineConfig()
        if (isLoadMore) {
            loadIndex++
        }
       val searchName =  if (name== GlobalApp().getString(R.string.all)){
            ""
        } else {
            name
        }
        FoodRepository.recipesList(category, searchName, loadIndex, pageSize).observeStatus(
            onFailed = {
                errorLiveData.postValue(true)
            },
            onSuccess = {
                val recipesList = it?.recipes?.toMutableList() ?: mutableListOf()
                val pager = it?.pager
                totalPageSize = pager?.pageCount ?: 1
                currentPage = pager?.pageIndex ?: 1
                FoodDataProvider.getUserDatabase().runInTransaction {

                    val favoriteRecipesList =
                        FoodDataProvider.getUserDatabase().userInfoDao()
                            .queryFavoriteRecipes(userId)
                            .toMutableList()
                    val starList = mutableListOf<Int>()
                    tempOnLineRecipes.addAll(recipesList)
                    tempOnLineRecipes.forEach { devRecipe ->
                        val userTag = FoodDataProvider.getUserDatabase().userInfoDao().queryUserTag(
                            CURRENT_USER_ID, devRecipe.number ?: ""
                        )
                        starList.add(devRecipe.score?.toInt() ?: 0)
                    }
                    onLineRecipesLiveData.postValue(
                        DataFactory.genNetRecipesData(
                            currCategoryName,
                            tempOnLineRecipes,
                            favoriteRecipesList,
                            starList, sortedType
                        )
                    )
                }
            })
    }


    fun getOnLineHotTags() {
        FoodRepository.getHotTags().observeStatus(onSuccess = {
            it?.hotTags?.toMutableList()?.apply {
                onLineHotTagsLiveData.postValue(this)
            }

        }, onFailed = {

        })
    }

    fun getNotices() {
        FoodRepository.getNotices().observeStatus(
            onSuccess = {
                val newsModelList = mutableListOf<NewsModel>()
                it?.informs?.forEach {
                    newsModelList.add(NewsModel(it.title, it.content, false))
                }
                noticesLiveData.postValue(newsModelList)
            },
            onFailed = {

            })
    }

    fun saveHistoryWords(hotWord: String) {
        var hotWordList: MutableList<String> = mutableListOf()
        val type: Type = object : TypeToken<List<String>>() {}.type
        val hotWordJson = MmkvUtils.getString("HistoryWords") ?: ""

        var commonDataList: MutableList<CommonSearchItem> = mutableListOf()

        val commonWordJson = MmkvUtils.getString("CommonWords") ?: ""
        if (commonWordJson.isNotEmpty()) {
            val type1: Type = object : TypeToken<List<CommonSearchItem>>() {}.type
            commonDataList = Gson().fromJson(commonWordJson, type1)
        }

        var hasWords = false
        commonDataList.forEach {
            if (it.name == hotWord) {
                it.count += 1
                hasWords = true
            }
        }
        if (!hasWords) {
            commonDataList.add(CommonSearchItem(hotWord, 1))
        }

        MmkvUtils.save("CommonWords", Gson().toJson(commonDataList))

        if (hotWordJson.isNotEmpty()) {
            hotWordList = Gson().fromJson(hotWordJson, type)
        }
        if (!hotWordList.contains(hotWord)) {
            hotWordList.add(hotWord)
        }
        MmkvUtils.save("HistoryWords", Gson().toJson(hotWordList))
    }


    private fun resetOnlineConfig() {
        currentPage = 1
        loadIndex = 1
        currentPageSize = 10
        totalPageSize = 1
        tempOnLineRecipes.clear()
    }

    enum class RecipesType {
        ONLINE,
        LOCAL
    }
}