<template>
  <ArtTableFullScreen>
    <div class="export-task-list-page" id="table-full-screen">
      <ArtSearchBar
        v-model:filter="searchForm"
        :items="searchFormItems"
        label-width="110"
        :show-expand="false"
        @reset="handleReset"
        @search="handleSearch"
      />

      <ElCard shadow="never" class="art-table-card">
        <ArtTableHeader
          :columnList="columnOptions"
          v-model:columns="columnChecks"
          @refresh="handleRefresh"
        />

        <ArtTable
          :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>
  </ArtTableFullScreen>
</template>

<script setup lang="ts">
  import { computed, h, onMounted, reactive, ref, watch } from 'vue'
  import { useRoute, useRouter } from 'vue-router'
  import { ElMessage, ElMessageBox, ElProgress, ElTag } from 'element-plus'
  import { ExportTaskService } from '@/api/modules'
  import { useAuth } from '@/composables/useAuth'
  import { useCheckedColumns } from '@/composables/useCheckedColumns'
  import { formatDateTime } from '@/utils/business/format'
  import { RoutesAlias } from '@/router/routesAlias'
  import { getExportTaskSceneConfig } from '@/config/constants'
  import type { SearchFormItem } from '@/types'
  import type { ExportTaskDetail, ExportTaskItem, ExportTaskScene } from '@/types/api'
  import { ExportTaskStatus } from '@/types/api'
  import { useAsyncTaskPolling } from '@/composables/useAsyncTaskPolling'

  defineOptions({ name: 'ExportTaskList' })

  const route = useRoute()
  const router = useRouter()
  const { hasAuth } = useAuth()
  const loading = ref(false)
  const taskList = ref<ExportTaskItem[]>([])
  const defaultSceneConfig = getExportTaskSceneConfig('device')!

  const routeScene = computed(() => route.meta.exportTaskScene as ExportTaskScene | undefined)
  const sceneConfig = computed(
    () => getExportTaskSceneConfig(routeScene.value) || defaultSceneConfig
  )
  const currentScene = computed(() => sceneConfig.value.scene)
  const currentPermissions = computed(() => sceneConfig.value.permissions)

  const initialSearchState = {
    status: undefined as ExportTaskStatus | undefined,
    dateRange: [] as string[],
    start_time: '',
    end_time: ''
  }

  const searchForm = reactive({ ...initialSearchState })
  const pagination = reactive({
    page: 1,
    pageSize: 20,
    total: 0
  })

  const statusOptions = [
    { label: '待处理', value: ExportTaskStatus.PENDING },
    { label: '处理中', value: ExportTaskStatus.PROCESSING },
    { label: '已完成', value: ExportTaskStatus.COMPLETED },
    { label: '失败', value: ExportTaskStatus.FAILED },
    { label: '已取消', value: ExportTaskStatus.CANCELED }
  ]

  const searchFormItems: SearchFormItem[] = [
    {
      label: '任务状态',
      prop: 'status',
      type: 'select',
      config: { clearable: true, placeholder: '请选择任务状态' },
      options: () => statusOptions
    },
    {
      label: '创建时间',
      prop: 'dateRange',
      type: 'date',
      config: {
        type: 'daterange',
        rangeSeparator: '至',
        startPlaceholder: '开始时间',
        endPlaceholder: '结束时间',
        valueFormat: 'YYYY-MM-DD'
      }
    }
  ]

  const columnOptions = [
    { label: '任务编号', prop: 'task_no' },
    { label: '状态', prop: 'status_name' },
    { label: '进度', prop: 'progress' },
    { label: '总数', prop: 'total_count' },
    { label: '成功数', prop: 'success_count' },
    { label: '失败数', prop: 'failed_count' },
    { label: '格式', prop: 'format' },
    { label: '总行数', prop: 'total_rows' },
    { label: '已处理行数', prop: 'processed_rows' },
    { label: '分片', prop: 'total_shards' },
    { label: '错误信息', prop: 'error_summary' },
    { label: '更新时间', prop: 'updated_at' },
    { label: '创建时间', prop: 'created_at' }
  ]

  const { columnChecks, columns } = useCheckedColumns(() => [
    {
      prop: 'task_no',
      label: '任务编号',
      minWidth: 170,
      showOverflowTooltip: true,
      formatter: (row: ExportTaskItem) =>
        h(
          'span',
          {
            class: 'task-no-link',
            onClick: () => goDetail(row)
          },
          row.task_no || '-'
        )
    },
    {
      prop: 'status_name',
      label: '状态',
      width: 110,
      formatter: (row: ExportTaskItem) =>
        h(ElTag, { type: getStatusTagType(row.status) }, () => row.status_name || '-')
    },
    {
      prop: 'progress',
      label: '进度',
      width: 150,
      formatter: (row: ExportTaskItem) => h(ElProgress, { percentage: row.progress || 0 })
    },
    {
      prop: 'total_count',
      label: '总数',
      width: 100,
      formatter: (row: ExportTaskItem) => row.total_count ?? row.total_rows ?? 0
    },
    {
      prop: 'success_count',
      label: '成功数',
      width: 100,
      formatter: (row: ExportTaskItem) => row.success_count ?? 0
    },
    {
      prop: 'failed_count',
      label: '失败数',
      width: 100,
      formatter: (row: ExportTaskItem) => row.failed_count ?? 0
    },
    { prop: 'format', label: '格式', width: 90 },
    { prop: 'total_rows', label: '总行数', width: 110 },
    { prop: 'processed_rows', label: '已处理行数', width: 120 },
    {
      prop: 'total_shards',
      label: '分片',
      width: 130,
      formatter: (row: ExportTaskItem) => `${row.success_shards || 0}/${row.total_shards || 0}`
    },
    {
      prop: 'error_summary',
      label: '错误信息',
      minWidth: 180,
      showOverflowTooltip: true,
      formatter: (row: ExportTaskItem) => row.error_summary || row.error_message || '-'
    },
    {
      prop: 'created_at',
      label: '创建时间',
      width: 180,
      formatter: (row: ExportTaskItem) => formatDateTime(row.created_at) || '-'
    },
    {
      prop: 'updated_at',
      label: '更新时间',
      width: 180,
      formatter: (row: ExportTaskItem) => formatDateTime(row.updated_at) || '-'
    }
  ])

  const getStatusTagType = (status: ExportTaskStatus) => {
    const statusTypeMap: Record<
      ExportTaskStatus,
      'primary' | 'success' | 'warning' | 'danger' | 'info'
    > = {
      [ExportTaskStatus.PENDING]: 'info',
      [ExportTaskStatus.PROCESSING]: 'warning',
      [ExportTaskStatus.COMPLETED]: 'success',
      [ExportTaskStatus.FAILED]: 'danger',
      [ExportTaskStatus.CANCELED]: 'info'
    }

    return statusTypeMap[status] || 'info'
  }

  const syncDateRange = () => {
    if (Array.isArray(searchForm.dateRange) && searchForm.dateRange.length === 2) {
      searchForm.start_time = searchForm.dateRange[0] || ''
      searchForm.end_time = searchForm.dateRange[1] || ''
    } else {
      searchForm.start_time = ''
      searchForm.end_time = ''
    }
  }

  const getTableData = async () => {
    loading.value = true
    try {
      syncDateRange()
      const res = await ExportTaskService.getExportTasks({
        page: pagination.page,
        page_size: pagination.pageSize,
        scene: currentScene.value,
        status: searchForm.status,
        start_time: searchForm.start_time || undefined,
        end_time: searchForm.end_time || undefined
      })

      if (res.code === 0 && res.data) {
        taskList.value = res.data.items || []
        pagination.total = res.data.total || 0
      } else {
        ElMessage.error(res.msg || '获取导出任务列表失败')
      }
    } catch (error) {
      console.error('获取导出任务列表失败:', error)
      ElMessage.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 = (pageSize: number) => {
    pagination.pageSize = pageSize
    getTableData()
  }

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

  const getTaskDetail = async (id: number) => {
    const res = await ExportTaskService.getExportTaskDetail(id)
    if (res.code !== 0 || !res.data) {
      throw new Error(res.msg || '获取导出任务详情失败')
    }

    return res.data
  }

  const activeTaskPolling = useAsyncTaskPolling<ExportTaskDetail>({
    storageKey: computed(() => `export-task-active:${currentScene.value}`).value,
    fetchTask: async (taskId) => {
      const res = await ExportTaskService.getExportTaskDetail(taskId)
      if (res.code === 403) {
        const error = new Error('暂无权限查看导出任务') as Error & { status?: number }
        error.status = 403
        throw error
      }
      if (res.code !== 0 || !res.data) throw new Error(res.msg || '获取导出任务详情失败')
      return res.data
    },
    isForbidden: (error: any) => error?.status === 403 || error?.response?.status === 403
  })

  watch(activeTaskPolling.task, () => {
    if (activeTaskPolling.task.value) getTableData()
  })

  const getRowPermissions = (row: ExportTaskItem) => {
    return getExportTaskSceneConfig(row.scene)?.permissions || currentPermissions.value
  }

  const goDetail = (row: ExportTaskItem) => {
    if (!hasAuth(getRowPermissions(row).detail)) {
      ElMessage.warning('您没有查看导出任务详情的权限')
      return
    }

    router.push({
      path: RoutesAlias.ExportTaskDetail,
      query: { id: row.task_id ?? row.id }
    })
  }

  const downloadTask = async (row: ExportTaskItem) => {
    if (!hasAuth(getRowPermissions(row).download)) {
      ElMessage.warning('您没有下载导出任务的权限')
      return
    }

    try {
      const detail = await getTaskDetail(row.task_id ?? row.id)
      if (!detail.download_url) {
        ElMessage.warning('当前任务暂无可用下载地址')
        return
      }

      window.open(detail.download_url, '_blank')
    } catch (error) {
      console.error('下载导出文件失败:', error)
      ElMessage.error(error instanceof Error ? error.message : '下载导出文件失败')
    }
  }

  const cancelTask = (row: ExportTaskItem) => {
    if (!hasAuth(getRowPermissions(row).cancel)) {
      ElMessage.warning('您没有取消导出任务的权限')
      return
    }

    ElMessageBox.confirm(`确定取消导出任务 ${row.task_no} 吗？`, '取消确认', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      try {
        const res = await ExportTaskService.cancelExportTask(row.task_id ?? row.id)
        if (res.code === 0) {
          ElMessage.success(res.data?.message || '任务取消成功')
          getTableData()
        } else {
          ElMessage.error(res.msg || '取消导出任务失败')
        }
      } catch (error) {
        console.error('取消导出任务失败:', error)
        ElMessage.error('取消导出任务失败')
      }
    })
  }

  const getActions = (row: ExportTaskItem) => {
    const actions: any[] = []
    const permissions = getRowPermissions(row)

    if (row.status === ExportTaskStatus.COMPLETED && hasAuth(permissions.download)) {
      actions.push({ label: '下载', handler: () => downloadTask(row), type: 'primary' })
    }

    if (
      [ExportTaskStatus.PENDING, ExportTaskStatus.PROCESSING].includes(row.status) &&
      hasAuth(permissions.cancel)
    ) {
      actions.push({ label: '取消', handler: () => cancelTask(row), type: 'danger' })
    }

    return actions
  }

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

  watch(currentScene, () => {
    Object.assign(searchForm, { ...initialSearchState })
    pagination.page = 1
    getTableData()
  })
</script>

<style scoped lang="scss">
  .export-task-list-page {
    height: 100%;
  }

  :deep(.task-no-link) {
    color: var(--el-color-primary);
    cursor: pointer;

    &:hover {
      text-decoration: underline;
    }
  }
</style>
