<template>
  <ContentWrap>
    <!-- 搜索工作栏 -->
    <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
      <el-form-item :label="t('DataCollection.Device.deviceCode')" prop="deviceCode">
        <el-input
          v-model="queryParams.deviceCode"
          :placeholder="t('DataCollection.Device.placeholderDeviceCode')"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px" />
      </el-form-item>
      <el-form-item :label="t('DataCollection.Device.deviceName')" prop="deviceName">
        <el-input
          v-model="queryParams.deviceName"
          :placeholder="t('DataCollection.Device.placeholderDeviceName')"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px" />
      </el-form-item>

      <!-- <el-form-item label="连接状态" prop="status">
        <el-select
          v-model="queryParams.status"
          placeholder="请选择状态"
          clearable
          class="!w-240px"
        >
          <el-option
            v-for="dict in getStrDictOptions(DICT_TYPE.IOT_GATEWAY_STATUS)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item> -->

      <!-- <el-form-item label="创建时间" prop="createTime">
        <el-date-picker
          v-model="queryParams.createTime"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="daterange"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
          class="!w-240px"
        />
      </el-form-item> -->
      <el-form-item>
        <el-button @click="handleQuery">
          <Icon icon="ep:search" class="mr-5px" /> {{ t('DataCollection.Device.search') }}
        </el-button>
        <el-button @click="resetQuery">
          <Icon icon="ep:refresh" class="mr-5px" /> {{ t('DataCollection.Device.reset') }}
        </el-button>
        <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['iot:device:create']">
          <Icon icon="ep:plus" class="mr-5px" /> {{ t('DataCollection.Device.create') }}
        </el-button>
        <el-button
          type="success" plain @click="handleExport" :loading="exportLoading"
          v-hasPermi="['iot:device:export']">
          <Icon icon="ep:download" class="mr-5px" /> {{ t('DataCollection.Device.export') }}
        </el-button>
        <el-button type="danger" plain @click="handleBatchDelete" v-hasPermi="['iot:device:delete']">
          <Icon icon="ep:delete" class="mr-5px" /> {{ t('DataCollection.Device.batchDelete') }}
        </el-button>
      </el-form-item>
    </el-form>
  </ContentWrap>

  <!-- 列表 -->
  <ContentWrap>
    <el-table
      ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id"
      @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" reserve-selection />
      <el-table-column :label="t('DataCollection.Device.deviceCode')" align="left" prop="deviceCode" />
      <el-table-column :label="t('DataCollection.Device.deviceName')" align="left" prop="deviceName" />
      <el-table-column :label="t('DataCollection.Device.operatingStatus')" align="center" prop="operatingStatus" width="120px">
        <template #default="scope">
          <el-tag
            size="small"
            :type="getOperatingStatusType(scope.row.operatingStatus)"
          >
            {{ getOperatingStatusLabel(scope.row.operatingStatus) }}
          </el-tag>
        </template>
      </el-table-column>
      <!-- <el-table-column label="设备类型" align="left" prop="deviceType" width="150px"> -->
      <!-- <template #default="scope">
          <dict-tag :type="DICT_TYPE.IOT_DEVICE_TYPE" :value="scope.row.deviceType" />
        </template>
      </el-table-column> -->
      <el-table-column :label="t('DataCollection.Device.protocol')" align="left" prop="protocol" width="120px">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.IOT_PROTOCOL" :value="scope.row.protocol" />
        </template>
      </el-table-column>
      <el-table-column :label="t('DataCollection.Device.status')" align="center" prop="status" width="120px">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.IOT_GATEWAY_STATUS" :value="scope.row.status" />
        </template>
      </el-table-column>
      <el-table-column :label="t('DataCollection.Device.sampleCycle')" align="center" prop="sampleCycle" width="120px" />

      <!-- <el-table-column label="读主题" align="center" prop="readTopic" />
      <el-table-column label="写主题" align="center" prop="writeTopic" />
      <el-table-column label="网关id" align="center" prop="gatewayId" /> -->
      <!--      <el-table-column label="设备品牌id" align="center" prop="deviceBrandId" />-->
      <!-- <el-table-column label="离线间隔" align="center" prop="offLineDuration" /> -->
      <!-- <el-table-column
        label="最后上线时间"
        align="center"
        prop="lastOnlineTime"
        :formatter="dateFormatter"
        width="180px"
      /> -->
      <!-- <el-table-column label="备注" align="center" prop="remark" /> -->
      <!-- <el-table-column
        label="创建时间"
        align="center"
        prop="createTime"
        :formatter="dateFormatter"
        width="170px"
      /> -->
      <el-table-column :label="t('DataCollection.Device.isEnable')" align="center" prop="isEnable" width="120px">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.isEnable" />
        </template>
      </el-table-column>
      <el-table-column
        :label="t('DataCollection.Device.collectionTime')"
        align="center"
        prop="collectionTime"
        width="180px"
        :formatter="dateFormatter"
      />
      <el-table-column :label="t('DataCollection.Device.operate')" align="center" fixed="right" width="380px">
        <template #default="scope">
          <el-button link type="primary" @click.stop="handleShowAttribute(scope.row)">{{ t('DataCollection.Device.attributeModuleName') }}</el-button>
          <el-button
            link
            type="primary"
            @click="openForm('setting', scope.row.id)"
            v-hasPermi="['iot:device:update']"
          >
            {{ t('DataCollection.Device.settingDialogTitle') }}
          </el-button>
          <el-button
            link
            type="primary"
            @click="handleCopy(scope.row.id)"
            v-hasPermi="['iot:device:create']"
          >
            {{ t('action.copy') }}
          </el-button>
          <el-button
            link
            type="primary"
            @click.stop="handleEdit(scope.row)"
            v-hasPermi="['iot:device:update']"
          >
            {{ t('action.edit') }}
          </el-button>
          <el-button
            link :type="isRowConnected(scope.row) ? 'warning' : 'success'"
            :loading="!!connectLoadingMap[scope.row.id]" @click.stop="handleToggleConnect(scope.row)">
            {{ isRowConnected(scope.row) ? t('DataCollection.Device.disconnect') : t('DataCollection.Device.connect') }}
          </el-button>
          <el-button
            link
            type="danger"
            @click="handleDelete(scope.row.id)"
            v-hasPermi="['iot:device:delete']"
          >
            {{ t('action.delete') }}
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
      @pagination="getList" />
  </ContentWrap>

  <!-- 表单弹窗：添加/修改 -->
  <DeviceForm ref="formRef" @success="getList" />
  <!-- 子表的列表 -->
  <ContentWrap>
    <template v-if="attributeDeviceId">
      <div class="mb-10px flex items-center justify-between text-sm text-gray-500">
        <div>
          {{ t('DataCollection.Device.currentDeviceLabel') }}<span class="font-medium text-gray-700">{{ attributeDeviceName || '-' }}</span>
        </div>
        <div>
          <el-button type="primary" link @click="handleShowDeviceAlarmHistory">
            {{ t('DataCollection.Device.alarmHistoryTitle') }}
          </el-button>
        </div>
      </div>
      <el-tabs v-model="deviceTabActive">
        <el-tab-pane :label="deviceAttributeTabLabel" name="deviceAttribute">
          <DeviceAttributeList :device-id="attributeDeviceId" />
        </el-tab-pane>
        <el-tab-pane :label="deviceRuleTabLabel" name="deviceRule">
          <el-form
            class="-mb-15px"
            :model="ruleQueryParams"
            ref="ruleQueryFormRef"
            :inline="true"
            label-width="120px"
          >
            <el-form-item :label="t('DataCollection.DeviceModel.ruleIdentifier')" prop="identifier">
              <el-input
                v-model="ruleQueryParams.identifier"
                :placeholder="t('DataCollection.DeviceModel.ruleSearchIdentifierPlaceholder')"
                clearable
                @keyup.enter="handleRuleQuery"
                class="!w-200px"
              />
            </el-form-item>
            <el-form-item :label="t('DataCollection.DeviceModel.ruleFieldName')" prop="fieldName">
              <el-input
                v-model="ruleQueryParams.fieldName"
                :placeholder="t('DataCollection.DeviceModel.ruleSearchFieldNamePlaceholder')"
                clearable
                @keyup.enter="handleRuleQuery"
                class="!w-200px"
              />
            </el-form-item>
            <el-form-item :label="t('DataCollection.DeviceModel.ruleDefaultValue')" prop="defaultValue">
              <el-input
                v-model="ruleQueryParams.defaultValue"
                :placeholder="t('DataCollection.DeviceModel.ruleSearchDefaultValuePlaceholder')"
                clearable
                @keyup.enter="handleRuleQuery"
                class="!w-200px"
              />
            </el-form-item>
            <el-form-item>
              <el-button @click="handleRuleQuery">
                <Icon icon="ep:search" class="mr-5px" /> {{ t('DataCollection.DeviceModel.ruleSearch') }}
              </el-button>
              <el-button @click="resetRuleQuery">
                <Icon icon="ep:refresh" class="mr-5px" /> {{ t('DataCollection.DeviceModel.ruleReset') }}
              </el-button>
            </el-form-item>
          </el-form>

          <div class="mb-10px text-right">
            <el-button type="primary" @click="openCreateRuleForm">
              {{ t('DataCollection.DeviceModel.ruleCreateButton') }}
            </el-button>
          </div>

          <el-table
            v-loading="ruleLoading"
            :data="ruleList"
            :stripe="true"
            :show-overflow-tooltip="true"
            row-key="id"
          >
            <el-table-column :label="t('DataCollection.DeviceModel.ruleIdentifier')" align="center" prop="identifier" />
            <el-table-column :label="t('DataCollection.DeviceModel.ruleFieldName')" align="center" prop="fieldName" />
            <el-table-column :label="t('DataCollection.DeviceModel.ruleFieldRule')" align="center" prop="fieldRule" />
            <el-table-column :label="t('DataCollection.DeviceModel.ruleDefaultValue')" align="center" prop="defaultValue" />
            <el-table-column
              :label="t('DataCollection.DeviceModel.ruleCreateTime')"
              align="center"
              prop="createTime"
              :formatter="dateFormatter"
              width="180px"
            />
        <el-table-column :label="t('DataCollection.DeviceModel.ruleOperate')" align="center" width="160px">
          <template #default="scope">
            <el-button link type="primary" @click="openRuleForm(scope.row)">
              {{ t('DataCollection.DeviceModel.ruleEditRuleButton') }}
            </el-button>
            <el-button
              v-if="(scope.row.identifier || '').toString().toUpperCase() === 'ALARM'"
              link
              type="danger"
              @click="handleRuleDelete(scope.row.id)"
            >
              {{ t('DataCollection.DeviceModel.ruleDeleteRuleButton') }}
            </el-button>
          </template>
        </el-table-column>
          </el-table>
          <Pagination
            :total="ruleTotal"
            v-model:page="ruleQueryParams.pageNo"
            v-model:limit="ruleQueryParams.pageSize"
            @pagination="getRuleList"
          />

          <el-dialog v-model="ruleDialogVisible" :title="t('DataCollection.DeviceModel.ruleDialogTitle')" width="880px" draggable>
            <el-form :model="ruleForm" ref="ruleFormRef" label-width="120px">
              <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogIdentifier')">
                <el-input v-model="ruleForm.identifier" disabled />
              </el-form-item>
              <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldName')">
                <el-input v-model="ruleForm.fieldName" disabled />
              </el-form-item>
              <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogDefaultValue')">
                <el-input v-model="ruleForm.defaultValue" disabled />
              </el-form-item>
              <el-form-item
                v-if="(ruleForm.identifier || '').toString().toUpperCase() === 'ALARM'"
                :label="t('DataCollection.DeviceModel.ruleDialogAlarmLevel')"
              >
                <el-select
                  v-model="ruleForm.alarmLevel"
                  :placeholder="t('DataCollection.DeviceModel.ruleDialogAlarmLevelPlaceholder')"
                >
                  <el-option
                    v-for="dict in getStrDictOptions(DICT_TYPE.IOT_ALARM_REGISTRATION)"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                  />
                </el-select>
              </el-form-item>

              <div class="flex flex-col w-full">
                <div class="border border-gray-200 dark:border-gray-600 rounded-md py-12px">
                  <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldRule')">
                    <el-select
                      v-model="ruleForm.fieldRule"
                      :placeholder="t('DataCollection.DeviceModel.ruleDialogFieldRulePlaceholder')"
                      class="!w-240px"
                      :disabled="!currentRuleOptions.length"
                    >
                      <el-option
                        v-for="item in currentRuleOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                        :disabled="isRuleDisabled(item.value, ruleForm.fieldRule)"
                      />
                    </el-select>
                  </el-form-item>
                  <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogRule')">
                    <div class="flex items-center gap-8px">
                      <el-select
                        v-model="ruleForm.ruleAttributeId"
                        :placeholder="t('DataCollection.DeviceModel.ruleDialogRuleAttributePlaceholder')"
                        class="!w-240px"
                      >
                        <el-option
                          v-for="item in ruleAttributeOptions"
                          :key="item.id"
                          :label="item.attributeName || item.attributeCode"
                          :value="item.id"
                        />
                      </el-select>
                      <el-select
                        v-model="ruleForm.ruleOperator"
                        :placeholder="t('DataCollection.DeviceModel.ruleDialogRuleOperatorPlaceholder')"
                        class="!w-160px"
                      >
                        <el-option
                          v-for="item in ruleOperatorOptions"
                          :key="item.value"
                          :label="item.label"
                          :value="item.value"
                        />
                      </el-select>
                      <el-input
                        v-if="ruleForm.ruleOperator !== 'TRUE' && ruleForm.ruleOperator !== 'FALSE'"
                        v-model="ruleForm.ruleValue"
                        :placeholder="t('DataCollection.DeviceModel.ruleDialogRuleValuePlaceholder')"
                        class="!w-200px"
                      />
                    </div>
                  </el-form-item>
                </div>

                <div
                  v-for="(item, index) in extraPointRules"
                  :key="index"
                  class="border border-gray-200 dark:border-gray-600 rounded-md px-16px py-12px"
                >
                  <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldRule')">
                    <el-select
                      v-model="item.rule"
                      :placeholder="t('DataCollection.DeviceModel.ruleDialogFieldRulePlaceholder')"
                      class="!w-240px"
                    >
                      <el-option
                        v-for="opt in currentRuleOptions"
                        :key="opt.value"
                        :label="opt.label"
                        :value="opt.value"
                        :disabled="isRuleDisabled(opt.value, item.rule)"
                      />
                    </el-select>
                  </el-form-item>
                  <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogRule')">
                    <div class="flex items-center gap-8px">
                      <el-select
                        v-model="item.id"
                        :placeholder="t('DataCollection.DeviceModel.ruleDialogRuleAttributePlaceholder')"
                        class="!w-240px"
                      >
                        <el-option
                          v-for="attr in ruleAttributeOptions"
                          :key="attr.id"
                          :label="attr.attributeName || attr.attributeCode"
                          :value="attr.id"
                        />
                      </el-select>
                      <el-select
                        v-model="item.operator"
                        :placeholder="t('DataCollection.DeviceModel.ruleDialogRuleOperatorPlaceholder')"
                        class="!w-160px"
                      >
                        <el-option
                          v-for="opt in ruleOperatorOptions"
                          :key="opt.value"
                          :label="opt.label"
                          :value="opt.value"
                        />
                      </el-select>
                      <el-input
                        v-if="item.operator !== 'TRUE' && item.operator !== 'FALSE'"
                        v-model="item.operatorRule"
                        :placeholder="t('DataCollection.DeviceModel.ruleDialogRuleValuePlaceholder')"
                        class="!w-200px"
                      />
                      <el-button type="danger" link @click="handleRemovePointRule(index)">
                        {{ t('DataCollection.DeviceModel.ruleDeleteRuleButton') }}
                      </el-button>
                    </div>
                  </el-form-item>
                </div>

                <el-form-item v-if="isRunningIdentifier" label=" ">
                  <el-button type="primary" link @click="handleAddPointRule">
                    + {{ t('DataCollection.DeviceModel.ruleCreateButton') }}
                  </el-button>
                </el-form-item>
              </div>
            </el-form>
            <template #footer>
              <span class="dialog-footer">
                <el-button @click="ruleDialogVisible = false">{{ t('DataCollection.DeviceModel.dialogCancel') }}</el-button>
                <el-button type="primary" :loading="ruleFormLoading" @click="handleRuleSubmit">{{ t('DataCollection.DeviceModel.dialogOk') }}</el-button>
              </span>
            </template>
          </el-dialog>

          <el-dialog v-model="createRuleDialogVisible" :title="t('DataCollection.DeviceModel.ruleCreateButton')" width="520px" draggable>
            <el-form :model="createRuleForm" ref="createRuleFormRef" label-width="120px">
              <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogIdentifier')">
                <el-input v-model="createRuleForm.identifier" disabled />
              </el-form-item>
              <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldName')">
                <el-input
                  v-model="createRuleForm.fieldName"
                  :placeholder="t('DataCollection.DeviceModel.ruleSearchFieldNamePlaceholder')"
                />
              </el-form-item>
              <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogDefaultValue')">
                <el-input v-model="createRuleForm.defaultValue" disabled />
              </el-form-item>
              <el-form-item :label="t('DataCollection.DeviceModel.ruleDialogAlarmLevel')">
                <el-select
                  v-model="createRuleForm.alarmLevel"
                  :placeholder="t('DataCollection.DeviceModel.ruleDialogAlarmLevelPlaceholder')"
                >
                  <el-option
                    v-for="dict in getStrDictOptions(DICT_TYPE.IOT_ALARM_REGISTRATION)"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                  />
                </el-select>
              </el-form-item>
            </el-form>
            <template #footer>
              <span class="dialog-footer">
                <el-button @click="createRuleDialogVisible = false">{{ t('DataCollection.DeviceModel.dialogCancel') }}</el-button>
                <el-button type="primary" :loading="createRuleFormLoading" @click="handleCreateRuleSubmit">
                  {{ t('DataCollection.DeviceModel.dialogOk') }}
                </el-button>
              </span>
            </template>
          </el-dialog>
        </el-tab-pane>
      </el-tabs>
    </template>
    <el-empty v-else :description="t('DataCollection.Device.emptyDescription')" />
  </ContentWrap>

  <Dialog :title="t('DataCollection.Device.alarmHistoryTitle')" v-model="deviceAlarmDialogVisible" width="1200px">
    <el-form
      class="-mb-15px"
      :model="deviceAlarmQueryParams"
      ref="deviceAlarmQueryFormRef"
      :inline="true"
      label-width="80px"
    >
      <el-form-item :label="t('DataCollection.Device.alarmRuleName')" prop="ruleId">
        <el-select
          v-model="deviceAlarmQueryParams.ruleId"
          :loading="deviceAlarmRuleLoading"
          clearable
          filterable
          class="!w-220px"
          :placeholder="t('DataCollection.DeviceModel.ruleSearchFieldNamePlaceholder')"
        >
          <el-option
            v-for="item in deviceAlarmRuleOptions"
            :key="item.id"
            :label="item.fieldName || item.ruleName || item.name"
            :value="item.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item :label="t('DataCollection.Device.alarmPointName')" prop="modelId">
        <el-select
          v-model="deviceAlarmQueryParams.modelId"
          :loading="deviceAlarmPointLoading"
          clearable
          filterable
          class="!w-220px"
          :placeholder="t('DataCollection.Device.placeholderAttributeName')"
        >
          <el-option
            v-for="item in deviceAlarmPointOptions"
            :key="item.id"
            :label="item.attributeName || item.attributeCode || item.name"
            :value="item.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item :label="t('DataCollection.Device.alarmTime')" prop="createTime">
        <el-date-picker
          v-model="deviceAlarmQueryParams.createTime"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="daterange"
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
          :start-placeholder="t('DataCollection.HistoryData.dialogCollectionTimeStartPlaceholder')"
          :end-placeholder="t('DataCollection.HistoryData.dialogCollectionTimeEndPlaceholder')"
          class="!w-260px"
        />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleDeviceAlarmQuery">
          <Icon icon="ep:search" class="mr-5px" />
          {{ t('DataCollection.Device.search') }}
        </el-button>
        <el-button @click="resetDeviceAlarmQuery">
          <Icon icon="ep:refresh" class="mr-5px" />
          {{ t('DataCollection.Device.reset') }}
        </el-button>
      </el-form-item>
    </el-form>

    <el-table
      :data="deviceAlarmList"
      v-loading="deviceAlarmLoading"
      :stripe="true"
      :show-overflow-tooltip="true"
      :max-height="700"
      class="mt-10px"
    >
      <el-table-column :label="t('DataCollection.Device.alarmRuleName')" align="center" prop="ruleName" />
      <el-table-column :label="t('DataCollection.Device.alarmPointName')" align="center" prop="modelName" />
      <el-table-column :label="t('DataCollection.Device.alarmPointValue')" align="center" prop="addressValue" />
      <el-table-column :label="t('DataCollection.Device.alarmLevel')" align="center" prop="alarmLevel">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.IOT_ALARM_REGISTRATION" :value="scope.row.alarmLevel" />
        </template>
      </el-table-column>
      <el-table-column
        :label="t('DataCollection.Device.alarmTime')"
        align="center"
        prop="createTime"
        :formatter="dateFormatter"
        width="180px"
      />
    </el-table>
    <div class="mt-10px pb-10px flex justify-end">
      <Pagination
        :total="deviceAlarmTotal"
        v-model:page="deviceAlarmQueryParams.pageNo"
        v-model:limit="deviceAlarmQueryParams.pageSize"
        @pagination="getDeviceAlarmList"
      />
    </div>
  </Dialog>
