<script setup>
import {onBeforeMount, ref, computed} from "vue";
import {useStore} from "vuex";
import {get_git_ver, get_update_alter, get_update_option, handle_update} from "@/apis/update.js"
import Tips from "@/components/update/Tips.vue"
import config from "@/request/config.js"
import ProcessIcon from "@/components/update/ProcessIcon.vue";
import {ElMessageBox} from "element-plus";


// 注册store
const store = useStore()

// 注册props
const props = defineProps({
  ip: {
    type: String,
    default: ''
  },
  ver_id: {
    type: Number,
    default: 0
  }
})

// 配置状态
const updateStatus = ref({})
let showStatusTips = ref(false)

//
const handleShowStatusTips = () => {
  if (store.state.updateModule.update_status[props.ip]) {
    showStatusTips.value = true
  }
}

// 配置websocket
let ws = null
let wsGetStatusInterval = null

const createWs = () => {
  console.log(ws)
  if (!ws) {
    console.log("建立ws连接")
    ws = new WebSocket(config.baseWS + "/ws/update/")
    ws.onopen = wsOpen
    ws.onmessage = wsMessage
    ws.onerror = wsError
    ws.onclose = wsClose
  }
}

const wsOpen = () => {
  wsSend(JSON.stringify({"msg": "ping"}))
}

const wsError = () => {
  ws.close()
  console.log("重新连接")
  if (ws.readyState !== 3) {
    ws = null
    createWs()
  }
}

const wsMessage = (event) => {
  handleWsMessage(event.data)
}

const wsClose = () => {
  console.log("关闭ws")
  ws = null
}

const wsSend = (msg) => {
  console.log(ws)
  if (ws === null) {
    createWs()
  }
  console.log(ws)
  if (ws.readyState === 1) {
    ws.send(msg)
  }
}

const handleWsMessage = function (msg) {
  if (msg === "你已经连接成功") {
    return
  }
  if (JSON.parse(msg).hasOwnProperty('msg')) {
    if (JSON.parse(msg)['msg'] === "ping") {
      wsSend(JSON.stringify({"msg": "pong"}))
    }
  }
  if (JSON.parse(msg).hasOwnProperty('status')) {
    console.log(JSON.parse(msg))
    updateStatus.value = JSON.parse(msg)['status']['result']
  }
}

const wsGetStatus = function () {
  if (ws === null || ws.readyState === 3) {
    createWs()
    wsGetStatusInterval = setInterval(() => {
      wsSend(JSON.stringify({'ip': props.ip}))
    }, 1000)
  } else {
    wsGetStatusInterval = setInterval(() => {
      wsSend(JSON.stringify({'ip': props.ip}))
    }, 1000)
  }
}

const stopWsGetStatus = function () {
  setTimeout(() => {
    clearInterval(wsGetStatusInterval)
  }, 1000)

}

const handleWsOpen = () => {
  if (store.state.updateModule.update_status[props.ip] === true) {
    createWs()
    wsGetStatus()
  } else {
    createWs()
  }
}
// const handleWsClose = () => {
//   if (store.state.updateModule.update_status[props.ip] === false) {
//     ws.send(JSON.stringify({"msg": "finish"}))
//     wsClose()
//   }
// }

const handleWsClear = (ip) => {
  if (store.state.updateModule.update_status[ip] === false) {
    wsSend(JSON.stringify({"finish": ip}))
    updateStatus.value = {}
  }
}
// const clearUpdateStatus = () => {
//   if ()
//   updateStatus.value = {}
// }


// region 获取git版本
const git_ver = ref([])
const selectedVersion = ref('')

onBeforeMount(async () => {
  await get_git_ver().then(res => {
    if (Array.isArray(res)) {
      git_ver.value = [...res]
    }
  }).catch()
})
// endregion

// region 获取升级警告
const updateAlter = ref([])
onBeforeMount(
    async () => {
      await get_update_alter().then(
          res => {
            if (Array.isArray(res)) {
              updateAlter.value = [...res]
              console.log(updateAlter.value)
            }
          }
      ).catch(err => {
        console.log(err)
      })
    }
)

// region 获取升级命令的功能
const updateCmd = ref({setup: [], teardown: [], sql: [], config: [], client: []})

