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

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.geometry.Offset
import androidx.lifecycle.viewModelScope
import com.iscs.bozzys.api.ApiRequest
import com.iscs.bozzys.api.ApiRequest.getResponse
import com.iscs.bozzys.api.Dict
import com.iscs.bozzys.api.FormField
import com.iscs.bozzys.api.IsolationPoint
import com.iscs.bozzys.api.TaskFormInfo
import com.iscs.bozzys.api.User
import com.iscs.bozzys.ui.common.VMBase
import com.iscs.bozzys.ui.pages.edit.step.compose.Connection
import com.iscs.bozzys.ui.pages.edit.step.compose.NodeUI
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

/**
 * 作业编辑流程
 */
class VMEditStep : VMBase() {

    private val _state = MutableStateFlow(StateEditStep())
    val state = _state.asStateFlow()

    // 当前工作id
    private var id = 0

    // 负责人列表
    private val workerUserList = ArrayList<User>()

    // 上锁/解锁人列表
    private val lockerUserList = ArrayList<User>()

    // 共锁人列表
    private val groupUserList = ArrayList<User>()

    // 业务表单列表
    private val workFormList = ArrayList<TaskFormInfo>()

    // 隔离方式列表
    private val isolationMethodList = ArrayList<Dict>()

    // 点位列表
    private val isolationList = ArrayList<IsolationPoint>()

    fun init(id: Int) {
        this.id = id
        viewModelScope.launch {
            loading.emit(StateLoading(show = true))
            // 获取负责人列表
            val workerRsp = ApiRequest.getUsersByRoleCode("jtdrawer").getOrNull()
            if ((workerRsp?.code ?: -1) == 0) {
                workerUserList.clear()
                workerUserList.addAll(workerRsp?.data ?: emptyList())
            } else {
                loading.emit(StateLoading())
                toast.emit("获取负责人异常")
                return@launch
            }
            // 获取上锁人列表
            val lockerRsp = ApiRequest.getUsersByRoleCode("jtlocker").getOrNull()
            if ((lockerRsp?.code ?: -1) == 0) {
                lockerUserList.clear()
                lockerUserList.addAll(lockerRsp?.data ?: emptyList())
            } else {
                loading.emit(StateLoading())
                toast.emit("获取上锁人异常")
                return@launch
            }
            // 获取共锁人列表
            val groupRsp = ApiRequest.getUsersByRoleCode("jtcolocker").getOrNull()
            if ((groupRsp?.code ?: -1) == 0) {
                groupUserList.clear()
                groupUserList.addAll(groupRsp?.data ?: emptyList())
            } else {
                loading.emit(StateLoading())
                toast.emit("获取共锁人异常")
                return@launch
            }
            // 获取业务表单列表
            val workFormRsp = ApiRequest.getBpmFormList(mutableMapOf("pageNo" to 1, "pageSize" to -1)).getOrNull()
            if ((workFormRsp?.code ?: -1) == 0) {
                workFormList.clear()
                workFormList.addAll(workFormRsp?.data?.list ?: emptyList())
            } else {
                loading.emit(StateLoading())
                toast.emit("获取业务表单异常")
                return@launch
            }
            // 获取隔离方式
            val isolationTypeRsp = ApiRequest.getDictData(mutableMapOf("pageNo" to 1, "pageSize" to -1, "dictType" to "isolation_method")).getOrNull()
            if ((isolationTypeRsp?.code ?: -1) == 0) {
                isolationMethodList.clear()
                isolationMethodList.addAll(isolationTypeRsp?.data?.list ?: emptyList())
            } else {
                loading.emit(StateLoading())
                toast.emit("获取隔离方式异常")
                return@launch
            }
            // 获取点位列表
            val isolationRsp = ApiRequest.getIsolationPointList(mutableMapOf("pageNo" to 1, "pageSize" to -1)).getOrNull()
            if ((isolationRsp?.code ?: -1) == 0) {
                isolationList.clear()
                isolationList.addAll(isolationRsp?.data?.list ?: emptyList())
            } else {
                loading.emit(StateLoading())
                toast.emit("获取隔离点位异常")
                return@launch
            }
            getJobInfo()
        }
    }

    /**
     * 获取作业信息
     */
    fun getJobInfo() {
        viewModelScope.launch {
            ApiRequest.getJobById(id).onSuccess {
                val enableEdit = listOf("unreleased").contains(it.data?.status)
                val nodes = it.data?.toUINodeMap() ?: mutableStateMapOf()
                val connections = it.data?.toUIConnectList() ?: emptyList()
                val nodeId = if (enableEdit) {
                    it.data?.workflowWorkNodeDOList?.getOrNull(0)?.id ?: 0
                } else {
                    // 如果不能编辑，说明是执行过程，默认选中进行中的
                    it.data?.workflowWorkNodeDOList?.find { n -> n.approvalStatus == "running" }?.id ?: 0
                }
                val node = nodes[nodeId.toString()]
                _state.value = _state.value.copy(
                    enableEdit = enableEdit,
                    nodes = nodes,
                    connections = connections,
                    node = if (node == null) _state.value.node else mutableStateOf(node)
                )
                loading.emit(StateLoading())
            }.onFailure {
                loading.emit(StateLoading())
                toast.emit(it.getResponse<Any>().msg)
            }
        }
    }