</template>

<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import request from '@/config/axios'
import { DeviceApi, DeviceConnectParams, DeviceVO } from '@/api/iot/device'
import DeviceForm from './DeviceForm.vue'
import DeviceAttributeList from './components/DeviceAttributeList.vue'


/** 物联设备 列表 */
defineOptions({ name: 'Device' })

const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化

const tableRef = ref()

const loading = ref(true) // 列表的加载中
const list = ref<DeviceVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  deviceCode: undefined,
  deviceName: undefined,
  deviceType: undefined,
  status: undefined,
  readTopic: undefined,
  writeTopic: undefined,
  gatewayId: undefined,
  deviceBrandId: undefined,
  offLineDuration: undefined,
  lastOnlineTime: [],
  remark: undefined,
  isEnable: undefined,
  createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中

const getOperatingStatusLabel = (value: string | number | undefined) => {
  const text = String(value ?? '').trim()
  if (!text) return '离线'
  return text
}

const getOperatingStatusType = (value: string | number | undefined) => {
  const text = String(value ?? '').trim()
  if (!text) return 'info'
  if (text === '运行') return 'success'
  if (text === '待机中') return 'info'
  if (text === '故障中') return 'danger'
  if (text === '报警中') return 'warning'
  return 'info'
}

const selectedIds = ref<number[]>([])
const handleSelectionChange = (rows: any[]) => {
  selectedIds.value = rows?.map((row) => row.id).filter((id) => id !== undefined) ?? []
}

