<template>
  <div class="page-content">
    <!-- 导入操作区 -->
    <ElCard shadow="never">
      <template #header>
        <span style="font-weight: 500">批量导入设备</span>
      </template>

      <ElRow :gutter="20">
        <ElCol :xs="24" :lg="12">
          <ElAlert type="info" :closable="false" style="margin-bottom: 20px">
            <template #title>
              <div style="line-height: 1.8">
                <p><strong>导入说明：</strong></p>
                <p>1. 请先下载 CSV 模板文件，按照模板格式填写设备信息</p>
                <p>2. 支持 CSV 格式（.csv），单次最多导入 1000 条</p>
                <p>3. CSV 文件编码：UTF-8（推荐）或 GBK</p>
                <p
                  >4.
                  <strong>必填字段：virtual_no（设备虚拟号）</strong
                  >、device_name（设备名称）、device_model（设备型号）</p
                >
                <p
                  >5.
                  可选字段：device_type（设备类型）、manufacturer（制造商）、max_sim_slots（最大插槽数，默认1）</p
                >
                <p
                  >6. virtual_no
                  为空将导入失败，设备号重复将自动跳过，导入后可在任务管理中查看详情</p
                >
              </div>
            </template>
          </ElAlert>

          <ElButton type="primary" :icon="Download" @click="downloadTemplate"
            >下载导入模板</ElButton
          >
        </ElCol>

        <ElCol :xs="24" :lg="12">
          <div class="upload-area">
            <ElUpload
              ref="uploadRef"
              drag
              :auto-upload="false"
              :on-change="handleFileChange"
              :limit="1"
              accept=".csv"
            >
              <el-icon class="el-icon--upload"><upload-filled /></el-icon>
              <div class="el-upload__text">将 CSV 文件拖到此处，或<em>点击选择</em></div>
              <template #tip>
                <div class="el-upload__tip">只能上传 CSV 文件，且不超过 10MB</div>
              </template>
            </ElUpload>
            <div style="margin-top: 16px; text-align: center">
              <ElButton
                type="success"
                :loading="uploading"
                :disabled="!fileList.length"
                @click="submitUpload"
              >
                开始导入
              </ElButton>
              <ElButton @click="clearFiles">清空</ElButton>
            </div>
          </div>
        </ElCol>
      </ElRow>
    </ElCard>

    <!-- 导入记录 -->
    <ElCard shadow="never" style="margin-top: 20px">
      <template #header>
        <div style="display: flex; align-items: center; justify-content: space-between">
          <span style="font-weight: 500">导入记录</span>
          <div>
            <ElSelect
              v-model="statusFilter"
              placeholder="状态筛选"
              style="width: 120px; margin-right: 12px"
              clearable
            >
              <ElOption label="全部" :value="null" />
              <ElOption label="待处理" :value="1" />
              <ElOption label="处理中" :value="2" />
              <ElOption label="已完成" :value="3" />
              <ElOption label="失败" :value="4" />
            </ElSelect>
            <ElButton @click="refreshList">刷新</ElButton>
          </div>
        </div>
      </template>

      <ArtTable
        rowKey="id"
        ref="tableRef"
        :loading="loading"
        :data="filteredRecords"
        :marginTop="10"
        :stripe="false"
      >
        <template #default>
          <ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
        </template>
      </ArtTable>
    </ElCard>

    <!-- 导入详情对话框 -->
    <ElDialog v-model="detailDialogVisible" title="设备导入详情" width="900px" align-center>
      <ElDescriptions :column="2" border>
        <ElDescriptionsItem label="任务编号" :span="2">{{
          currentDetail.taskNo
        }}</ElDescriptionsItem>
        <ElDescriptionsItem label="状态">{{ currentDetail.statusText }}</ElDescriptionsItem>
        <ElDescriptionsItem label="批次号">{{ currentDetail.batchNo }}</ElDescriptionsItem>
        <ElDescriptionsItem label="文件名" :span="2">{{
          currentDetail.fileName
        }}</ElDescriptionsItem>
        <ElDescriptionsItem label="总数">{{ currentDetail.totalCount }}</ElDescriptionsItem>
        <ElDescriptionsItem label="成功数">
          <span style="color: var(--el-color-success)">{{ currentDetail.successCount }}</span>
        </ElDescriptionsItem>
        <ElDescriptionsItem label="跳过数">{{ currentDetail.skipCount }}</ElDescriptionsItem>
        <ElDescriptionsItem label="失败数">
          <span style="color: var(--el-color-danger)">{{ currentDetail.failCount }}</span>
        </ElDescriptionsItem>
        <ElDescriptionsItem label="警告数">
          <span style="color: var(--el-color-warning)">{{ currentDetail.warningCount }}</span>
        </ElDescriptionsItem>
        <ElDescriptionsItem label="开始时间">{{ currentDetail.startedAt }}</ElDescriptionsItem>
        <ElDescriptionsItem label="完成时间">{{ currentDetail.completedAt }}</ElDescriptionsItem>
        <ElDescriptionsItem label="创建时间">{{ currentDetail.createdAt }}</ElDescriptionsItem>
        <ElDescriptionsItem label="错误信息" :span="2">{{
          currentDetail.errorMessage
        }}</ElDescriptionsItem>
      </ElDescriptions>

      <ElDivider content-position="left">失败明细</ElDivider>
      <div
        v-if="currentDetail.failReasons && currentDetail.failReasons.length"
        style="max-height: 300px; overflow-y: auto"
      >
        <ElTable :data="currentDetail.failReasons" border size="small">
          <ElTableColumn label="行号" prop="row" width="80" />
          <ElTableColumn label="设备编号" prop="deviceCode" width="150" />
          <ElTableColumn label="ICCID" prop="iccid" width="200" />
          <ElTableColumn label="失败原因" prop="message" min-width="200" />
        </ElTable>
      </div>
      <ElEmpty v-else description="无失败记录" />

      <template #footer>
        <ElButton @click="detailDialogVisible = false">关闭</ElButton>
        <ElButton
          v-if="currentDetail.failCount > 0"
          type="primary"
          :icon="Download"
          @click="downloadFailData(currentDetail)"
        >
          下载失败数据
        </ElButton>
      </template>
    </ElDialog>
  </div>
