package com.develop.main.viewmodel

import android.util.Log
import androidx.annotation.RestrictTo.Scope
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.scopeNetLife
import com.develop.base.ext.getSN
import com.develop.base.mvvm.BaseViewModel
import com.develop.base.util.MMkvUtils
import com.develop.common.data_repo.FoodDataProvider
import com.develop.common.data_repo.db.*
import com.develop.common.data_repo.db.entity.DevRecipe
import com.develop.common.data_repo.db.entity.DevRecipeCategory
import com.develop.common.data_repo.db.entity.UserFavoriteRecipes
import com.develop.common.data_repo.net.Api
import com.develop.common.data_repo.net.model.response.*
import com.develop.common.tag.CURRENT_LANGUAGE
import com.develop.common.tag.CURRENT_USER_ID
import com.develop.common.widget.HomeOrBack
import com.drake.net.Get
import com.drake.net.utils.scope
import kotlinx.coroutines.Dispatchers

class HomeViewModel : BaseViewModel() {

    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>>()
    val onLineHotTagsLiveData = MutableLiveData<MutableList<String>>()
    var noticesLiveData = MutableLiveData<MutableList<Inform>>()
    var tempOnLineRecipes = mutableListOf<DevRecipe>()
    var moreLocalRecipeLiveData = MutableLiveData<MutableList<FoodContentModel>>()
    var moreSearchLocalRecipeLiveData = MutableLiveData<MutableList<FoodContentModel>>()

    var currCategoryName = ""
    var recipesType = RecipesType.LOCAL
    var isFromDownloadNewRecipesEntrance = false
    var currentPage = 1
    var currentPageSize = 12
    var totalPageSize = 1
    var sortedType = SortedType.A2Z
    var homeOrBackLiveData = MutableLiveData<HomeOrBack>()
    var isSearch = false
    private val userId = CURRENT_USER_ID

    private var totalLocalRecipes = mutableListOf<DevRecipe>()
    private var totalSearchLocalRecipes = mutableListOf<DevRecipe>()
    private var searchLocalRecipes = mutableListOf<DevRecipe>()
    private var searchLocalFood = mutableListOf<DevRecipe>()

    private var totalLocalSize = 0
    private var startSize = 0
    private var endSize = 11

    private var totalSearchLocalSize = 0
    private var searchLocalSize = 0
    private var foodSize = 0
    private var startSearchSize = 0
    private var endSearchSize = 11

    private var startRecipesSearchSize = 0
    private var endRecipesSearchSize = 11

    private var startFoodSearchSize = 0
    private var endFoodSearchSize = 11

    private var lastLocalRecipesShowList = mutableListOf<Any>()
    private var hasMoreLocal = false
    private var hasMoreTotalSearchLocal = false
    private var hasMoreSearchLocal = false
    private var hasMoreFoodLocal = false
    private var lastLocalRecipeList = mutableListOf<DevRecipe>()
    private var lastTotalLocalSearchRecipeList = mutableListOf<DevRecipe>()
    private var lastLocalSearchRecipeList = mutableListOf<DevRecipe>()
    private var lastLocalSearchFoodList = mutableListOf<DevRecipe>()
    private var localFavoriteRecipesList = mutableListOf<UserFavoriteRecipes>()
    private var lastSearchCategoryType = CategoryType.All

    private var recipeCount = 0
    private var foodCount = 0
    private var recipeDao = FoodDataProvider.getDatabase().recipeDao()

    /**查询本地菜谱分类*/
    fun queryRecipesCategory() {
        FoodDataProvider.getDatabase().runInTransaction {
            localCategoryLiveData.postValue(
                FoodDataProvider.getDatabase().recipeDao().queryCategory().toMutableList()
            )
        }
    }