/** 查询列表 */
const getList = async (showLoading = true) => {
  if (showLoading) {
    loading.value = true
  }
  try {
    const data = await DeviceApi.getDevicePage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    if (showLoading) {
      loading.value = false
    }
  }
}

/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNo = 1
  getList()
}

/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  handleQuery()
}

/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
  formRef.value.open(type, id)
}

/** 删除按钮操作 */
const buildIdsParam = (ids: number | number[]) => {
  return Array.isArray(ids) ? ids.join(',') : String(ids)
}

const handleDelete = async (ids: number | number[]) => {
  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    const idsParam = buildIdsParam(ids)
    await DeviceApi.deleteDevice(idsParam)
    message.success(t('common.delSuccess'))
    selectedIds.value = []
    tableRef.value?.clearSelection?.()
    if (attributeDeviceId.value && idsParam.split(',').includes(String(attributeDeviceId.value))) {
      attributeDeviceId.value = undefined
      attributeDeviceName.value = ''
    }
    // 刷新列表
    await getList()
  } catch { }
}

const handleBatchDelete = async () => {
  if (!selectedIds.value.length) {
    message.error(t('common.delNoData'))
    return
  }
  await handleDelete(selectedIds.value)
}

const handleCopy = async (id: number) => {
  // 二次确认
  await message.confirm('是否复制设备?')
  try {
    await DeviceApi.copyDevice(id)
    message.success(t('common.copySuccess'))
    await getList()
  } catch { }
}