onBeforeMount(
    async () => {
      await get_update_option().then(res => {

        // 返回值处理逻辑
        if (Array.isArray(res)) {
          console.log(res)
          res.forEach(
              (value, index) => {
                if (value.process === "setup") {
                  updateCmd.value.setup.push(value)
                }
                if (value.process === "teardown") {
                  updateCmd.value.teardown.push(value)
                }
                if (value.process === "sql") {
                  updateCmd.value.sql.push(value)
                }
                if (value.process === "config") {
                  updateCmd.value.config.push(value)
                }
                if (value.process === "client") {
                  updateCmd.value.client.push(value)
                }
              }
          )
        }
      }).catch()
    }
)
//endregion

// region 处理版本依赖
let selectedVerId = ref('9999')

const handleChangeVersion = () => {
  git_ver.value.forEach(
      (item, index) => {
        if (item.short_release === selectedVersion.value) {
          selectedVerId.value = item.ver_id
        }
      }
  )
}
// endregion

// 切换版本事件
const changeVersion = () => {
  handleChangeVersion()
  handleUpdateAlter()
}
// endregion

// region 处理版本警告
const showAlterMsg = ref('')
const handleUpdateAlter = () => {
  updateAlter.value.forEach(
      (item, index) => {
        if (selectedVerId.value < item.ver_id && props.ver_id >= item.ver_id) {
          showAlterMsg.value = "当前版本为" + props.ver_id + "：" + item.alter
          ElMessageBox(
              {
                title: "降级提示",
                message: showAlterMsg.value,
                confirmButtonText: "知道了",
                closeOnClickModal: false,
                type: "warning",
                center: true,
                'show-close': false
              }
          ).then().catch()
        }
      }
  )
}

// region 处理按键文案
let updateBtn = ref("更新")
const handleBtnName = (ip) => {
  if (store.state.updateModule.update_status[ip] === false) {
    updateBtn.value = "更新"
  }
  if (store.state.updateModule.update_status[ip] === true) {
    updateBtn.value = "更新中"
  }
}
// endregion

// region 更新时禁用全部选项
const disableAll = ref(false)

const handleDisable = (ip) => {
  disableAll.value = store.state.updateModule.update_status[ip] === true;
}
// endregion

// region 更新状态
const changUpdateStatus = (ip) => {
  store.commit("updateModule/change_update_status", ip)
}
// endregion

// region opened事件对应的功能
// 定义方法用于在加载过程中将ip对应的状态存入全局store中
const addUpdateStatus = () => {
  if (!store.state.updateModule.update_status.hasOwnProperty(props.ip)) {
    let data = {
      "ip": props.ip,
      "status": false  // 更新中是true 更新是false
    }
    store.commit("updateModule/add_update_status", data)
  }
}

const getCurrentConfig = () => {
  if (store.state.updateModule.update_config.hasOwnProperty(props.ip)) {
    selectedVersion.value = store.state.updateModule.update_config[props.ip].version
    checkedCmd.value = store.state.updateModule.update_config[props.ip].selected
  } else {
    selectedVersion.value = ''
  }
}

const handleOpened = () => {
  getCurrentConfig()
  addUpdateStatus()
  handleBtnName(props.ip)
  handleDisable(props.ip)
  handleWsOpen()
  handleShowStatusTips()
}
// endregion

// region close时间对应功能
const handleClose = () => {
  stopWsGetStatus()
  handleWsClear(props.ip)
  // handleWsClose()
  showStatusTips.value = false
  store.state.updateModule.update_dialog_show = false
}
// endregion

// region 提交升级相关逻辑
const updateForm = ref()
const checkedCmd = ref([])

// 处理点击事件
const handleRep = (ip) => {
  console.log(store.state.updateModule.update_status[ip])
  changUpdateStatus(ip)  // 更新状态
  handleBtnName(props.ip)  // 变更按键文案
  handleDisable(props.ip)  // 启用全部状态
  handleShowStatusTips()
  console.log(store.state.updateModule.update_status[ip])
}