</template>

<script setup lang="ts">
  import { h, computed, watch } from 'vue'
  import { ElMessage, ElTag, ElProgress, ElIcon, ElButton } from 'element-plus'
  import { useRouter } from 'vue-router'
  import { Download, UploadFilled, View, Loading } from '@element-plus/icons-vue'
  import type { UploadInstance } from 'element-plus'
  import { StorageService } from '@/api/modules/storage'
  import { DeviceService } from '@/api/modules'
  import { formatDateTime } from '@/utils/business/format'
  import { useCheckedColumns } from '@/composables/useCheckedColumns'
  import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'

  defineOptions({ name: 'DeviceImport' })

  const router = useRouter()

  interface FailReason {
    row: number
    deviceCode: string
    iccid: string
    message: string
  }

  interface ImportRecord {
    id: string
    taskNo: string
    status: number
    statusText: string
    batchNo: string
    fileName: string
    totalCount: number
    successCount: number
    skipCount: number
    failCount: number
    warningCount: number
    startedAt: string
    completedAt: string
    errorMessage: string
    createdAt: string
    failReasons?: FailReason[]
  }

  const uploadRef = ref<UploadInstance>()
  const tableRef = ref()
  const fileList = ref<File[]>([])
  const uploading = ref(false)
  const detailDialogVisible = ref(false)
  const statusFilter = ref<number | null>(null)
  const loading = ref(false)

  const importRecords = ref<ImportRecord[]>([])

  const currentDetail = ref<ImportRecord>({
    id: '',
    taskNo: '',
    status: 1,
    statusText: '',
    batchNo: '',
    fileName: '',
    totalCount: 0,
    successCount: 0,
    skipCount: 0,
    failCount: 0,
    warningCount: 0,
    startedAt: '',
    completedAt: '',
    errorMessage: '',
    createdAt: ''
  })

  const filteredRecords = computed(() => {
    if (statusFilter.value === null) return importRecords.value
    return importRecords.value.filter((item) => item.status === statusFilter.value)
  })

  // 动态列配置
  const { columnChecks, columns } = useCheckedColumns(() => [
    {
      prop: 'taskNo',
      label: '任务编号',
      width: 200,
      showOverflowTooltip: true
    },
    {
      prop: 'status',
      label: '状态',
      width: 120,
      formatter: (row: ImportRecord) => {
        if (row.status === 1) {
          return h(ElTag, { type: 'info' }, () => '待处理')
        } else if (row.status === 2) {
          return h(
            ElTag,
            { type: 'warning' },
            {
              default: () => [
                h(ElIcon, { class: 'is-loading' }, () => h(Loading)),
                h('span', { style: { marginLeft: '4px' } }, '处理中')
              ]
            }
          )
        } else if (row.status === 3) {
          return h(ElTag, { type: 'success' }, () => '已完成')
        } else if (row.status === 4) {
          return h(ElTag, { type: 'danger' }, () => '失败')
        } else {
          return h(ElTag, { type: 'info' }, () => row.statusText || '-')
        }
      }
    },
    {
      prop: 'batchNo',
      label: '批次号',
      width: 180,
      showOverflowTooltip: true
    },
    {
      prop: 'fileName',
      label: '文件名',
      minWidth: 200,
      showOverflowTooltip: true
    },
    {
      prop: 'totalCount',
      label: '总数',
      width: 100
    },
    {
      prop: 'successCount',
      label: '成功数',
      width: 100,
      formatter: (row: ImportRecord) => {
        return h('span', { style: { color: 'var(--el-color-success)' } }, row.successCount)
      }
    },
    {
      prop: 'skipCount',
      label: '跳过数',
      width: 100
    },
    {
      prop: 'failCount',
      label: '失败数',
      width: 100,
      formatter: (row: ImportRecord) => {
        return h('span', { style: { color: 'var(--el-color-danger)' } }, row.failCount)
      }
    },
    {
      prop: 'warningCount',
      label: '警告数',
      width: 100,
      formatter: (row: ImportRecord) => {
        return h('span', { style: { color: 'var(--el-color-warning)' } }, row.warningCount)
      }
    },
    {
      prop: 'startedAt',
      label: '开始时间',
      width: 180
    },
    {
      prop: 'completedAt',
      label: '完成时间',
      width: 180
    },
    {
      prop: 'errorMessage',
      label: '错误信息',
      minWidth: 200,
      showOverflowTooltip: true
    },
    {
      prop: 'createdAt',
      label: '创建时间',
      width: 180
    },
    {
      prop: 'operation',
      label: '操作',
      width: 180,
      fixed: 'right',
      formatter: (row: ImportRecord) => {
        const buttons = []

        // 显示"查看详情"按钮
        buttons.push(
          h(ArtButtonTable, {
            text: '详情',
            onClick: () => viewDetail(row)
          })
        ),
          buttons.push(
            h(ArtButtonTable, {
              text: '失败数据',
              type: 'danger',
              onClick: () => downloadFailData(row)
            })
          )

        return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
      }
    }
  ])

  const downloadTemplate = () => {
    // CSV模板内容 - 包含表头和示例数据
    const csvContent = [
      // 表头
      'virtual_no,device_name,device_model,device_type,manufacturer,max_sim_slots',
      // 示例数据
      'DEV001,智能水表01,WM-2000,智能水表,华为,1',
      'DEV002,GPS定位器01,GPS-3000,定位设备,小米,2',
      'DEV003,智能燃气表01,GM-1500,智能燃气表,海尔,1'
    ].join('\n')

    // 添加 BOM 头确保 Excel 正确识别 UTF-8 编码
    const BOM = '\uFEFF'
    const blob = new Blob([BOM + csvContent], { type: 'text/csv;charset=utf-8;' })

    // 创建下载链接
    const link = document.createElement('a')
    const url = URL.createObjectURL(blob)
    link.setAttribute('href', url)
    link.setAttribute('download', '设备导入模板.csv')
    link.style.visibility = 'hidden'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(url)

    ElMessage.success('设备导入模板下载成功')
  }

  const handleFileChange = (uploadFile: any) => {
    // 验证文件大小（10MB限制）
    const maxSize = 10 * 1024 * 1024
    if (uploadFile.raw && uploadFile.raw.size > maxSize) {
      ElMessage.error('文件大小不能超过 10MB')
      uploadRef.value?.clearFiles()
      fileList.value = []
      return
    }

    // 验证文件类型
    if (uploadFile.raw && !uploadFile.raw.name.endsWith('.csv')) {
      ElMessage.error('只能上传 CSV 文件')
      uploadRef.value?.clearFiles()
      fileList.value = []
      return
    }

    fileList.value = uploadFile.raw ? [uploadFile.raw] : []
  }

  const clearFiles = () => {
    uploadRef.value?.clearFiles()
    fileList.value = []
  }

  /**
   * 三步上传流程
   * 1. 调用 StorageService.getUploadUrl() 获取预签名 URL 和 file_key
   * 2. 调用 StorageService.uploadFile() 上传文件到对象存储
   * 3. 调用 DeviceService.importDevices() 触发后端导入任务
   */
  const submitUpload = async () => {
    if (!fileList.value.length) {
      ElMessage.warning('请先选择CSV文件')
      return
    }

    const file = fileList.value[0]
    uploading.value = true

    try {
      // 第一步：获取预签名上传 URL
      ElMessage.info('正在准备上传...')
      const uploadUrlRes = await StorageService.getUploadUrl({
        file_name: file.name,
        content_type: 'text/csv',
        purpose: 'iot_import'
      })

      if (uploadUrlRes.code !== 0) {
        throw new Error(uploadUrlRes.msg || '获取上传地址失败')
      }

      const { upload_url, file_key } = uploadUrlRes.data

      // 第二步：上传文件到对象存储
      ElMessage.info('正在上传文件...')
      await StorageService.uploadFile(upload_url, file, 'text/csv')

      // 第三步：调用设备导入API
      ElMessage.info('正在创建导入任务...')
      const importRes = await DeviceService.importDevices({
        file_key,
        batch_no: `DEV-${Date.now()}`
      })

      if (importRes.code !== 0) {
        throw new Error(importRes.msg || '创建导入任务失败')
      }

      const taskNo = importRes.data.task_no

      // 清空文件列表
      clearFiles()

      // 刷新任务列表
      await fetchImportTasks()

      // 显示成功消息
      ElMessage.success({
        message: `导入任务已创建！任务编号：${taskNo}`,
        duration: 3000,
        showClose: true
      })
    } catch (error: any) {
      console.error('设备导入失败:', error)
      ElMessage.error(error.message || '设备导入失败')
    } finally {
      uploading.value = false
    }
  }

  // 获取导入任务列表
  const fetchImportTasks = async () => {
    loading.value = true
    try {
      const params: any = {
        page: 1,
        page_size: 100
      }

      // 如果有状态筛选,添加到参数
      if (statusFilter.value !== null) {
        params.status = statusFilter.value
      }

      const res = await DeviceService.getImportTasks(params)
      if (res.code === 0 && res.data) {
        // 将API返回的数据映射到本地格式
        importRecords.value = res.data.items.map((item: any) => ({
          id: item.id.toString(),
          taskNo: item.task_no || '-',
          status: item.status,
          statusText: item.status_text || '-',
          batchNo: item.batch_no || '-',
          fileName: item.file_name || '-',
          totalCount: item.total_count || 0,
          successCount: item.success_count || 0,
          skipCount: item.skip_count || 0,
          failCount: item.fail_count || 0,
          warningCount: item.warning_count || 0,
          startedAt: item.started_at ? formatDateTime(item.started_at) : '-',
          completedAt: item.completed_at ? formatDateTime(item.completed_at) : '-',
          errorMessage: item.error_message || '-',
          createdAt: item.created_at ? formatDateTime(item.created_at) : '-'
        }))
      }
    } catch (error) {
      console.error('获取导入任务列表失败:', error)
      ElMessage.error('获取导入任务列表失败')
    } finally {
      loading.value = false
    }
  }

  const refreshList = () => {
    fetchImportTasks()
  }

  const viewDetail = async (row: ImportRecord) => {
    try {
      const res = await DeviceService.getImportTaskDetail(Number(row.id))
      if (res.code === 0 && res.data) {
        const detail = res.data
        currentDetail.value = {
          id: detail.id.toString(),
          taskNo: detail.task_no || '-',
          status: detail.status,
          statusText: detail.status_text || '-',
          batchNo: detail.batch_no || '-',
          fileName: detail.file_name || '-',
          totalCount: detail.total_count || 0,
          successCount: detail.success_count || 0,
          skipCount: detail.skip_count || 0,
          failCount: detail.fail_count || 0,
          warningCount: detail.warning_count || 0,
          startedAt: detail.started_at ? formatDateTime(detail.started_at) : '-',
          completedAt: detail.completed_at ? formatDateTime(detail.completed_at) : '-',
          errorMessage: detail.error_message || '-',
          createdAt: detail.created_at ? formatDateTime(detail.created_at) : '-',
          failReasons:
            detail.failed_items?.map((item: any, index: number) => ({
              row: index + 1,
              deviceCode: item.virtual_no || '-',
              iccid: item.iccid || '-',
              message: item.reason || item.error || '未知错误'
            })) || []
        }
        detailDialogVisible.value = true
      }
    } catch (error) {
      console.error('获取任务详情失败:', error)
      ElMessage.error('获取任务详情失败')
    }
  }

  const downloadFailData = (row: ImportRecord) => {
    if (!row.failReasons || row.failReasons.length === 0) {
      ElMessage.warning('没有失败数据可下载')
      return
    }

    // 生成失败数据CSV
    const headers = ['行号', '设备编号', 'ICCID', '失败原因']
    const csvRows = [
      headers.join(','),
      ...row.failReasons.map((item) =>
        [item.row, item.deviceCode, item.iccid, `"${item.message}"`].join(',')
      )
    ]
    const csvContent = csvRows.join('\n')

    // 添加 BOM 头确保 Excel 正确识别 UTF-8 编码
    const BOM = '\uFEFF'
    const blob = new Blob([BOM + csvContent], { type: 'text/csv;charset=utf-8;' })

    // 创建下载链接
    const link = document.createElement('a')
    const url = URL.createObjectURL(blob)
    link.setAttribute('href', url)
    link.setAttribute('download', `导入失败数据_${row.batchNo}.csv`)
    link.style.visibility = 'hidden'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(url)

    ElMessage.success('失败数据下载成功')
  }

  // 页面加载时获取任务列表
  onMounted(() => {
    fetchImportTasks()
  })

  // 监听状态筛选变化
  watch(statusFilter, () => {
    fetchImportTasks()
  })
</script>

<style lang="scss" scoped>
  .page-content {
    .upload-area {
      :deep(.el-upload) {
        width: 100%;
      }

      :deep(.el-upload-dragger) {
        width: 100%;
      }
    }

    :deep(.el-icon--upload) {
      margin-bottom: 16px;
      font-size: 67px;
      color: var(--el-text-color-placeholder);
    }

    :deep(.el-upload__text) {
      font-size: 14px;
      color: var(--el-text-color-regular);

      em {
        font-style: normal;
        color: var(--el-color-primary);
      }
    }

    :deep(.is-loading) {
      animation: rotating 2s linear infinite;
    }

    @keyframes rotating {
      0% {
        transform: rotate(0deg);
      }

      100% {
        transform: rotate(360deg);
      }
    }

    .stat-card {
      :deep(.el-card__body) {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 20px;
      }

      .stat-content {
        .stat-label {
          margin-bottom: 8px;
          font-size: 14px;
          color: var(--el-text-color-secondary);
        }

        .stat-value {
          font-size: 24px;
          font-weight: 600;
          color: var(--el-text-color-primary);
        }
      }

      .stat-icon {
        font-size: 40px;
        opacity: 0.6;
      }
    }
  }
</style>
