<template>
  <a-card
    style="width: 100%"
    :tab-list="tabListNoTitle"
    :active-tab-key="state.tasActive"
    @tabChange="onTabChange"
  >
    <template v-if="state.tasActive == 'msg'" >
      <a-alert :message="tipMessage" type="info" show-icon />
      <div class="subtitle" >注意：平台为每个设备默认最多保存20条消息，超过20条后，后续的消息会替换下发最早的消息。</div>
      <a-row justify="space-between" >
        <a-col></a-col>
        <a-col> <a-button type="primary" @click="state.visible = true">下发消息</a-button>  </a-col>
      </a-row>
    </template>
    <template v-else >
      <a-alert :message="tipMessage" type="info" show-icon style="margin-bottom: 20px;" />
      <a-row justify="space-between" >
        <a-col class="msg-title" >
          <div class="title" >同步命令下发</div>
          <div class="subtitle" >同步命令暂不支持历史记录查看。</div>
        </a-col>
        <a-col> <a-button type="primary" @click="state.visible = true">命令下发</a-button> </a-col>
      </a-row>
    </template>
    <a-table
        style="margin-top: 20px;"
        :columns="state.tasActive === 'msg' ? columns :cmdColumns"
        :dataSource="state.msgDataSource"
        :loading="state.loading"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'status'">
            <span>{{ DeviceContriller.deviceMag.get(record.status)?.name }}</span>
          </template>
          <template v-if="column.key === 'createAt'">
            {{dayjs(record.createAt).format('YYYY-MM-DD HH:mm:ss')}}
          </template>
          <template v-if="column.key === 'action'">
            <a @click="openDetailModal(record)" >详情</a>
          </template>
        </template>
    </a-table>
  </a-card>

  <modal-pro
    style="width: 700px;"
    :title="modalTitle"
    :visible="state.visible"
    @cancel="state.visible = false"
    @ok="ok"
  >
  <a-form
    v-if="state.tasActive === 'msg'"
    :labelCol="{span: 4}"
    :wrapperCol="{span: 14}"
  >
    <a-form-item
      label="消息名称"
      v-bind="validateInfos.msgLabel"
    >
      <a-input v-model:value="msgState.msgLabel" > </a-input>
    </a-form-item>
    <a-form-item
      label="Topic"
    >
      <a-input v-model:value="msgState.topic" > </a-input>
    </a-form-item>
    <a-form-item
      label="消息内容"
      v-bind="validateInfos.msgPayload"
    >
      <a-textarea v-model:value="msgState.msgPayload" > </a-textarea>
    </a-form-item>
  </a-form>
  <template v-else >
    <a-alert message="同步命令成功下发后，设备需要在20秒内向平台回复响应，否则会认为命令请求超时。" type="info" show-icon style="margin-bottom: 20px;" />
    <a-form
    :labelCol="{span: 4}"
    :wrapperCol="{span: 14}"
  >
    <a-form-item
      label="命令名称"
      v-bind="validateInfosCmd.cmdId"
    >
      <a-select v-model:value="cmdState.cmdId" >
        <a-select-option
          v-for="item in state.cmdList"
          :key="item.id"
          :value="item.id"
        >
        {{item.cmdLabel}}
        </a-select-option>
      </a-select>
    </a-form-item>
    <a-form-item
      label="设置命令参数"
      v-bind="validateInfos.validateInfosCmd"
      v-if="cmdDetail?.cmdParams"
    >
      <a-row>
        <a-col v-for="(item, index) in cmdDetail?.cmdParams" :key="index" style="margin: 10px 0px;"  >
          <a-input-group  size="large"  >
            <a-row :gutter="8" align="middle" >
              <a-col :span="8">
                <a-input placeholder="key" v-model:value="item.paramLabel"  disabled />
              </a-col>
              <a-col :span="8">
                <a-input placeholder="value" v-model:value="item.dataUnit" />
              </a-col>
            </a-row>
          </a-input-group>
        </a-col>
      </a-row>
    </a-form-item>
    <a-form-item  label="设置命令参数" >
      产品尚未配置命令，请先去 <a @click="pushProductDetail" >产品详情</a> 定义命令。
    </a-form-item>
    </a-form>
  </template>
  </modal-pro>

  <modal-pro
    title="下发消息"
    layout="vertical"
    :visible="state.detailVisible"
    @cancel="state.detailVisible = false"
  >
    <a-descriptions
      :column="1"
      :labelStyle="{width: '100px', textAlign: 'left', display: 'block'}"
      v-if="state.tasActive === 'msg'"
      >
      <a-descriptions-item :span="24" label="状态">{{ DeviceContriller.deviceMag.get(state.msgDetail!.status! )?.name }}</a-descriptions-item>
      <a-descriptions-item :span="24" label="消息 ID">{{state.msgDetail.msgId}}</a-descriptions-item>
      <a-descriptions-item :span="24" label="消息名称">{{state.msgDetail.msgLabel}}</a-descriptions-item>
      <a-descriptions-item :span="24" label="Topic">{{state.msgDetail.topic}}</a-descriptions-item>
      <a-descriptions-item :span="24" label="消息创建时间">
        {{dayjs(state.msgDetail.createAt).format('YYYY-MM-DD HH:mm:ss')}}
      </a-descriptions-item>
    </a-descriptions>
    <a-descriptions
      :column="1"
      :labelStyle="{width: '100px', textAlign: 'left', display: 'block'}"
      v-else
      >
      <a-descriptions-item :span="24" label="状态">{{ DeviceContriller.deviceMag.get(state.cmdDetail!.status! )?.name }}</a-descriptions-item>
      <a-descriptions-item :span="24" label="命令名称">{{state.cmdDetail.cmdLabel}}</a-descriptions-item>
      <a-descriptions-item :span="24" label="参数">{{state.cmdDetail.cmdPayload}}</a-descriptions-item>
      <!-- <a-descriptions-item :span="24" label="下发参数">{{state.cmdDetail.msgLabel}}</a-descriptions-item> -->
      <a-descriptions-item :span="24" label="消息创建时间">
        {{dayjs(state.cmdDetail.createAt).format('YYYY-MM-DD HH:mm:ss')}}
      </a-descriptions-item>
    </a-descriptions>
  </modal-pro>

