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

import androidx.lifecycle.viewModelScope
import com.iscs.bozzys.api.ApiRequest
import com.iscs.bozzys.api.ApiRequest.getResponse
import com.iscs.bozzys.api.Attachment
import com.iscs.bozzys.api.FormField
import com.iscs.bozzys.api.Node
import com.iscs.bozzys.api.Point
import com.iscs.bozzys.api.Task
import com.iscs.bozzys.api.TaskFormInfo
import com.iscs.bozzys.api.Ticket
import com.iscs.bozzys.event.RefreshEvent
import com.iscs.bozzys.event.RefreshEventBus
import com.iscs.bozzys.ui.common.VMBase
import com.iscs.bozzys.ui.pages.compose.checkCanCommitReturnTips
import com.iscs.bozzys.ui.pages.compose.getFormListByJsonList
import com.iscs.bozzys.utils.LogUtil
import com.iscs.bozzys.utils.SystemUtil
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

/**
 * 任务详情页面vm
 */
class VMDetailTask : VMBase() {

    // 本类使用
    private val _state = MutableStateFlow(StateDetailTask())

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

    // 任务信息
    private lateinit var task: Task

    // 任务表单信息
    private lateinit var formInfo: TaskFormInfo

    // 盲板和拆除操作需要固定字段数据
    private val mbForms = listOf(
        "{\"id\":\"field_1770613077797\",\"type\":\"input\",\"label\":\"盲板设备编号\",\"name\":\"deviceNumber\",\"required\":false,\"placeholder\":\"请输入盲板设备编号\",\"options\":[]}",
        "{\"id\":\"field_1770613171131\",\"type\":\"upload\",\"label\":\"附件上传\",\"name\":\"attachments\",\"required\":false,\"placeholder\":\"\",\"options\":[],\"uploadType\":\"file\",\"maxCount\":5}"
    )

    /**
     * 获取任务表单信息
     */
    fun getTaskFormInfo(task: Task) {
        this.task = task
        viewModelScope.launch {
            loading.emit(StateLoading(show = true))
            ApiRequest.getTaskInfoByNodeId(task.nodeId).onSuccess {
                val taskInfo = it.data
                if (taskInfo == null) {
                    loading.emit(StateLoading(show = false))
                    toast.emit("任务数据异常")
                    return@launch
                }
                // 盲板操作需要显示表单
                if (listOf("0", "2").contains(taskInfo.isolationType)) {
                    val forms = mbForms.getFormListByJsonList()
                    forms.forEach { form ->
                        if (form.name == "attachments") {
                            val json = Json
                            val list = json.decodeFromString<List<Attachment>>(taskInfo.attachments ?: "[]")
                            form.value = list.map { a -> a.url }
                        } else if (form.name == "deviceNumber") {
                            form.value = listOf(taskInfo.deviceNumber ?: "")
                        }
                    }
                    _state.value = _state.value.copy(mbForms = forms)
                }
                // 兼容它端返回的异样数据格式
                if (!taskInfo.formData.isNullOrEmpty()) {
                    val json = Json { ignoreUnknownKeys = true }
                    formInfo = json.decodeFromString<TaskFormInfo>(taskInfo.formData.ifEmpty { "{}" })
                    // 有些表单不需要显示的逻辑处理
                    // 解除隔离和还锁不需要录入信息
                    if (!taskInfo.checkCanOptionByPhone()) {
                        formInfo = TaskFormInfo()
                    }
                    _state.value = _state.value.copy(
                        forms = formInfo.fields?.getFormListByJsonList() ?: emptyList(),
                        node = taskInfo
                    )
                    delay(500)
                    loading.emit(StateLoading())
                } else {
                    ApiRequest.getTaskFormInfoByFormId(it.data?.formId ?: 0).onSuccess { formInfo ->
                        this@VMDetailTask.formInfo = formInfo.data ?: TaskFormInfo()
                        _state.value =
                            _state.value.copy(
                                forms = this@VMDetailTask.formInfo.fields?.getFormListByJsonList() ?: emptyList(),
                                node = taskInfo
                            )
                        delay(500)
                        loading.emit(StateLoading())
                    }.onFailure { err ->
                        delay(500)
                        loading.emit(StateLoading())
                        toast.emit("获取表单异常：${err.getResponse<TaskFormInfo>().msg}")
                    }
                }
            }.onFailure {
                delay(500)
                loading.emit(StateLoading(show = false))
                toast.emit("获取任务详情异常：${it.getResponse<Any>().msg}")
            }
        }
    }