/** 导出按钮操作 */
const handleExport = async () => {
  try {
    // 导出的二次确认
    await message.exportConfirm()
    // 发起导出
    exportLoading.value = true
    const params: any = {
      ...queryParams,
      ids: selectedIds.value.length ? selectedIds.value.join(',') : undefined
    }
    const data = await DeviceApi.exportDevice(params)
    download.excel(data, t('DataCollection.Device.exportFilename'))
  } catch {
  } finally {
    exportLoading.value = false
  }
}

interface DevicePointRuleVO {
  id: number
  identifier: string
  fieldName: string
  fieldRule: string
  defaultValue: string
  deviceId: number
  createTime?: string | number | Date
  ruleAttributeId?: number
  ruleOperator?: string
  ruleValue?: string | number
}

const attributeDeviceId = ref<number | undefined>(undefined)
const attributeDeviceName = ref('')

const deviceTabActive = ref('deviceAttribute')

const deviceAttributeTabLabel = computed(() => {
  return t('DataCollection.Device.deviceAttributeTabLabel')
})

const deviceRuleTabLabel = computed(() => {
  return t('DataCollection.Device.deviceRuleTabLabel')
})

const handleShowAttribute = (row: any) => {
  attributeDeviceId.value = row?.id
  attributeDeviceName.value = row?.deviceName ?? ''
}