</template>

<script lang="ts" setup >

import { DeviceContriller, ModelCmdController } from '@/controller'
import { computed, onMounted, reactive, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Form, message } from 'ant-design-vue'
import dayjs from 'dayjs'

const msg = '消息下发不依赖产品模型，平台会以异步方式（消息下发后无需等待设备侧回复响应）下发消息给设备。当前仅MQTT设备支持消息下发。'
const cmdMsg = '如果设备所属产品定义了命令功能，则您可以通过应用调用平台接口或者操作下面的“下发命令”按钮下发命令。当前MQTT设备仅支持同步命令下发，NB设备仅支持异步命令下发 。'
const modalTitle = '新增下发消息'
const tabListNoTitle = [
  {
    key: 'msg',
    tab: '消息下发'
  },
  {
    key: 'cmd',
    tab: '命令下发'
  }
]

const columns = [
  {
    title: '状态',
    dataIndex: 'status',
    key: 'status'
  },
  {
    title: '消息名称',
    dataIndex: 'msgLabel'
  },
  {
    title: '消息id',
    dataIndex: 'msgId'
  },
  {
    title: '消息内容',
    dataIndex: 'msgPayload'
  },
  {
    title: '消息创建时间',
    dataIndex: 'createAt',
    key: 'createAt'
  },
  {
    title: '操作',
    key: 'action'
  }
]

const cmdColumns = [
  {
    title: '状态',
    dataIndex: 'status',
    key: 'status'
  },
  {
    title: '消息名称',
    dataIndex: 'cmdLabel'
  },
  {
    title: '消息id',
    dataIndex: 'msgId'
  },
  {
    title: '消息内容',
    dataIndex: 'cmdPayload'
  },
  {
    title: '消息创建时间',
    dataIndex: 'createAt',
    key: 'createAt'
  },
  {
    title: '操作',
    key: 'action'
  }
]

const useForm = Form.useForm
const route = useRoute()
const router = useRouter()

const deviceId = route.query.id as string