const handleUpdate = async () => {
  if (props.ip === "" || selectedVersion.value === "") {
    alert("请先选择影院和目标版本！")
    return
  }

  updateStatus.value = {}

  handleRep(props.ip)

  // 处理ws
  wsGetStatus()

  // 添加store全局数据
  let data = {}
  data = {
    "ip": props.ip,
    "config": {'version': selectedVersion.value, 'selected': checkedCmd.value}
  }
  store.commit("updateModule/add_update_cine", data)

  // 处理提交数据的结构
  let cmd_array = []
  checkedCmd.value.forEach((value, index) => {
    cmd_array.push(value)
  })
  let params = {
    ip: props.ip,
    version: selectedVersion.value,
    cmd: JSON.stringify(cmd_array)
  }

  await handle_update(params).then(res => {
    const res_data = JSON.parse(JSON.stringify(res))
    const res_ip = res_data["ip"]
    // 处理成功逻辑
    if (res_data["result"] === "success") {
      handleRep(res_ip)
      store.commit("updateModule/clear_update_status", res_ip)  // 清除临时状态
    }
    if (res_data["result"] === "fail") {
      alert(res_ip + ' 升级失败：' + res_data["msg"])
      handleRep(res_ip)
      store.commit("updateModule/clear_update_status", res_ip)  // 清除临时状态
    }
    stopWsGetStatus() // 停止获取ws更新状态
  }).catch(err => {
    const ip = err.config.params.ip
    handleRep(ip)
    store.commit("updateModule/clear_update_status", ip)  // 清除临时状态
    stopWsGetStatus() // 停止获取ws更新状态
    alert(ip + " 升级失败，请重试！")
  })
}

// endregion
</script>


<template>
  <el-dialog v-model="store.state.updateModule.update_dialog_show" title="更新影院" :modal="true" width="720px"
             :close-on-click-modal="false" @opened="handleOpened" @close="handleClose">
    <div><span class="update">更新单机：</span><span class="ip">{{ ip }}</span><span>目标版本：</span>

      <el-select v-model="selectedVersion" :disabled="disableAll" @change="changeVersion">
        <el-option v-for="ver in git_ver" :label="ver.short_release" :value="ver.short_release"
                   :key="ver.id"></el-option>
      </el-select>
    </div>
    <el-form ref="updateForm">
      <el-form-item>
        <el-checkbox-group v-model="checkedCmd" :disabled="disableAll">
          <el-divider content-position="left">
            <span class="cmd_label">执行脚本</span>
            <ProcessIcon v-if="showStatusTips" class="process_icon"
                         :exec-status="updateStatus.setup"/>
          </el-divider>
          <el-checkbox v-for="cmd in updateCmd.setup" v-if="true" :label="cmd.id" :key="cmd.id"
                       :checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }}
            <tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips>
          </el-checkbox>

          <el-divider content-position="left">
            <span class="cmd_label">数据库</span>
            <ProcessIcon v-if="showStatusTips" class="process_icon"
                         :exec-status="updateStatus.sql"/>
          </el-divider>
          <el-checkbox v-for="cmd in updateCmd.sql" :label="cmd.id" :key="cmd.id"
                       :checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }}
            <tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips>
          </el-checkbox>
          <el-divider content-position="left">
            <span class="cmd_label">执行升级</span>
            <ProcessIcon v-if="showStatusTips" class="process_icon"
                         :exec-status="updateStatus.teardown"/>
          </el-divider>
          <el-checkbox v-for="cmd in updateCmd.teardown" :label="cmd.id" :key="cmd.id"
                       :checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }}
            <tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips>
          </el-checkbox>
          <el-divider content-position="left">
            <span class="cmd_label">修改设置</span>
            <ProcessIcon v-if="showStatusTips" class="process_icon"
                         :exec-status="updateStatus.config"/>
          </el-divider>
          <template v-for="cmd in updateCmd.config">
            <el-checkbox v-if="selectedVerId >= cmd.ver_id" :label="cmd.id" :key="cmd.id"
                         :checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }}
              <tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips>
            </el-checkbox>
          </template>
          <el-divider content-position="left">
            <span class="cmd_label">客户端</span>
            <ProcessIcon v-if="showStatusTips" class="process_icon"
                         :exec-status="updateStatus.client"/>
          </el-divider>
          <el-checkbox v-for="cmd in updateCmd.client" :label="cmd.id" :key="cmd.id"
                       :checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }}
            <tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips>
          </el-checkbox>
        </el-checkbox-group>
      </el-form-item>
    </el-form>
    <el-button type="primary" @click="handleUpdate" :disabled="disableAll">{{ updateBtn }}</el-button>
  </el-dialog>
</template>

<style scoped>
.el-checkbox-group {
  text-align: left;
  width: 640px;
  padding-left: 25px;
}

.el-checkbox {
  margin-left: 0;
  margin-right: 25px;
  width: 180px;
  padding-left: 0;
  text-align: left;
}

.el-divider--horizontal {
  line-height: 1;
}

.update {
  padding-left: 0;
}

.ip {
  margin-right: 100px;
}

:deep(.el-divider--horizontal .el-icon) {
  margin-left: 10px;
}

</style>