    /**
     * 提交按钮被点击
     */
    fun onSubmit(status: String = "approved", done: () -> Unit) {
        viewModelScope.launch {
            val forms = _state.value.forms
            val tips = forms.checkCanCommitReturnTips()
            if (tips.isNotEmpty()) {
                toast.emit(tips)
                return@launch
            }
            val params = mutableMapOf<String, Any>("nodeId" to task.nodeId, "approvalStatus" to status)
            val json = Json
            // 重点在FormData
            val fields = forms.map { json.encodeToString(it) }
            val formInfo = this@VMDetailTask.formInfo.copy(fields = fields)
            params["formData"] = json.encodeToString(formInfo)
            // 处理特殊盲板操作数据
            if (listOf("0", "2").contains(_state.value.node.isolationType)) {
                // 这里做数据转换操作
                _state.value.mbForms.forEach { form ->
                    if (form.name == "attachments") {
                        val list = arrayListOf<MutableMap<String, String>>()
                        form.value.forEach { url ->
                            val name = SystemUtil.getUrlFileName(url)
                            list += mutableMapOf("name" to name, "url" to url)
                        }
                        params["attachments"] = json.encodeToString(list)
                    } else if (form.name == "deviceNumber") {
                        params["deviceNumber"] = form.value.getOrNull(0) ?: ""
                    }
                }
            }
            loading.emit(StateLoading(show = true))
            ApiRequest.updateJobNodeApproval(params).onSuccess {
                delay(1000)
                loading.emit(StateLoading())
                toast.emit("提交成功")
                // 通知首页刷新数据
                RefreshEventBus.onRefreshData(RefreshEvent.HomeData)
                delay(500)
                done()
            }.onFailure {
                delay(1000)
                loading.emit(StateLoading())
                toast.emit("提交失败：${it.getResponse<Any>().msg}")
            }
        }
    }

    fun updateTicket(ticket: Ticket) {
        viewModelScope.launch {
            val task = ticket.data.getOrNull(0) ?: return@launch
            val locks = _state.value.locks
            var step = _state.value.step
            var pointsF = _state.value.points.first
            var pointsS = _state.value.points.second
            // 校验是上锁过程还是解锁过程
            if (_state.value.step == 1) {
                task.dataList.forEach {
                    if (it.equipRfidNo == "E452E13B") {
                        pointsF = it
                    } else if (it.equipRfidNo == "2457BC3B") {
                        pointsS = it
                    }
                }
                // 上锁钥匙返回，校验是否还需要设备，根据上锁点位是否都完成隔离判断当前流程
                val useLocks = mutableListOf<String>()
                // 查找未完成的点位
                repeat(task.dataList.filter { it.closed == 0 }.size) {
                    val canUse = locks.filter {
                        !task.dataList.filter { p -> p.closed == 1 }.map { p -> p.infoRfidNo }.contains(it)
                                && !useLocks.contains(it)
                    }
                    if (canUse.isNotEmpty()) useLocks += canUse[0]
                }
                // 所需挂锁不为空，这里需要回滚步骤
                if (useLocks.isNotEmpty()) {
                    step--
                    loading.emit(StateLoading())
                    toast.emit("点位隔离任务未完成，请继续隔离任务")
                } else {
                    step++
                    // 修改点位target状态
                    pointsF = pointsF.copy(target = 1, closed = 0)
                    pointsS = pointsS.copy(target = 1, closed = 0)
                }
                LogUtil.d("xiaoming", "当前步骤 $step")
                _state.value = _state.value.copy(step = step, useLocks = useLocks)
            } else if (step == 3) {
                task.dataList.forEach {
                    if (it.equipRfidNo == "E452E13B") {
                        pointsF = it
                    } else if (it.equipRfidNo == "2457BC3B") {
                        pointsS = it
                    }
                }
                if (task.dataList.all { it.closed == 1 }) {
                    step++
                } else {
                    loading.emit(StateLoading())
                    toast.emit("点位解除隔离未完成，请继续未解除隔离作业")
                    step--
                }
                _state.value = _state.value.copy(step = step, useLocks = mutableListOf())
            }
            _state.value = _state.value.copy(points = pointsF to pointsS)
        }
    }