const tipMessage = computed(() => state.tasActive === 'msg' ? msg : cmdMsg)

const cmdDetail = computed(() => state.cmdList.find(item => item.id === cmdState.cmdId))

const cmdParametersTrans = computed(() => {
  return Object.keys(cmdState.cmdParameters).map(key => {
    return { key: key, value: cmdState.cmdParameters[key] }
  })
})

const state = reactive<{
  tasActive: 'msg' | 'cmd',
  msgDataSource: (IOT.API.DEVICE.Msg | IOT.API.DEVICE.Cmd)[],
  visible: boolean,
  loading: boolean,
  detailVisible: boolean,
  msgDetail: Partial<IOT.API.DEVICE.Msg >
  cmdDetail: Partial<IOT.API.DEVICE.Cmd>
    cmdList: IOT.API.CMD.Cmd[],
    deviceDetail: IOT.API.DEVICE.Device | null
    }>({
      tasActive: 'msg',
      msgDataSource: [],
      visible: false,
      loading: false,
      detailVisible: false,
      msgDetail: {},
      cmdDetail: {},
      cmdList: [],
      deviceDetail: null
    })

const msgState = reactive({
  deviceId: deviceId,
  msgPayload: '',
  msgLabel: '',
  topic: ''
})

const cmdState = reactive<{
  cmdId: string
  deviceId: string,
  cmdLabel: string,
  cmdParameters: {key: string, value: string}[]
}>({
  cmdId: '',
  deviceId: deviceId,
  cmdLabel: '',
  cmdParameters: []
})

const { resetFields, validate, validateInfos } = useForm(msgState, reactive({
  msgPayload: [{ required: true, message: '请填写消息内容' }],
  msgLabel: [{ required: true, message: '请填写消息标题' }]
}))

const { resetFields: resetFieldsCmd, validate: validateCmd, validateInfos: validateInfosCmd } = useForm(cmdState, reactive({
  cmdId: [{ required: true, message: '请填写命令名称' }]
}))

const getModelCmdList = async () => {
  const { data } = await ModelCmdController.list({ modelId: state.deviceDetail!.modelId })
  state.cmdList = data
}

const pushProductDetail = () => {
  router.push({ path: '/product/detail', query: { id: state.deviceDetail!.modelId } })
}

const ok = () => {
  if (state.tasActive === 'msg') {
    validate().then(async () => {
      await DeviceContriller.addDeviceMsg(msgState)
      state.visible = false
      getDeviceMsgList()
    })
  } else {
    validateCmd().then(async () => {
      const _cmdParameters: Record<string, string> = {}

      cmdDetail.value?.cmdParams.forEach(item => {
        _cmdParameters[item.paramLabel] = item.dataUnit
      })

      const $params = {
        ...cmdState,
        cmdLabel: cmdDetail.value!.cmdLabel,
        cmdParameters: _cmdParameters
      }
      await DeviceContriller.addDeviceCmd($params)
      state.visible = false
      getDeviceMsgList()
    })
  }
}

const openDetailModal = (record: IOT.API.DEVICE.Msg) => {
  const key = state.tasActive === 'cmd' ? 'cmdDetail' : 'msgDetail'
  state.detailVisible = true
  state[key] = record
}

const getDeviceMsgList = async () => {
  state.loading = true
  state.msgDataSource = state.tasActive === 'msg' ? await DeviceContriller.listDeviceMsg({ deviceId }) : await DeviceContriller.listDeviceCmd({ deviceId })
  state.loading = false
}

const getDeviceById = async () => {
  state.deviceDetail = await DeviceContriller.byId(deviceId)
  getModelCmdList()
}

const onTabChange = (value: 'msg' | 'cmd') => {
  state.tasActive = value
  getDeviceMsgList()
}

onMounted(() => {
  getDeviceMsgList()
  getDeviceById()
})
</script>

<style lang="less" scoped >
@import '~@/styles/theme.less';
.subtitle {
  color: @sublabel-color;
  margin: 20px 0px;
}

.msg-title {
  .title {
    font-size: 20px;
  }
  .subtitle {
    color: @sublabel-color;
    font-size: 14px;
  }
}
</style>
