<template>
  <ArtTableFullScreen>
    <div class="iot-card-task-page" id="table-full-screen">
      <!-- 搜索栏 -->
      <ArtSearchBar
        v-model:filter="searchForm"
        :items="searchFormItems"
        show-expand
        @reset="handleReset"
        @search="handleSearch"
      ></ArtSearchBar>

      <ElCard shadow="never" class="art-table-card">
        <!-- 表格头部 -->
        <ArtTableHeader
          :columnList="columnOptions"
          v-model:columns="columnChecks"
          @refresh="handleRefresh"
        >
          <template #left>
            <ElButton
              type="primary"
              :icon="Upload"
              @click="importDialogVisible = true"
              v-permission="'lot_task:bulk_import'"
            >
              批量导入IoT卡
            </ElButton>
          </template>
        </ArtTableHeader>

        <!-- 表格 -->
        <ArtTable
          ref="tableRef"
          row-key="id"
          :loading="loading"
          :data="taskList"
          :currentPage="pagination.page"
          :pageSize="pagination.pageSize"
          :total="pagination.total"
          :marginTop="10"
          :actions="getActions"
          :actionsWidth="180"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        >
          <template #default>
            <ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
          </template>
        </ArtTable>
      </ElCard>
    </div>

    <!-- 失败数据对话框 -->
    <ElDialog
      v-model="failDataDialogVisible"
      title="失败数据详情"
      width="900px"
      align-center
      destroy-on-close
    >
      <div v-if="failDataLoading" style="padding: 40px; text-align: center">
        <ElSkeleton :rows="5" animated />
      </div>
      <div v-else-if="failedItems.length > 0">
        <ElAlert type="warning" :closable="false" style="margin-bottom: 20px">
          <template #title>
            <div style="line-height: 1.8">
              <p><strong>失败数据汇总：</strong></p>
              <p>共 {{ failedItems.length }} 条记录导入失败</p>
            </div>
          </template>
        </ElAlert>

        <ElTable :data="failedItems" max-height="400" border>
          <ElTableColumn prop="line" label="行号" width="80" />
          <ElTableColumn prop="iccid" label="ICCID" width="200" show-overflow-tooltip />
          <ElTableColumn prop="msisdn" label="MSISDN" width="150" show-overflow-tooltip />
          <ElTableColumn prop="message" label="失败原因" min-width="200" show-overflow-tooltip />
        </ElTable>
      </div>
      <div v-else style="padding: 40px; text-align: center">
        <ElEmpty description="暂无失败数据" />
      </div>

      <template #footer>
        <ElButton @click="failDataDialogVisible = false">关闭</ElButton>
        <ElButton
          v-if="failedItems.length > 0"
          type="primary"
          :icon="Download"
          @click="downloadCurrentFailData"
        >
          下载失败数据
        </ElButton>
      </template>
    </ElDialog>

    <!-- 导入对话框 -->
    <ElDialog v-model="importDialogVisible" title="批量导入IoT卡" width="700px" align-center>
      <ElAlert type="info" :closable="false" style="margin-bottom: 20px">
        <template #title>
          <div style="line-height: 1.8">
            <p><strong>导入说明：</strong></p>
            <p>1. 请先下载 Excel 模板文件，按照模板格式填写IoT卡信息</p>
            <p>2. 仅支持 Excel 格式（.xlsx），单次最多导入 1000 条</p>
            <p>3. 列格式请设置为文本格式，避免长数字被转为科学计数法</p>
            <p>4. <span style="color: var(--el-color-primary)">必填字段：ICCID、MSISDN</span></p>
            <p>5. 必须选择运营商</p>
          </div>
        </template>
      </ElAlert>

      <div style="margin-bottom: 20px">
        <ElButton type="primary" :icon="Download" @click="downloadTemplate">
          下载导入模板
        </ElButton>
      </div>

      <ElRow :gutter="20">
        <ElCol :span="12">
          <ElFormItem label="运营商" required>
            <ElSelect
              v-model="selectedCarrierId"
              placeholder="请输入运营商名称搜索"
              style="width: 100%"
              filterable
              remote
              :remote-method="handleCarrierSearch"
              :loading="carrierLoading"
              clearable
            >
              <ElOption
                v-for="carrier in carrierList"
                :key="carrier.id"
                :label="carrier.carrier_name"
                :value="carrier.id"
              />
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="卡业务类型">
            <ElSelect
              v-model="selectedCardCategory"
              placeholder="请选择卡业务类型"
              style="width: 100%"
            >
              <ElOption label="普通卡" value="normal" />
              <ElOption label="行业卡" value="industry" />
            </ElSelect>
          </ElFormItem>
        </ElCol>
      </ElRow>

      <ElRow :gutter="20">
        <ElCol :span="12">
          <ElFormItem label="批次号" prop="batch_no">
            <ElInput
              v-model="importForm.batch_no"
              placeholder="请输入批次号或点击生成"
              :maxlength="100"
              clearable
            >
              <template #append>
                <ElButton @click="handleGenerateBatchNo">生成编码</ElButton>
              </template>
            </ElInput>
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="实名认证策略">
            <ElSelect
              v-model="importForm.realname_policy"
              placeholder="默认无需实名"
              clearable
              style="width: 100%"
            >
              <ElOption label="无需实名" value="none" />
              <ElOption label="先实名后充值/购买" value="before_order" />
              <ElOption label="先充值/购买后实名" value="after_order" />
            </ElSelect>
          </ElFormItem>
        </ElCol>
      </ElRow>

      <ElUpload
        ref="uploadRef"
        drag
        :auto-upload="false"
        :on-change="handleFileChange"
        :limit="1"
        accept=".xlsx"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">将 Excel 文件拖到此处，或<em>点击选择</em></div>
        <template #tip>
          <div class="el-upload__tip">只能上传 .xlsx 格式的 Excel 文件，且不超过 300MB</div>
        </template>
      </ElUpload>

      <template #footer>
        <ElButton @click="handleCancelImport">取消</ElButton>
        <ElButton
          type="primary"
          :loading="uploading"
          :disabled="!fileList.length || !selectedCarrierId"
          @click="submitUpload"
        >
          开始导入
        </ElButton>
      </template>
    </ElDialog>
  </ArtTableFullScreen>