    fun updateTicketStatus(step: Int = -1, status: String, delay: Long = 0) {
        viewModelScope.launch {
            delay(delay)
            if (step >= 0) _state.value = _state.value.copy(step = step)
            loading.emit(StateLoading(show = status.isNotEmpty(), content = status))
        }
    }

    // 构建作业票
    fun createTicketJson(): String {
        val sb = StringBuilder("{\"cardNo\":\"\",\"data\":[{\"codeId\":1,\"dataList\":[")
        val step = _state.value.step
        val points = _state.value.points
        val useLocks = _state.value.useLocks
        if (step == 0) {
            var spl = ""
            if (points.first.closed == 0) {
                sb.append("{\"dataId\":87,\"equipName\":\"E_57\",\"equipRfidNo\":\"E452E13B\",\"infoRfidNo\":\"\",\"target\":0}")
                spl = ","
            }
            if (points.second.closed == 0) {
                sb.append("$spl{\"dataId\":88,\"equipName\":\"E_58\",\"equipRfidNo\":\"2457BC3B\",\"infoRfidNo\":\"\",\"target\":0}")
            }
        } else if (step == 2) {
            var spl = ""
            if ((points.first.closed == 1 && points.first.target == 0) || (points.first.closed == 0 && points.first.target == 1)) {
                sb.append("{\"dataId\":87,\"equipName\":\"E_57\",\"equipRfidNo\":\"E452E13B\",\"infoRfidNo\":\"${points.first.infoRfidNo}\",\"target\":1}")
                spl = ","
            }
            if ((points.second.closed == 1 && points.second.target == 0) || (points.second.closed == 0 && points.second.target == 1)) {
                sb.append("$spl{\"dataId\":88,\"equipName\":\"E_58\",\"equipRfidNo\":\"2457BC3B\",\"infoRfidNo\":\"${points.second.infoRfidNo}\",\"target\":1}")
            }
        }
        // 所需挂锁
        sb.append("],\"taskCode\":\"165\"}],\"lockList\":[")
        // 挂锁
        var idx = 1
        useLocks.forEach {
            if (idx == 1) sb.append("{\"lockId\":$idx,\"rfid\":\"$it\"}")
            else sb.append(",{\"lockId\":$idx,\"rfid\":\"$it\"}")
            idx++
        }
        sb.append("],\"password\":\"123456\"}")
        LogUtil.d("xiaoming", "创建的作业票：$sb")
        return "$sb"
    }
}

/**
 * 页面状态类
 *
 * @param forms     自定义表单数据
 * @param mbForms   盲板表单数据
 * @param node      当前节点数据
 * @param step      0-去上锁 1-完成上锁 2-去解锁 3-完成解锁 4-任务完成
 * @param points    点位列表
 * @param keys      钥匙列表
 * @param locks     挂锁列表
 * @param useLocks  当前上锁所需要的设备
 */
data class StateDetailTask(
    val forms: List<FormField> = listOf(),
    val mbForms: List<FormField> = listOf(),
    val node: Node = Node(),
    val step: Int = 0,
    val points: Pair<Point, Point> = Point(equipRfidNo = "E452E13B") to Point(equipRfidNo = "2457BC3B"),
    val keys: MutableList<String> = mutableListOf("9C7B02F9"),
    val locks: MutableList<String> = mutableListOf("0351B1E4", "4353B1E4"),
    val useLocks: MutableList<String> = mutableListOf("0351B1E4", "4353B1E4")
)