    /**查询本地对应菜谱分类下的菜谱列表信息*/
    fun queryLocalRecipes(categoryNum: String) {
        scope(Dispatchers.IO) {
            startSize = 0
            endSize = 11
            localFavoriteRecipesList =
                FoodDataProvider.getUserDatabase().userInfoDao().queryFavoriteRecipes(userId)
                    .toMutableList()
            //获取所有的分类
            totalLocalRecipes =
                if (categoryNum.isEmpty()) FoodDataProvider.getDatabase().recipeDao()
                    .queryAllRecipe().toMutableList() else {
                    //获取当前分类
                    FoodDataProvider.getDatabase().recipeDao().queryRecipesByCategory(categoryNum)
                        .toMutableList()
                }
            totalLocalRecipes.sortWith(Comparator { t, t2 ->
                when (sortedType) {
                    SortedType.Popular -> {
                        if ((t.useNum ?: 0) > (t2.useNum ?: 0)) {
                            return@Comparator -1
                        } else if ((t.useNum ?: 0) == (t2.useNum ?: 0)) {
                            return@Comparator 0
                        } else {
                            return@Comparator 1
                        }
                    }

                    SortedType.Newest -> {
                        if ((t.updateTime ?: 0L) > (t2.updateTime ?: 0L)) {
                            return@Comparator 1
                        } else if ((t.updateTime ?: 0L) == (t2.updateTime
                                ?: 0L)
                        ) return@Comparator 0
                        else {
                            return@Comparator -1
                        }

                    }

                    SortedType.Score -> {
                        val score1 = t.score?.toInt() ?: 0
                        val score2 = t2.score?.toInt() ?: 0
                        if (score1 > score2) {
                            return@Comparator 1
                        } else if (score1 == score2) {
                            return@Comparator 0
                        } else {
                            return@Comparator -1
                        }
                    }

                    SortedType.A2Z -> {
                        val score1 = t.name?.compareTo(t2.name ?: "") ?: 0
                        if (score1 > 0) {
                            return@Comparator 1
                        } else if (score1 == 0) {
                            return@Comparator 0
                        } else {
                            return@Comparator -1
                        }
                    }
                }
            })
            totalLocalSize = totalLocalRecipes.size
            val localRecipeList = if (totalLocalSize < 12) {
                hasMoreLocal = false
                totalLocalRecipes
            } else {
                hasMoreLocal = true
                totalLocalRecipes.subList(0, 12)
            }
            lastLocalRecipeList.clear()
            lastLocalRecipeList.addAll(localRecipeList)
            lastLocalRecipesShowList = DataFactory.genLocalRecipes(
                currCategoryName, localRecipeList, localFavoriteRecipesList, sortedType
            )
            localRecipesLiveData.postValue(
                lastLocalRecipesShowList
            )
        }
    }

    /**
     * 获取更多本地数据，没有返回false
     */
    fun loadMoreLocalRecipes(): Boolean {
        if (hasMoreLocal) {
            lastLocalRecipeList.clear()
            scope(Dispatchers.IO) {
                startSize = endSize
                endSize = startSize + 12
                if (endSize > totalLocalSize) {
                    endSize = totalLocalSize
                    hasMoreLocal = false
                }
                val moreData = totalLocalRecipes.subList(startSize, endSize)
                lastLocalRecipeList.addAll(moreData)
                val favoriteRecipesIds = mutableListOf<String>()
                localFavoriteRecipesList.forEach {
                    favoriteRecipesIds.add(it.favoriteRecipesId)
                }
                val foodList = mutableListOf<FoodContentModel>()
                for (i in lastLocalRecipeList.indices) {
                    val recipes = lastLocalRecipeList[i]
                    foodList.add(
                        FoodContentModel(
                            recipes.photoPath ?: "",
                            recipes.name ?: "",
                            recipes.score?.toInt() ?: 0,
                            getTime(recipes.makeHours ?: 0, recipes.makeMinutes ?: 0),
                            recipes.difficultyLevel ?: "",
                            isLike = favoriteRecipesIds.contains(recipes.number),
                            foodId = recipes.number ?: "",
                            isNetRecipes = false,
                            hasDownloaded = false,
                            recipesEdition = recipes.edition,
                            useNum = recipes.useNum?.toInt() ?: 0
                        )
                    )
                }
                moreLocalRecipeLiveData.postValue(foodList)
            }
        } else {
            return false
        }
        return true
    }


