package com.iscs.bozzys.ui.pages.vm

import androidx.compose.ui.graphics.Color
import androidx.lifecycle.viewModelScope
import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory
import com.iscs.bozzys.R
import com.iscs.bozzys.api.ApiRequest
import com.iscs.bozzys.api.ApiRequest.getResponse
import com.iscs.bozzys.api.ApiRequest.isCodeOk
import com.iscs.bozzys.api.Job
import com.iscs.bozzys.api.Message
import com.iscs.bozzys.api.ResponsePage
import com.iscs.bozzys.api.Task
import com.iscs.bozzys.api.User
import com.iscs.bozzys.event.RefreshEvent
import com.iscs.bozzys.event.RefreshEventBus
import com.iscs.bozzys.ui.common.VMBase
import com.iscs.bozzys.ui.theme.Text
import com.iscs.bozzys.utils.Storage
import com.iscs.bozzys.utils.Storage.saveRoleList
import com.iscs.bozzys.utils.Storage.saveUserAvatar
import com.iscs.bozzys.utils.isAdmin
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class VMHome : VMBase() {

    // 内部调用
    private val _state = MutableStateFlow(StateHome())

    // 对外暴露
    val state = _state.asStateFlow()

    // 首页
    private val TAB_HOME = NavBarItem(0, "首页", R.drawable.home)

    // 作业
    private val TAB_JOBS = NavBarItem(1, "作业", R.drawable.jobs)

    // 任务
    private val TAB_TASKS = NavBarItem(2, "任务", R.drawable.tasks)

    // 用户
    private val TAB_SETTINGS = NavBarItem(3, "设置", R.drawable.settings)

    /**
     * 页面初始化操作
     */
    fun init() {
        initEvent()
        viewModelScope.launch {
             _state.value = _state.value.copy(navs = listOf(TAB_HOME))
            delay(500)
            refreshHome(true)
        }
    }

    /**
     * 初始化事件
     */
    private fun initEvent() {
        viewModelScope.async {
            RefreshEventBus.events.collect { event ->
                when (event) {
                    is RefreshEvent.HomeData -> refreshHome()
                    is RefreshEvent.UpdateUserInfo -> _state.value = _state.value.copy(user = event.value as User)
                    // 其余不处理
                    else -> {}
                }
            }
        }
    }

    /**
     * 更新底部选择的导航
     */
    fun navigationToId(id: Int) {
        _state.value = _state.value.copy(navigationId = id)
    }

    /**
     * 进行中的任务数被点击
     */
    fun onTaskProgressClick() {
        navigationToId(2)
        getTaskList(StatePage(type = "running", page = 1, keywords = "", isRefresh = true, noMore = false))
    }

    /**
     * 已完成的任务数被点击
     */
    fun onTaskFinishClick() {
        navigationToId(2)
        getTaskList(StatePage(type = "approved", page = 1, keywords = "", isRefresh = true, noMore = false))
    }

    /**
     * 更新未读消息
     *
     * @param navId 导航id
     * @param count 未读条数
     */
    fun updateUnReadCount(navId: Int, count: Int) {
        // 更新未读消息数演示
        val navs = _state.value.navs.map { if (it.id == navId) it.copy(count = count) else it }
        _state.value = _state.value.copy(navs = ArrayList(navs))
    }

    /**
     * 刷新数据
     */
    fun onRefreshHomeTab() {
        _state.value = _state.value.copy(isHomeTabRefresh = true)
        // 下拉刷新，刷新数据
        refreshHome()
    }

    /**
     * 获取首页数据
     */
    fun getHomeTaskData(showLoading: Boolean = false, done: () -> Unit = {}) {
        viewModelScope.launch {
            loading.emit(StateLoading(show = showLoading))
            // 执行消息推送注册
            registerPush()
            // 查询权限信息
            val permissionRsp = ApiRequest.getUserPermission().getOrElse { it.getResponse() }
            if (!permissionRsp.code.isCodeOk()) {
                _state.value = _state.value.copy(isHomeTabRefresh = false)
                delay(500)
                loading.emit(StateLoading())
                delay(100)
                toast.emit("获取用户信息失败，请稍后重试")
                return@launch
            }
            // 查询顶部的任务个数
            val statisticsRsp = ApiRequest.getTaskStatistics().getOrElse { it.getResponse() }
            if (!statisticsRsp.code.isCodeOk()) {
                _state.value = _state.value.copy(isHomeTabRefresh = false)
                delay(500)
                loading.emit(StateLoading())
                delay(100)
                toast.emit(statisticsRsp.msg)
                return@launch
            }
            // 获取未读消息数量
            val msgCountRsp = ApiRequest.getMessagesUnread().getOrElse { it.getResponse() }
            if (!msgCountRsp.code.isCodeOk()) {
                _state.value = _state.value.copy(isHomeTabRefresh = false)
                delay(500)
                loading.emit(StateLoading())
                delay(100)
                toast.emit(msgCountRsp.msg)
                return@launch
            }
            // 查询进行中的作业
            val jobRsp =
                ApiRequest.getJobs(hashMapOf("pageNo" to 1, "pageSize" to 1, "status" to "running"))
                    .getOrElse { it.getResponse() }
            if (!jobRsp.code.isCodeOk()) {
                _state.value = _state.value.copy(isHomeTabRefresh = false)
                delay(500)
                loading.emit(StateLoading())
                delay(100)
                toast.emit(jobRsp.msg)
                return@launch
            }
            // 查询待审核的任务，目前只读最新3条
            val tasksRsp = ApiRequest.getTasks(
                hashMapOf(
                    "pageNo" to 1, "pageSize" to 3, "approvalStatus" to "running"
                )
            ).getOrElse { it.getResponse() }
            if (!tasksRsp.code.isCodeOk()) {
                _state.value = _state.value.copy(isHomeTabRefresh = false)
                delay(500)
                loading.emit(StateLoading())
                delay(100)
                toast.emit(statisticsRsp.msg)
                return@launch
            }
            // 获取最新三条消息
            val msgRsp = ApiRequest.getMessages(mutableMapOf("pageNo" to 1, "pageSize" to 3)).getOrElse { it.getResponse() }
            if (!msgRsp.code.isCodeOk()) {
                _state.value = _state.value.copy(isHomeTabRefresh = false)
                delay(500)
                loading.emit(StateLoading())
                delay(100)
                toast.emit(msgRsp.msg)
                return@launch
            }
            permissionRsp.data?.user?.avatar.saveUserAvatar()
            permissionRsp.data?.roleList?.saveRoleList()
            delay(500)
            loading.emit(StateLoading())
            delay(100)
            // 获取到用户信息后即刷新导航栏数据
            val navs = if (permissionRsp.data?.roles.isAdmin()) { listOf(TAB_HOME, TAB_JOBS, TAB_TASKS, TAB_SETTINGS) } else { listOf(TAB_HOME, TAB_TASKS, TAB_SETTINGS) }
            _state.value = _state.value.copy(
                navs = navs,
                homeTasks = ArrayList(tasksRsp.data?.list ?: emptyList()),
                messageList = ArrayList(msgRsp.data?.list ?: emptyList()),
                todoCountRunning = statisticsRsp.data?.inProgressCount ?: 0,
                todoCountFinish = statisticsRsp.data?.completedCount ?: 0,
                isHomeTabRefresh = false,
                roles = permissionRsp.data?.roles ?: emptyList(),
                user = permissionRsp.data?.user ?: User(),
                msgCount = msgCountRsp.data ?: 0
            )
            // 更新进行中的任务数字
            updateUnReadCount(1, jobRsp.data?.total ?: 0)
            // 更新任务数字
            updateUnReadCount(2, statisticsRsp.data?.inProgressCount ?: 0)
            // 去加载作业和任务数据
            done()
        }
    }

    /**
     * 获取作业数据，分页
     */
    fun getJobList(page: StatePage) {
        // 正在刷新禁止重复进行
        if (_state.value.jobPage.isRefresh) return
        viewModelScope.launch {
            // 下拉即刷新
            _state.value = _state.value.copy(jobPage = _state.value.jobPage.copy(isRefresh = page.isRefresh, type = page.type))
            // 执行接口数据请求
            ApiRequest.getJobs(hashMapOf("pageNo" to page.page, "pageSize" to page.pageSize, "status" to page.type, "key" to page.keywords))
                .onSuccess {
                    if (page.page == 1) _state.value.jobList.clear()
                    val newJobs = _state.value.jobList.toMutableList()
                    val jobs = it.data?.list ?: emptyList()
                    newJobs.addAll(jobs)
                    _state.value.jobList.addAll(jobs)
                    // 存储页面数据
                    delay(1000)
                    _state.value =
                        _state.value.copy(jobPage = page.copy(isRefresh = false, noMore = (it.data?.total ?: 0) == newJobs.size))
                }.onFailure {
                    delay(1000)
                    _state.value = _state.value.copy(jobPage = _state.value.jobPage.copy(isRefresh = false))
                    toast.emit(it.getResponse<ResponsePage<Job>>().msg)
                }
        }
    }

    /**
     * 获取任务列表数据，分页
     */
    fun getTaskList(page: StatePage) {
        // 正在刷新禁止重复进行
        if (_state.value.taskPage.isRefresh) return
        viewModelScope.launch {
            // 下拉即刷新
            _state.value = _state.value.copy(taskPage = _state.value.taskPage.copy(isRefresh = page.isRefresh, type = page.type))
            ApiRequest.getTasks(
                hashMapOf("pageNo" to page.page, "pageSize" to page.pageSize, "approvalStatus" to page.type, "key" to page.keywords)
            ).onSuccess {
                if (page.page == 1) _state.value.taskList.clear()
                val newTasks = _state.value.taskList.toMutableList()
                val tasks = it.data?.list ?: emptyList()
                newTasks.addAll(tasks)
                delay(1000)
                // 存储页面数据
                _state.value =
                    _state.value.copy(
                        taskPage = page.copy(isRefresh = false, noMore = (it.data?.total ?: 0) == newTasks.size),
                        taskList = newTasks
                    )
            }.onFailure {
                delay(1000)
                _state.value =
                    _state.value.copy(taskPage = _state.value.taskPage.copy(isRefresh = false))
                toast.emit(it.getResponse<ResponsePage<Task>>().msg)
            }
        }
    }

    /**
     * 消息被点击操作，主要是已读操作
     */
    fun onMessage(msg: Message) {
        // 已读不做处理
        if (msg.readStatus) return
        viewModelScope.launch {
            ApiRequest.updateMessageRead(mutableMapOf("ids" to "${msg.id}")).onSuccess {
                val newList = _state.value.messageList.map { if (it.id == msg.id) it.copy(readStatus = true) else it }.toMutableList()
                _state.value = _state.value.copy(messageList = newList)
            }
        }
    }

    /**
     * 退出登录操作
     */
    fun logout(done: () -> Unit) {
        viewModelScope.launch {
            val deviceId = PushServiceFactory.getCloudPushService().deviceId
            // 执行注销消息推送操作
            if (!deviceId.isNullOrEmpty()) {
                val rsp = ApiRequest.updateMessagePushStatus(deviceId, true).getOrElse { it.getResponse() }
                if (!rsp.code.isCodeOk()) {
                    toast.emit(rsp.msg)
                    return@launch
                }
            }
            ApiRequest.logout().onSuccess {
                // 清除本地数据
                Storage.saveLogin(false)
                done()
            }.onFailure {
                toast.emit(it.getResponse<Any>().msg)
            }
        }
    }

    /**
     * 刷新首页全部数据
     */
    private fun refreshHome(showLoading: Boolean = false) {
        viewModelScope.launch {
            getHomeTaskData(showLoading = showLoading) {
                val jobType = _state.value.jobPage.type.ifEmpty { "running" }
                val taskType = _state.value.taskPage.type.ifEmpty { "running" }
                // 刷新重置page
                _state.value = _state.value.copy(
                    jobPage = _state.value.jobPage.copy(page = 1, type = jobType),
                    taskPage = _state.value.taskPage.copy(page = 1, type = taskType)
                )
                // 获取作业列表
                getJobList(_state.value.jobPage)
                // 获取任务列表数据
                getTaskList(_state.value.taskPage)
            }
        }
    }

    /**
     * 消息推送注册
     */
    private fun registerPush() {
        viewModelScope.launch {
            val pushService = PushServiceFactory.getCloudPushService()
            val deviceId = pushService.deviceId
            if (deviceId.isNullOrEmpty()) return@launch
            // 不处理结果
            ApiRequest.updateMessagePushStatus(deviceId, false)
        }
    }

}