</template>

<script setup lang="ts">
  import { h } from 'vue'
  import { useRouter } from 'vue-router'
  import { ref, reactive, computed, onMounted } from 'vue'
  import { CardService, CarrierService } from '@/api/modules'
  import {
    ElMessage,
    ElTag,
    ElFormItem,
    ElSelect,
    ElOption,
    ElSkeleton,
    ElEmpty
  } from 'element-plus'
  import { Download, UploadFilled, Upload } from '@element-plus/icons-vue'
  import type { UploadInstance } from 'element-plus'
  import type { SearchFormItem } from '@/types'
  import { useCheckedColumns } from '@/composables/useCheckedColumns'
  import { useAuth } from '@/composables/useAuth'
  import { formatDateTime } from '@/utils/business/format'
  import { StorageService } from '@/api/modules/storage'
  import { generatePackageCode } from '@/utils/codeGenerator'
  import { RoutesAlias } from '@/router/routesAlias'
  import { CardCategory } from '@/types/api/card'
  import type { IotCardImportTask, IotCardImportTaskStatus } from '@/types/api/card'
  import type { Carrier } from '@/types/api'

  defineOptions({ name: 'IotCardTask' })

  const router = useRouter()

  const { hasAuth } = useAuth()

  const loading = ref(false)
  const tableRef = ref()
  const uploadRef = ref<UploadInstance>()
  const fileList = ref<File[]>([])
  const uploading = ref(false)
  const importDialogVisible = ref(false)
  const selectedCarrierId = ref<number>()
  const selectedCardCategory = ref<CardCategory>(CardCategory.NORMAL) // 默认普通卡
  const carrierList = ref<Carrier[]>([])
  const carrierLoading = ref(false)
  const failDataDialogVisible = ref(false)
  const failDataLoading = ref(false)
  const failedItems = ref<any[]>([])
  const currentFailTask = ref<IotCardImportTask | null>(null)
  const importForm = reactive({
    batch_no: '',
    realname_policy: '' as '' | 'none' | 'before_order' | 'after_order'
  })

  // 搜索表单初始值
  const initialSearchState = {
    status: undefined,
    carrier_id: undefined,
    batch_no: '',
    dateRange: undefined as any
  }

  // 搜索表单
  const searchForm = reactive({ ...initialSearchState })

  // 分页
  const pagination = reactive({
    page: 1,
    pageSize: 20,
    total: 0
  })

  // 搜索表单配置
  const searchFormItems = computed<SearchFormItem[]>(() => [
    {
      label: '任务状态',
      prop: 'status',
      type: 'select',
      config: {
        clearable: true,
        placeholder: '全部'
      },
      options: () => [
        { label: '待处理', value: 1 },
        { label: '处理中', value: 2 },
        { label: '已完成', value: 3 },
        { label: '失败', value: 4 }
      ]
    },
    {
      label: '运营商',
      prop: 'carrier_id',
      type: 'select',
      options: carrierList.value.map((carrier: Carrier) => ({
        label: carrier.carrier_name,
        value: carrier.id
      })),
      config: {
        clearable: true,
        filterable: true,
        remote: true,
        remoteMethod: handleCarrierSearch,
        placeholder: '请输入运营商名称搜索'
      }
    },
    {
      label: '批次号',
      prop: 'batch_no',
      type: 'input',
      config: {
        clearable: true,
        placeholder: '请输入批次号'
      }
    },
    {
      label: '创建时间',
      prop: 'dateRange',
      type: 'daterange',
      config: {
        type: 'daterange',
        startPlaceholder: '开始时间',
        endPlaceholder: '结束时间',
        valueFormat: 'YYYY-MM-DDTHH:mm:ssZ'
      }
    }
  ])

  // 列配置
  const columnOptions = [
    { label: '任务编号', prop: 'task_no' },
    { label: '任务状态', prop: 'status' },
    { label: '运营商', prop: 'carrier_name' },
    { label: '卡业务类型', prop: 'card_category' },
    { label: '总数', prop: 'total_count' },
    { label: '成功数', prop: 'success_count' },
    { label: '失败数', prop: 'fail_count' },
    { label: '跳过数', prop: 'skip_count' },
    { label: '开始时间', prop: 'started_at' },
    { label: '完成时间', prop: 'completed_at' },
    { label: '错误信息', prop: 'error_message' },
    { label: '批次号', prop: 'batch_no' },
    { label: '文件名', prop: 'file_name' },
    { label: '创建时间', prop: 'created_at' }
  ]

  const taskList = ref<IotCardImportTask[]>([])

  // 获取状态标签类型
  const getStatusType = (status: IotCardImportTaskStatus) => {
    switch (status) {
      case 1:
        return 'info'
      case 2:
        return 'warning'
      case 3:
        return 'success'
      case 4:
        return 'danger'
      default:
        return 'info'
    }
  }

  // 查看详情 - 跳转到详情页面
  const viewDetail = (row: IotCardImportTask) => {
    router.push({
      path: RoutesAlias.TaskDetail,
      query: {
        id: row.id,
        task_type: 'card'
      }
    })
  }

  // 处理名称点击
  const handleNameClick = (row: IotCardImportTask) => {
    if (hasAuth('iot_card_task:view_detail')) {
      viewDetail(row)
    } else {
      ElMessage.warning('您没有查看详情的权限')
    }
  }

  // 动态列配置
  const { columnChecks, columns } = useCheckedColumns(() => [
    {
      prop: 'task_no',
      label: '任务编号',
      width: 180,
      formatter: (row: IotCardImportTask) => {
        return h(
          'span',
          {
            style: 'color: var(--el-color-primary); cursor: pointer; text-decoration: underline;',
            onClick: (e: MouseEvent) => {
              e.stopPropagation()
              handleNameClick(row)
            }
          },
          row.task_no
        )
      }
    },
    {
      prop: 'status',
      label: '任务状态',
      width: 100,
      formatter: (row: IotCardImportTask) => {
        return h(ElTag, { type: getStatusType(row.status) }, () => row.status_text)
      }
    },
    {
      prop: 'carrier_name',
      label: '运营商',
      width: 180,
      showOverflowTooltip: true
    },
    {
      prop: 'card_category',
      label: '卡业务类型',
      width: 110,
      formatter: (row: IotCardImportTask) => {
        if (!row.card_category) return '-'
        return row.card_category === 'normal'
          ? '普通卡'
          : row.card_category === 'industry'
            ? '行业卡'
            : row.card_category
      }
    },
    {
      prop: 'total_count',
      label: '总数',
      width: 80
    },
    {
      prop: 'success_count',
      label: '成功数',
      width: 80,
      formatter: (row: IotCardImportTask) => {
        return h('span', { style: { color: 'var(--el-color-success)' } }, row.success_count)
      }
    },
    {
      prop: 'fail_count',
      label: '失败数',
      width: 80,
      formatter: (row: IotCardImportTask) => {
        return h('span', { style: { color: 'var(--el-color-danger)' } }, row.fail_count)
      }
    },
    {
      prop: 'skip_count',
      label: '跳过数',
      width: 80
    },
    {
      prop: 'batch_no',
      label: '批次号',
      width: 180,
      showOverflowTooltip: true
    },
    {
      prop: 'started_at',
      label: '开始时间',
      width: 180,
      formatter: (row: IotCardImportTask) => (row.started_at ? formatDateTime(row.started_at) : '-')
    },
    {
      prop: 'completed_at',
      label: '完成时间',
      width: 180,
      formatter: (row: IotCardImportTask) =>
        row.completed_at ? formatDateTime(row.completed_at) : '-'
    },
    {
      prop: 'error_message',
      label: '错误信息',
      minWidth: 200,
      showOverflowTooltip: true,
      formatter: (row: IotCardImportTask) => row.error_message || '-'
    },
    {
      prop: 'file_name',
      label: '文件名',
      minWidth: 250,
      showOverflowTooltip: true
    },
    {
      prop: 'creator_name',
      label: '操作人',
      width: 140,
      showOverflowTooltip: true,
      formatter: (row: IotCardImportTask) => row.creator_name || '-'
    },
    {
      prop: 'created_at',
      label: '创建时间',
      width: 180,
      formatter: (row: IotCardImportTask) => formatDateTime(row.created_at)
    }
  ])

  onMounted(() => {
    getTableData()
    loadCarrierList()
  })

  // 获取IoT卡任务列表
  const getTableData = async () => {
    loading.value = true
    try {
      const params: any = {
        page: pagination.page,
        page_size: pagination.pageSize,
        status: searchForm.status,
        carrier_id: searchForm.carrier_id,
        batch_no: searchForm.batch_no || undefined
      }

      // 处理时间范围
      if (searchForm.dateRange && Array.isArray(searchForm.dateRange)) {
        params.start_time = searchForm.dateRange[0]
        params.end_time = searchForm.dateRange[1]
      }

      // 清理空值
      Object.keys(params).forEach((key) => {
        if (params[key] === '' || params[key] === undefined) {
          delete params[key]
        }
      })

      const res = await CardService.getIotCardImportTasks(params)
      if (res.code === 0) {
        taskList.value = res.data.items || []
        pagination.total = res.data.total || 0
      }
    } catch (error) {
      console.error(error)
    } finally {
      loading.value = false
    }
  }

  // 重置搜索
  const handleReset = () => {
    Object.assign(searchForm, { ...initialSearchState })
    pagination.page = 1
    getTableData()
  }

  // 搜索
  const handleSearch = () => {
    pagination.page = 1
    getTableData()
  }

  // 刷新表格
  const handleRefresh = () => {
    getTableData()
  }

  // 处理表格分页变化
  const handleSizeChange = (newPageSize: number) => {
    pagination.pageSize = newPageSize
    getTableData()
  }

  const handleCurrentChange = (newCurrentPage: number) => {
    pagination.page = newCurrentPage
    getTableData()
  }

  // 显示失败数据弹窗
  const showFailDataDialog = async (row: IotCardImportTask) => {
    try {
      failDataDialogVisible.value = true
      failDataLoading.value = true
      failedItems.value = []
      currentFailTask.value = row

      const res = await CardService.getIotCardImportTaskDetail(row.id)
      if (res.code === 0 && res.data) {
        const detail = res.data
        failedItems.value =
          detail.failed_items?.map((item: any) => ({
            line: item.line || '-',
            iccid: item.iccid || '-',
            msisdn: item.msisdn || '-',
            message: item.reason || item.error || '未知错误'
          })) || []

        if (failedItems.value.length === 0) {
          ElMessage.warning('没有失败数据')
        }
      }
    } catch (error) {
      console.error('获取失败数据失败:', error)
    } finally {
      failDataLoading.value = false
    }
  }

  // 下载当前失败数据
  const downloadCurrentFailData = () => {
    if (!currentFailTask.value || failedItems.value.length === 0) {
      ElMessage.warning('没有失败数据可下载')
      return
    }

    try {
      const headers = ['行号', 'ICCID', 'MSISDN', '失败原因']
      const csvRows = [
        headers.join(','),
        ...failedItems.value.map((item: any) =>
          [item.line, item.iccid, item.msisdn, `"${item.message}"`].join(',')
        )
      ]
      const csvContent = csvRows.join('\n')

      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', `IoT卡导入失败数据_${currentFailTask.value.task_no}.csv`)
      link.style.visibility = 'hidden'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      URL.revokeObjectURL(url)

      ElMessage.success('失败数据下载成功')
    } catch (error) {
      console.error('下载失败数据失败:', error)
    }
  }

  // 下载模板
  const downloadTemplate = async () => {
    try {
      const link = document.createElement('a')
      link.href = new URL('@/template/IoT卡导入模板.xlsx', import.meta.url).href
      link.download = 'IoT卡导入模板.xlsx'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      ElMessage.success('IoT卡导入模板下载成功')
    } catch (error) {
      console.error('下载模板失败:', error)
      ElMessage.error('下载模板失败')
    }
  }

  // 文件选择变化
  const handleFileChange = (uploadFile: any) => {
    const maxSize = 300 * 1024 * 1024
    if (uploadFile.raw && uploadFile.raw.size > maxSize) {
      ElMessage.error('文件大小不能超过 300MB')
      uploadRef.value?.clearFiles()
      fileList.value = []
      return
    }

    if (uploadFile.raw && !uploadFile.raw.name.endsWith('.xlsx')) {
      ElMessage.error('只能上传 .xlsx 格式的 Excel 文件')
      uploadRef.value?.clearFiles()
      fileList.value = []
      return
    }

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

  // 清空文件
  const clearFiles = () => {
    uploadRef.value?.clearFiles()
    fileList.value = []
    selectedCarrierId.value = undefined
  }

  // 生成批次号
  const handleGenerateBatchNo = () => {
    const code = generatePackageCode().replace('PKG', 'IOT')
    importForm.batch_no = code
    ElMessage.success('批次号生成成功')
  }

  // 取消导入
  const handleCancelImport = () => {
    clearFiles()
    selectedCardCategory.value = CardCategory.NORMAL
    importForm.batch_no = ''
    importForm.realname_policy = ''
    importDialogVisible.value = false
  }

  // 加载运营商列表
  const loadCarrierList = async (carrierName?: string) => {
    carrierLoading.value = true
    try {
      const res = await CarrierService.getCarriers({
        page: 1,
        page_size: 20,
        carrier_name: carrierName || undefined,
        status: 1 // 只加载启用的运营商
      })
      if (res.code === 0) {
        carrierList.value = res.data.items || []
      }
    } catch (error) {
      console.error('获取运营商列表失败:', error)
    } finally {
      carrierLoading.value = false
    }
  }

  // 运营商搜索处理
  const handleCarrierSearch = (query: string) => {
    loadCarrierList(query)
  }

  // 提交上传
  const submitUpload = async () => {
    if (!selectedCarrierId.value) {
      ElMessage.warning('请先选择运营商')
      return
    }

    if (!fileList.value.length) {
      ElMessage.warning('请先选择 Excel 文件')
      return
    }

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

    try {
      ElMessage.info('正在准备上传...')
      const uploadUrlRes = await StorageService.getUploadUrl({
        file_name: file.name,
        content_type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        purpose: 'iot_import'
      })

      if (uploadUrlRes.code !== 0) {
        ElMessage.error(uploadUrlRes.msg || '获取上传地址失败')
        return
      }

      const { upload_url, file_key } = uploadUrlRes.data

      ElMessage.info('正在上传文件...')
      await StorageService.uploadFile(
        upload_url,
        file,
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      )

      ElMessage.info('正在创建导入任务...')
      const importRes = await CardService.importIotCards({
        carrier_id: selectedCarrierId.value,
        file_key,
        batch_no: importForm.batch_no || undefined,
        card_category: selectedCardCategory.value,
        realname_policy: importForm.realname_policy || undefined
      })

      if (importRes.code !== 0) {
        ElMessage.error(importRes.msg || '创建导入任务失败')
        return
      }

      const taskNo = importRes.data.task_no

      handleCancelImport()
      await getTableData()

      ElMessage.success({
        message: `导入任务已创建！任务编号：${taskNo}`,
        duration: 3000,
        showClose: true
      })
    } catch (error: any) {
      console.error('IoT卡导入失败:', error)
      console.log(error.message || 'IoT卡导入失败')
    } finally {
      uploading.value = false
    }
  }

  const downloadTaskFile = async (row: IotCardImportTask) => {
    const fileKey = row.file_name?.trim()
    if (!fileKey) {
      ElMessage.warning('当前任务没有可下载的原始文件')
      return
    }

    try {
      await StorageService.downloadFileByKey(fileKey)
      ElMessage.success('原始文件下载已开始')
    } catch (error) {
      console.error('下载原始文件失败:', error)
      ElMessage.error('下载原始文件失败')
    }
  }

  // 获取操作按钮
  const getActions = (row: IotCardImportTask) => {
    const actions: any[] = []
    const showDownloadFileAction = false

    if (showDownloadFileAction && row.file_name?.trim() && hasAuth('iot_card_task:download_file')) {
      actions.push({
        label: '下载文件',
        handler: () => downloadTaskFile(row),
        type: 'primary'
      })
    }

    if (row.fail_count > 0 && hasAuth('iot_card_task:download_fail_data')) {
      actions.push({
        label: '失败数据',
        handler: () => showFailDataDialog(row),
        type: 'danger'
      })
    }

    return actions
  }
</script>

<style lang="scss" scoped>
  .iot-card-task-page {
    :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);
      }
    }
  }
</style>