const ruleLoading = ref(false)
const ruleList = ref<DevicePointRuleVO[]>([])
const ruleTotal = ref(0)
const ruleQueryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  identifier: undefined as string | undefined,
  fieldName: undefined as string | undefined,
  fieldRule: undefined as string | undefined,
  defaultValue: undefined as string | undefined,
  alarmLevel: undefined as string | undefined,
  deviceId: undefined as number | undefined,
})
const ruleQueryFormRef = ref()

const ruleAttributeOptions = ref<any[]>([])

const getRuleList = async () => {
  if (!attributeDeviceId.value) return
  ruleLoading.value = true
  try {
    const params = {
      ...ruleQueryParams,
      deviceId: attributeDeviceId.value,
    }
    const data = await request.get({ url: '/iot/device-point-rules/page', params })
    const listData = Array.isArray((data as any)?.list) ? (data as any).list : (Array.isArray(data) ? data : [])
    const totalData = (data as any)?.total ?? listData.length
    ruleList.value = listData as DevicePointRuleVO[]
    ruleTotal.value = totalData
  } finally {
    ruleLoading.value = false
  }
}

const handleRuleQuery = () => {
  if (!attributeDeviceId.value) return
  ruleQueryParams.pageNo = 1
  getRuleList()
}

const resetRuleQuery = () => {
  if (!attributeDeviceId.value) return
  ruleQueryFormRef.value?.resetFields?.()
  handleRuleQuery()
}