/**
 * @param navs              当前底部的导航列表
 * @param navigationId      当前选中的底部导航Id
 * @param isHomeTabRefresh  是否HomeTab页面刷新数据
 * @param homeTasks         首页进行中的任务
 * @param messageList       消息列表
 * @param taskList          任务列表
 * @param taskPage          任务列表分页器
 * @param jobList           作业列表
 * @param jobPage           作业列表分页器
 * @param todoCountRunning  进行中
 * @param todoCountFinish   已完成
 * @param roles             用户角色
 * @param user              当前用户
 * @param msgCount          未读消息数
 */
data class StateHome(
    val navs: List<NavBarItem> = arrayListOf(),
    val navigationId: Int = 0,
    val isHomeTabRefresh: Boolean = false,
    val homeTasks: List<Task> = listOf(),
    val messageList: List<Message> = listOf(),
    val taskPage: StatePage = StatePage(),
    val taskList: MutableList<Task> = mutableListOf(),
    val jobPage: StatePage = StatePage(),
    val jobList: MutableList<Job> = mutableListOf(),
    val todoCountRunning: Int = 0,
    val todoCountFinish: Int = 0,
    val roles: List<String> = listOf(),
    val user: User = User(),
    val msgCount: Int = 0,
)

/**
 * 底部导航栏对象
 *
 * @param id                用于标记当前
 * @param title             导航栏名称
 * @param icon              图标
 * @param count             未读消息数
 * @param selectedColor     选中的颜色
 * @param unselectedColor   未选中的颜色
 */
data class NavBarItem(
    val id: Int = 0,
    val title: String = "",
    val icon: Int = 0,
    val count: Int = 0,
    val selectedColor: Color = Color(0xFF1E90FF),
    val unselectedColor: Color = Text
)

/**
 * 页面数据
 *
 * @param page      当前页面
 * @param pageSize  页面大小
 * @param type      请求数据类型 unaudited 默认取进行中的
 * @param keywords  关键字
 * @param isRefresh 是否正在刷新
 * @param noMore    没有更多数据
 */
data class StatePage(
    val page: Int = 1,
    val pageSize: Int = 10,
    val type: String = "",
    val keywords: String = "",
    val isRefresh: Boolean = false,
    val noMore: Boolean = true,
)