    /**
     * 更新当前选中的节点
     *
     * @param nodeUI
     */
    fun updateNode(nodeUI: NodeUI) {
        // 这里不得不在这里进行校验，隔离方式，因为这个隔离方式变化会影响表单结构变化
        val isLocker = (nodeUI.node?.isolationType ?: "") == "1"
        _state.value = _state.value.copy(
            node = mutableStateOf(nodeUI),
            nodeForms = nodeUI.node?.buildFormList(
                workerUserList,
                lockerUserList,
                groupUserList,
                workFormList,
                isolationMethodList,
                isolationList,
                _state.value.nodes.map { it.value },
                isLocker = isLocker
            ) ?: emptyList()
        )
    }

    /**
     * 是否显示表单Dialog
     */
    fun formDialogShow(show: Boolean) {
        _state.value = _state.value.copy(showFormDialog = show)
    }

    /**
     * 节点表单变化监听
     *
     * @param form  变化的表单
     */
    fun onNodeFormChanged(form: FormField) {
        // 更新表单数据到节点对象中
        val node = _state.value.node.value.node?.updateNodeInfo(_state.value.nodeForms, _state.value.nodes.map { it.value }) ?: return
        // 更新当前选中的节点和更新nodes列表中的数据
        _state.value = _state.value.copy(node = mutableStateOf(_state.value.node.value.copy(node = node)))
        _state.value.nodes[node.id.toString()] = _state.value.node.value.copy(node = node)
        // 如果是隔离方式/隔离节点选择变化
        if (listOf("isolationType", "isolationNode").contains(form.name)) {
            val value = form.value.getOrNull(0) ?: "-1"
            val nodeUI = _state.value.node.value
            // 是否上锁人
            val isLocker = if (form.name == "isolationType") value == "1" else false
            _state.value = _state.value.copy(
                nodeForms = nodeUI.node?.buildFormList(
                    workerUserList,
                    lockerUserList,
                    groupUserList,
                    workFormList,
                    isolationMethodList,
                    isolationList,
                    _state.value.nodes.map { it.value },
                    isLocker = isLocker
                ) ?: emptyList()
            )
        }
    }

    /**
     * 节点保存按钮点击
     */
    fun onNodeSave(done: () -> Unit) {
        viewModelScope.launch {
            val node = _state.value.node.value.node ?: return@launch
            val forms = _state.value.nodeForms
            val tips = node.checkCanSubmit(forms)
            if (tips.isNotEmpty()) {
                toast.emit(tips)
                return@launch
            }
            loading.emit(StateLoading(show = true))
            val params = node.buildSubmitParams(forms, workFormList)
            ApiRequest.updateJobNodeInfo(params).onSuccess {
                // 增加视觉停留效果
                delay(500)
                // 更新当前编辑的节点
                _state.value.nodes[node.id.toString()] =
                    _state.value.node.value.copy(node = node.updateNodeInfo(forms, _state.value.nodes.map { it.value }))
                // 关闭Dialog
                loading.emit(StateLoading())
                _state.value = _state.value.copy(showFormDialog = false)
                toast.emit("保存成功")
                done()
            }.onFailure {
                delay(500)
                loading.emit(StateLoading())
                toast.emit(it.getResponse<Any>().msg)
            }
        }
    }

    /**
     * 查找下一个需要编辑的节点，若没有则提示是否继续
     */
    fun onNext(done: (complete: Boolean, node: NodeUI?) -> Unit) {
        viewModelScope.launch {
            val nodes = _state.value.nodes
            // 找到下一个需要处理的节点
            var record: NodeUI? = null
            // 按照节点创建顺序进行校验
            for (nui in nodes.map { it.value }.sortedBy { it.id }) {
                val node = nui.node ?: continue
                val tips = node.checkCanSubmit(
                    node.buildFormList(
                        workerUserList,
                        lockerUserList,
                        groupUserList,
                        workFormList,
                        isolationMethodList,
                        isolationList,
                        _state.value.nodes.map { it.value },
                        isLocker = node.isolationType == "1"
                    )
                )
                if (tips.isNotEmpty()) {
                    record = nui
                    done(false, record)
                    break
                }
            }
            if (record == null) done(true, null)
        }
    }

    /**
     * 显示提示Dialog
     */
    fun showTipsDialog(title: String = "", content: String = "") {
        _state.value = _state.value.copy(showTipsDialog = true, showTipsDialogContent = content)
    }

    /**
     * 隐藏提示Dialog
     */
    fun hideTipsDialog() {
        _state.value = _state.value.copy(showTipsDialog = false)
    }
}

/**
 * 页面驱动数据
 *
 * @param nodes             节点数据
 * @param node              当前选中的节点
 * @param nodeForms         当前节点表单列表
 * @param connections       连接线
 * @param showFormDialog    是否显示表单Dialog
 */
data class StateEditStep(
    val enableEdit: Boolean = false,
    val nodes: SnapshotStateMap<String, NodeUI> = mutableStateMapOf(),
    val node: MutableState<NodeUI> = mutableStateOf(NodeUI("", Offset(0f, 0f))),
    val nodeForms: List<FormField> = listOf(),
    val connections: List<Connection> = emptyList(),
    val showFormDialog: Boolean = false,
    val showTipsDialog: Boolean = false,
    val showTipsDialogContent: String = "",
)