<template>
  <div class="w-1/1">
    <el-button class="w-1/1" @click="openDrawer">点击配置</el-button>

    <el-drawer v-model="drawerVisible" title="配置设备绑定" direction="ltr" size="520px">
      <el-empty v-if="!devices.length" description="当前组态项目未绑定设备" />

      <template v-else>
        <el-form ref="formRef" :model="formModel" label-position="top" size="small">
          <div
            v-for="(bindItem, index) in formModel.deviceBinds"
            :key="bindItem.id"
            class="mb-12px">
            <el-form-item
              label="选择设备"
              :prop="`deviceBinds.${index}.deviceId`"
              :rules="rules.deviceId">
              <el-select
                v-model="bindItem.deviceId"
                filterable
                clearable
                class="w-1/1"
                placeholder="请选择设备"
                :disabled="!bindItem.editing"
                @change="onDeviceChange(bindItem)">
                <el-option
                  v-for="device in devices"
                  :key="device.id"
                  :label="formatDeviceLabel(device)"
                  :value="device.id" />
              </el-select>
            </el-form-item>

            <el-form-item
              label="设备属性"
              :prop="`deviceBinds.${index}.deviceProp`"
              :rules="rules.deviceProp">
              <el-select
                v-model="bindItem.deviceProp"
                filterable
                clearable
                class="w-1/1"
                placeholder="请选择设备属性"
                :disabled="!bindItem.editing || !bindItem.deviceId">
                <el-option
                  v-for="deviceProp in getDeviceProps(bindItem.deviceId)"
                  :key="deviceProp.value"
                  :label="deviceProp.label"
                  :value="deviceProp.value" />
              </el-select>
            </el-form-item>

            <el-form-item
              label="图形属性"
              :prop="`deviceBinds.${index}.nodeProp`"
              :rules="rules.nodeProp">
              <el-select
                v-model="bindItem.nodeProp"
                filterable
                clearable
                class="w-1/1"
                placeholder="请选择图形属性"
                :disabled="!bindItem.editing">
                <el-option
                  v-for="nodeProp in nodePropOptions"
                  :key="nodeProp.value"
                  :label="nodeProp.label"
                  :value="nodeProp.value" />
              </el-select>
            </el-form-item>

            <el-button
              v-if="bindItem.editing"
              type="success"
              size="small"
              class="w-1/1"
              @click="saveBind(index)">
              绑定
            </el-button>
            <el-button v-else type="danger" size="small" class="w-1/1" @click="removeBind(index)">
              解绑
            </el-button>

            <el-divider />
          </div>
        </el-form>

        <el-button type="primary" size="small" class="w-1/1" @click="addBind">新增</el-button>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import type { WebtopoProjectLinkedDeviceVO } from '@/api/pms/maotu'
import type { IDoneJson, IDoneJsonDeviceBind } from '@/components/mt-edit/store/types'
import { ElMessage, type FormInstance, type FormItemRule } from 'element-plus'
import { computed, reactive, ref } from 'vue'

type DeviceBindRow = IDoneJsonDeviceBind & {
  editing?: boolean
}

type Props = {
  item: IDoneJson
  devices?: WebtopoProjectLinkedDeviceVO[]
}

const props = withDefaults(defineProps<Props>(), {
  devices: () => []
})

const drawerVisible = ref(false)
const formRef = ref<FormInstance>()
const formModel = reactive({
  deviceBinds: [] as DeviceBindRow[]
})

const rules: Record<string, FormItemRule | FormItemRule[]> = {
  deviceId: [{ required: true, message: '请选择设备', trigger: 'change' }],
  deviceProp: [{ required: true, message: '请选择设备属性', trigger: 'change' }],
  nodeProp: [{ required: true, message: '请选择图形属性', trigger: 'change' }]
}

const nodePropOptions = computed(() => {
  return Object.entries(props.item.props || {})
    .filter(([, prop]) => !prop.disabled)
    .map(([key, prop]) => ({
      label: prop.title,
      value: `props.${key}.val`
    }))
})

function randomId() {
  return `device-bind-${Date.now()}-${Math.random().toString(36).slice(2)}`
}

function getChineseName(value?: string) {
  return (value || '').split('~~')[0]
}

function formatDeviceLabel(device: WebtopoProjectLinkedDeviceVO) {
  return [device.deviceCode, getChineseName(device.deviceName)].filter(Boolean).join(' - ')
}

function updateItemDeviceBinds(item: IDoneJson, deviceBinds: IDoneJsonDeviceBind[]) {
  item.deviceBinds = deviceBinds
}

function syncDeviceBinds() {
  updateItemDeviceBinds(
    props.item,
    formModel.deviceBinds.map(({ editing, ...item }) => item)
  )
}

async function openDrawer() {
  formModel.deviceBinds = (props.item.deviceBinds || []).map((item) => ({
    ...item,
    editing: false
  }))
  drawerVisible.value = true
}

function addBind() {
  if (formModel.deviceBinds.some((item) => item.editing)) {
    ElMessage.error('请先完成当前绑定')
    return
  }

  formModel.deviceBinds.push({
    id: randomId(),
    deviceId: undefined,
    deviceProp: '',
    nodeProp: '',
    editing: true
  })
}

function onDeviceChange(bindItem: DeviceBindRow) {
  bindItem.deviceProp = ''
}

function getDeviceProps(deviceId?: number) {
  const device = props.devices.find((item) => item.id === deviceId)
  return (device?.pointParams || [])
    .filter((item) => item.paramCode)
    .map((item) => ({
      label: item.paramName || item.paramCode!,
      value: item.paramCode!
    }))
}

async function saveBind(index: number) {
  await formRef.value?.validateField([
    `deviceBinds.${index}.deviceId`,
    `deviceBinds.${index}.deviceProp`,
    `deviceBinds.${index}.nodeProp`
  ])

  formModel.deviceBinds[index].editing = false
  syncDeviceBinds()
  ElMessage.success('绑定成功')
}

function removeBind(index: number) {
  formModel.deviceBinds.splice(index, 1)
  syncDeviceBinds()
  ElMessage.success('解绑成功')
}
</script>