    /**根据热词查询菜谱列表信息*/
    fun queryRecipesByHotWord(hotWord: String, categoryType: CategoryType) {
        val result = mutableListOf<Any>()
        result.add(FilterSortModel(""))
        startSearchSize = 0
        endSearchSize = 11
        startFoodSearchSize = 0
        endFoodSearchSize = 11
        startRecipesSearchSize = 0
        endRecipesSearchSize = 11
        totalSearchLocalRecipes.clear()
        searchLocalRecipes.clear()
        searchLocalFood.clear()
        lastSearchCategoryType = categoryType
        scope(Dispatchers.IO) {
            val recipeDao = FoodDataProvider.getDatabase().recipeDao()
            val recipesList = recipeDao.queryRecipeByName(hotWord)
            val foodList = mutableListOf<DevRecipe>()
            recipeDao.queryFoodByFoodName(hotWord).forEach {
                it.recipeNumber?.apply {
                    recipeDao.queryRecipe(this)?.let { devRecipe ->
                        foodList.add(devRecipe)
                    }
                }
            }
            recipeCount = recipesList.size
            foodCount = foodList.size
            totalSearchLocalRecipes.addAll(recipesList)
            totalSearchLocalRecipes.addAll(foodList)
            totalSearchLocalSize = totalSearchLocalRecipes.size
            searchLocalSize = recipeCount
            foodSize = foodCount
            searchLocalFood.addAll(foodList)

            searchLocalRecipes.addAll(recipesList)
            val allList: MutableList<DevRecipe> = if (totalSearchLocalSize < 12) {
                hasMoreTotalSearchLocal = false
                totalSearchLocalRecipes
            } else {
                hasMoreTotalSearchLocal = true
                totalSearchLocalRecipes.subList(0, 12)
            }
            val localRecipesList = if (recipeCount < 12) {
                hasMoreSearchLocal = false
                searchLocalRecipes
            } else {
                hasMoreSearchLocal = true
                searchLocalRecipes.subList(0, 12)
            }

            val fooShowList = if (foodSize < 12) {
                hasMoreFoodLocal = false
                foodList
            } else {
                hasMoreFoodLocal = true
                foodList.subList(0, 12)
            }

            lastTotalLocalSearchRecipeList.clear()
            lastTotalLocalSearchRecipeList.addAll(allList)
            result.add(CategoryModel(recipeCount + foodCount, recipeCount, foodCount))
            val foodContentList = mutableListOf<FoodContentModel>()
            when (categoryType) {
                CategoryType.All -> {
                    allList.forEach {
                        foodContentList.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                3,
                                getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                foodId = it.number ?: ""
                            )
                        )
                    }
                }

                CategoryType.Recipes -> {
                    localRecipesList.forEach {
                        foodContentList.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                3,
                                getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                foodId = it.number ?: ""
                            )
                        )
                    }
                }

                CategoryType.Ingredients -> {
                    fooShowList.forEach {
                        foodContentList.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                3,
                                getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                foodId = it.number ?: ""
                            )
                        )
                    }
                }
            }
            result.add(FoodListModel(foodContentList, ""))
            hotWordSearchRecipesLiveData.postValue(result)
        }
    }

    fun loadMoreForSearch(): Boolean {
        if (hasMoreTotalSearchLocal) {
            startSearchSize = endSearchSize
            endSearchSize = startSearchSize + 12
            startRecipesSearchSize = endRecipesSearchSize
            endRecipesSearchSize = startRecipesSearchSize + 12

            startFoodSearchSize = endFoodSearchSize
            endFoodSearchSize = startFoodSearchSize + 12

            if (endSearchSize > totalSearchLocalSize) {
                endSearchSize = totalSearchLocalSize
                hasMoreTotalSearchLocal = false
            }
            if (endRecipesSearchSize > searchLocalSize) {
                endRecipesSearchSize = searchLocalSize
                hasMoreSearchLocal = false
            }
            if (endFoodSearchSize > foodSize) {
                endFoodSearchSize = foodSize
                hasMoreFoodLocal = false
            }
            val newTotal = totalSearchLocalRecipes.subList(
                startSearchSize, endSearchSize
            )
            lastTotalLocalSearchRecipeList.clear()
            lastLocalSearchRecipeList.clear()
            lastLocalSearchFoodList.clear()
            lastTotalLocalSearchRecipeList.addAll(newTotal)
            if (hasMoreSearchLocal) {
                val newRecipes = searchLocalRecipes.subList(
                    startRecipesSearchSize, endRecipesSearchSize
                )
                lastLocalSearchRecipeList.addAll(newRecipes)
            }
            if (hasMoreFoodLocal) {
                val newFoods = searchLocalFood.subList(startFoodSearchSize, endFoodSearchSize)
                lastLocalSearchFoodList.addAll(newFoods)
            }
            val result = mutableListOf<Any>()
            result.add(FilterSortModel(""))
            result.add(CategoryModel(recipeCount + foodCount, recipeCount, foodCount))
            val foodContentList = mutableListOf<FoodContentModel>()
            when (lastSearchCategoryType) {
                CategoryType.All -> {
                    lastTotalLocalSearchRecipeList.forEach {
                        foodContentList.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                3,
                                getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                foodId = it.number ?: ""
                            )
                        )
                    }
                }

                CategoryType.Recipes -> {
                    lastLocalRecipeList.forEach {
                        foodContentList.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                3,
                                getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                foodId = it.number ?: ""
                            )
                        )
                    }
                }

                CategoryType.Ingredients -> {
                    lastLocalSearchFoodList.forEach {
                        foodContentList.add(
                            FoodContentModel(
                                it.photoPath ?: "",
                                it.name ?: "",
                                3,
                                getTime(it.makeHours ?: 0, it.makeMinutes ?: 0),
                                it.difficultyLevel ?: "",
                                foodId = it.number ?: ""
                            )
                        )
                    }
                }
            }
            moreSearchLocalRecipeLiveData.postValue(foodContentList)
        } else {
            return false
        }
        return true
    }

    /**获取线上的菜谱分类*/
    fun getOnLineCategoryList() {
        scopeNetLife {
            onlineCategoryLiveData.value = Get<CategoryListResult>(Api.GET_CATEGORIES) {
                addQuery("sn", getSN())
                addQuery("lang", MMkvUtils.getString(CURRENT_LANGUAGE) ?: "EN")
            }.await().categorys.toMutableList()
        }
    }

    /**获取线上的热门标签*/
    fun getOnLineHotTags() {
        scopeNetLife {
            onLineHotTagsLiveData.value = Get<HotTagsResult>(Api.GET_HOT_TAGS) {
                addQuery("sn", getSN())
                addQuery("lang", MMkvUtils.getString(CURRENT_LANGUAGE) ?: "EN")
            }.await().hotTags.toMutableList()
        }
    }

    fun getOnLineRecipeList(
        category: String,
        name: String,
        pageIndex: Int = 1,
        pageSize: Int = 10,
        isLoadMore: Boolean = false
    ) {
        if (!isLoadMore) resetOnlineConfig()
        scopeNetLife {
            val result = Get<RecipesListResult>(Api.GET_RECIPES) {
                addQuery("category", category)
                addQuery("name", name)
                addQuery("sn", getSN())
                addQuery("lang", MMkvUtils.getString(CURRENT_LANGUAGE) ?: "EN")
                addQuery("pageIndex", pageIndex)
                addQuery("pageSize", pageSize)
            }.await()
            val recipesList = result.recipes
            val pager = result.pager
            totalPageSize = pager.pageCount
            currentPage = pager.pageIndex
            scope(Dispatchers.IO) {
                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(userTag?.starCount ?: 0)
                }
                onLineRecipesLiveData.postValue(
                    DataFactory.genNetRecipesData(
                        currCategoryName, tempOnLineRecipes, favoriteRecipesList, sortedType
                    )
                )
            }
        }
    }

    /**获取线上的消息*/
    fun getNotices() {
        scopeNetLife {
            noticesLiveData.value = Get<NoticeResult>(Api.GET_NOTICES) {
                addQuery("sn", getSN())
                addQuery("lang", MMkvUtils.getString(CURRENT_LANGUAGE) ?: "EN")
            }.await().informs.toMutableList()
        }
    }


    /**刷新空数据*/
    fun postEmptyOnlineRecipes() {
        onLineRecipesLiveData.postValue(
            DataFactory.genNetRecipesData(
                currCategoryName, tempOnLineRecipes, arrayListOf(), sortedType
            )
        )
    }


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


}