const loadRuleAttributeOptions = async (deviceId: number) => {
  try {
    const res = await request.get({ url: '/iot/device-contact-model/list', params: { id: deviceId } })
    const data = Array.isArray(res) ? res : (res as any)?.list ?? []
    ruleAttributeOptions.value = data as any[]
  } catch {
    ruleAttributeOptions.value = []
  }
}

watch(
  () => attributeDeviceId.value,
  async (val) => {
    ruleQueryParams.deviceId = val ?? undefined
    if (!val) {
      ruleList.value = []
      ruleTotal.value = 0
      ruleAttributeOptions.value = []
      return
    }
    ruleQueryParams.pageNo = 1
    await getRuleList()
  }
)

const ruleDialogVisible = ref(false)
const ruleFormLoading = ref(false)
const ruleFormRef = ref()
const ruleForm = reactive<Partial<DevicePointRuleVO>>({
  id: undefined,
  identifier: '',
  fieldName: '',
  fieldRule: '',
  defaultValue: '',
  deviceId: undefined,
  ruleAttributeId: undefined,
  ruleOperator: undefined,
  ruleValue: undefined,
   alarmLevel: '',
})

const extraPointRules = ref<
  Array<{
    id?: number
    rule?: string
    operator?: string
    operatorRule?: string | number
  }>
>([])

const runningRuleOptions = [
  { value: '1', label: '运行' },
  { value: '2', label: '待机中（不运行、没故障）' },
  { value: '3', label: '故障中（故障且待机）' },
  // { value: '4', label: '报警中（故障且运行）' },
]

const alarmRuleOptions = [{ value: '5', label: '报警' }]

const currentRuleOptions = computed(() => {
  const id = (ruleForm.identifier || '').toString().toUpperCase()
  if (id === 'RUNNING') return runningRuleOptions
  if (id === 'ALARM') return alarmRuleOptions
  return []
})

const isRuleDisabled = (value: string, selfRule?: string | number) => {
  if (!value) return false
  const v = String(value)
  const self = selfRule != null ? String(selfRule) : undefined
  if (self === v) return false
  if (ruleForm.fieldRule && String(ruleForm.fieldRule) === v && self !== v) return true
  if (
    extraPointRules.value.some(
      (item) => item.rule != null && String(item.rule) === v && String(item.rule) !== self
    )
  ) {
    return true
  }
  return false
}

const ruleOperatorOptions = computed(() => getStrDictOptions('czsb_rules_conditions'))

const isRunningIdentifier = computed(() => {
  return (ruleForm.identifier || '').toString().toUpperCase() === 'RUNNING'
})

const openRuleForm = async (row: DevicePointRuleVO & { pointRulesVOList?: any[] }) => {
  const deviceId = row.deviceId || attributeDeviceId.value
  if (!deviceId) {
    message.error(t('DataCollection.Device.messageDeviceInfoMissingForRules'))
    return
  }

  await loadRuleAttributeOptions(deviceId)

  ruleForm.id = row.id
  ruleForm.identifier = row.identifier
  ruleForm.fieldName = row.fieldName
  ruleForm.defaultValue = row.defaultValue
  ruleForm.deviceId = row.deviceId
  ruleForm.alarmLevel = (row as any).alarmLevel

  extraPointRules.value = []

  const list = Array.isArray(row.pointRulesVOList) ? row.pointRulesVOList : []

  if (list.length) {
    const first = list[0] as any
    const firstRule = first.rule ?? row.fieldRule
    const firstAttrId = (() => {
      if (first && first.code != null) {
        const target = ruleAttributeOptions.value.find(
          (item) => item.attributeCode === first.code
        )
        return target?.id
      }
      if (first && first.id != null) return first.id
      return undefined
    })()
    ruleForm.fieldRule = firstRule as any
    ruleForm.ruleAttributeId = firstAttrId as any
    ruleForm.ruleOperator = first.operator as any
    ruleForm.ruleValue = first.operatorRule as any
    extraPointRules.value = list.slice(1).map((item: any) => ({
      id: (() => {
        if (item && item.code != null) {
          const target = ruleAttributeOptions.value.find(
            (opt) => opt.attributeCode === item.code
          )
          return target?.id
        }
        if (item && item.id != null) return item.id
        return undefined
      })(),
      rule: item.rule,
      operator: item.operator,
      operatorRule: item.operatorRule,
    }))
  } else {
    ruleForm.fieldRule = row.fieldRule
    ruleForm.ruleAttributeId = row.ruleAttributeId
    ruleForm.ruleOperator = row.ruleOperator
    ruleForm.ruleValue = row.ruleValue as any
  }

  const options = currentRuleOptions.value
  if (options.length && !options.some((item) => item.value === ruleForm.fieldRule)) {
    ruleForm.fieldRule = options[0].value
  }
  ruleDialogVisible.value = true
}

const handleRuleSubmit = async () => {
  if (!ruleForm.id) return
  try {
    ruleFormLoading.value = true
    const pointRulesVOList: any[] = []

    if (ruleForm.ruleAttributeId && ruleForm.ruleOperator) {
      const attr = ruleAttributeOptions.value.find(
        (item) => item.id === ruleForm.ruleAttributeId
      )
      if (attr && attr.attributeCode) {
        pointRulesVOList.push({
          code: attr.attributeCode,
          rule: ruleForm.fieldRule,
          operator: ruleForm.ruleOperator,
          operatorRule: ruleForm.ruleValue,
        })
      }
    }

    extraPointRules.value.forEach((item) => {
      if (!item.id || !item.operator) return
      const attr = ruleAttributeOptions.value.find((opt) => opt.id === item.id)
      if (!attr || !attr.attributeCode) return
      pointRulesVOList.push({
        code: attr.attributeCode,
        rule: item.rule ?? ruleForm.fieldRule,
        operator: item.operator,
        operatorRule: item.operatorRule,
      })
    })

    const payload = {
      id: ruleForm.id,
      identifier: ruleForm.identifier,
      fieldName: ruleForm.fieldName,
      fieldRule: ruleForm.fieldRule,
      defaultValue: ruleForm.defaultValue,
      deviceId: ruleForm.deviceId ?? attributeDeviceId.value,
      alarmLevel: ruleForm.alarmLevel,
      pointRulesVOList,
    }

    await request.put({ url: '/iot/device-point-rules/update', data: payload })
    message.success(t('common.updateSuccess'))
    ruleDialogVisible.value = false
    await getRuleList()
  } finally {
    ruleFormLoading.value = false
  }
}

const handleRuleDelete = async (id: number) => {
  if (!id) return
  try {
    await message.delConfirm()
    await request.delete({ url: '/iot/device-point-rules/delete?id=' + id })
    message.success(t('common.delSuccess'))
    await getRuleList()
  } catch { }
}

const handleAddPointRule = () => {
  if (!isRunningIdentifier.value) return
  const allOptions = currentRuleOptions.value || []
  const used = new Set<string>()
  if (ruleForm.fieldRule) used.add(String(ruleForm.fieldRule))
  extraPointRules.value.forEach((item) => {
    if (item.rule != null) used.add(String(item.rule))
  })
  const next = allOptions.find((opt) => !used.has(String(opt.value)))
  if (!next) {
    message.warning('已没有可用的点位规则可选')
    return
  }
  extraPointRules.value.push({
    rule: next.value as any,
    id: undefined,
    operator: undefined,
    operatorRule: undefined,
  })
}

const handleRemovePointRule = (index: number) => {
  if (index < 0 || index >= extraPointRules.value.length) return
  extraPointRules.value.splice(index, 1)
}

const createRuleDialogVisible = ref(false)
const createRuleFormLoading = ref(false)
const createRuleFormRef = ref()
const createRuleForm = reactive({
  identifier: 'ALARM',
  fieldName: '',
  defaultValue: '报警',
  alarmLevel: '',
})

const openCreateRuleForm = () => {
  if (!attributeDeviceId.value) {
    message.error('请先选择设备')
    return
  }
  createRuleForm.identifier = 'ALARM'
  createRuleForm.fieldName = '报警'
  createRuleForm.defaultValue = '报警'
  createRuleForm.alarmLevel = ''
  createRuleDialogVisible.value = true
}

const handleCreateRuleSubmit = async () => {
  if (!attributeDeviceId.value) return
  if (!createRuleForm.fieldName) {
    message.warning('请输入名称')
    return
  }
  try {
    createRuleFormLoading.value = true
    const payload = {
      identifier: createRuleForm.identifier,
      fieldName: createRuleForm.fieldName,
      defaultValue: createRuleForm.defaultValue,
      alarmLevel: createRuleForm.alarmLevel,
      deviceId: attributeDeviceId.value,
    }
    await request.post({ url: '/iot/device-point-rules/create', data: payload })
    message.success('新增成功')
    createRuleDialogVisible.value = false
    await getRuleList()
  } finally {
    createRuleFormLoading.value = false
  }
}
const connectLoadingMap = reactive<Record<number, boolean>>({})

const getRowConnectValue = (row: any) => {
  return row?.isConnect ?? row?.status
}

const isRowConnected = (row: any) => {
  return String(getRowConnectValue(row)) === '1'
}

const handleEdit = async (row: DeviceVO) => {
  if (isRowConnected(row)) {
    await message.alertWarning('设备在线状态，无法编辑，请先断开连接')
    return
  }
  openForm('update', row.id)
}

const handleToggleConnect = async (row: DeviceVO) => {
  const id = row?.id
  if (!id) {
    message.error('设备信息不完整')
    return
  }

  const nextIsConnect = isRowConnected(row) ? '2' : '1'
  const actionText = nextIsConnect === '1' ? '连接' : '断开连接'

  try {
    await message.confirm(`确认${actionText}设备“${row.deviceName ?? ''}”吗？`)
    connectLoadingMap[id] = true

    const params: DeviceConnectParams = { id: String(id), isConnect: nextIsConnect }
    await DeviceApi.connectDevice(params)
    message.success(`${actionText}成功`)
    await getList()
  } catch {
  } finally {
    connectLoadingMap[id] = false
  }
}

let deviceTimer: number | undefined

const startDeviceTimer = () => {
  if (deviceTimer) return
  deviceTimer = window.setInterval(() => {
    getList(false)
  }, 5000)
}

const stopDeviceTimer = () => {
  if (!deviceTimer) return
  window.clearInterval(deviceTimer)
  deviceTimer = undefined
}

onMounted(() => {
  getList()
  startDeviceTimer()
})

onActivated(() => {
  startDeviceTimer()
})

onDeactivated(() => {
  stopDeviceTimer()
})

onBeforeUnmount(() => {
  stopDeviceTimer()
})

const deviceAlarmDialogVisible = ref(false)
const deviceAlarmLoading = ref(false)
const deviceAlarmList = ref<any[]>([])
const deviceAlarmTotal = ref(0)
const deviceAlarmQueryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  deviceId: undefined as number | undefined,
  modelId: undefined as number | undefined,
  rule: undefined as string | undefined,
  alarmLevel: undefined as string | undefined,
  addressValue: undefined as string | undefined,
  createTime: [] as string[],
  ruleId: undefined as number | undefined,
})
const deviceAlarmQueryFormRef = ref()
const deviceAlarmRuleOptions = ref<any[]>([])
const deviceAlarmPointOptions = ref<any[]>([])
const deviceAlarmRuleLoading = ref(false)
const deviceAlarmPointLoading = ref(false)

const loadDeviceAlarmRuleOptions = async () => {
  if (!attributeDeviceId.value) return
  deviceAlarmRuleLoading.value = true
  try {
    const res = await request.get({
      url: '/iot/device-point-rules/getList',
      params: { id: attributeDeviceId.value },
    })
    const data = (res as any)?.data ?? res
    const listData = Array.isArray((data as any)?.list)
      ? (data as any).list
      : Array.isArray(data)
      ? data
      : []
    deviceAlarmRuleOptions.value = listData as any[]
  } finally {
    deviceAlarmRuleLoading.value = false
  }
}

const loadDeviceAlarmPointOptions = async () => {
  if (!attributeDeviceId.value) return
  deviceAlarmPointLoading.value = true
  try {
    const res = await request.get({
      url: '/iot/device/device-attribute/list',
      params: { deviceId: attributeDeviceId.value },
    })
    const data = (res as any)?.data ?? res
    const listData = Array.isArray((data as any)?.list)
      ? (data as any).list
      : Array.isArray(data)
      ? data
      : []
    deviceAlarmPointOptions.value = listData as any[]
  } finally {
    deviceAlarmPointLoading.value = false
  }
}

const getDeviceAlarmList = async () => {
  if (!attributeDeviceId.value) return
  deviceAlarmLoading.value = true
  try {
    deviceAlarmQueryParams.deviceId = attributeDeviceId.value
    const params = {
      pageNo: deviceAlarmQueryParams.pageNo,
      pageSize: deviceAlarmQueryParams.pageSize,
      deviceId: deviceAlarmQueryParams.deviceId,
      modelId: deviceAlarmQueryParams.modelId,
      rule: deviceAlarmQueryParams.rule,
      alarmLevel: deviceAlarmQueryParams.alarmLevel,
      addressValue: deviceAlarmQueryParams.addressValue,
      createTime: deviceAlarmQueryParams.createTime,
      ruleId: deviceAlarmQueryParams.ruleId,
    }
    const data = await request.get({
      url: '/iot/device-warinning-record/page',
      params,
    })
    const listData = Array.isArray((data as any)?.list)
      ? (data as any).list
      : Array.isArray(data)
      ? data
      : []
    const totalData = (data as any)?.total ?? listData.length
    deviceAlarmList.value = listData as any[]
    deviceAlarmTotal.value = totalData
  } finally {
    deviceAlarmLoading.value = false
  }
}

const handleDeviceAlarmQuery = () => {
  if (!attributeDeviceId.value) return
  deviceAlarmQueryParams.pageNo = 1
  getDeviceAlarmList()
}

const resetDeviceAlarmQuery = () => {
  if (!attributeDeviceId.value) return
  deviceAlarmQueryFormRef.value?.resetFields?.()
  deviceAlarmQueryParams.pageNo = 1
  getDeviceAlarmList()
}

const handleShowDeviceAlarmHistory = async () => {
  if (!attributeDeviceId.value) {
    message.error(t('DataCollection.Device.messageSelectDeviceRequired'))
    return
  }
  deviceAlarmQueryParams.pageNo = 1
  deviceAlarmQueryParams.pageSize = 10
  deviceAlarmQueryParams.modelId = undefined
  deviceAlarmQueryParams.rule = undefined
  deviceAlarmQueryParams.alarmLevel = undefined
  deviceAlarmQueryParams.addressValue = undefined
  deviceAlarmQueryParams.createTime = []
  deviceAlarmQueryParams.ruleId = undefined
  deviceAlarmDialogVisible.value = true
  await Promise.all([loadDeviceAlarmRuleOptions(), loadDeviceAlarmPointOptions()])
  await getDeviceAlarmList()
}

</script>
