<script setup lang="ts">
import type { ExportMaskPolicy, ExportTaskItem } from '../../../types/export'

usePageTitle('数据导出')

const toast = useToast()
const { fetchData, getApiErrorMessage } = useClientApi()

const maskPolicy = ref<ExportMaskPolicy>('masked')
const creating = ref(false)
const loading = ref(true)
const refreshing = ref(false)
const tasks = ref<ExportTaskItem[]>([])

const maskPolicyItems = [
  { label: 'masked（默认，脱敏导出）', value: 'masked' as const },
  { label: 'raw（原始值导出）', value: 'raw' as const },
]

const statusToneMap: Record<ExportTaskItem['status'], 'neutral' | 'primary' | 'success' | 'error' | 'warning'> = {
  queued: 'neutral',
  running: 'primary',
  succeeded: 'success',
  failed: 'error',
  expired: 'warning',
}

const statusLabelMap: Record<ExportTaskItem['status'], string> = {
  queued: '排队中',
  running: '处理中',
  succeeded: '已完成',
  failed: '失败',
  expired: '已过期',
}

function formatTime(iso: string | null): string {
  if (!iso) {
    return '—'
  }
  const dt = new Date(iso)
  return Number.isNaN(dt.getTime()) ? iso : dt.toLocaleString('zh-CN')
}

function formatBytes(n: number | null): string {
  if (n === null || Number.isNaN(n)) {
    return '—'
  }
  if (n < 1024) {
    return `${n} B`
  }
  if (n < 1024 * 1024) {
    return `${(n / 1024).toFixed(1)} KB`
  }
  return `${(n / (1024 * 1024)).toFixed(1)} MB`
}

function taskDownloadUrl(taskId: number): string {
  return `/api/me/export/tasks/${taskId}/download`
}

async function loadTasks() {
  const useBlocking = tasks.value.length === 0
  if (useBlocking) {
    loading.value = true
  } else {
    refreshing.value = true
  }
  try {
    const res = await fetchData<{ items: ExportTaskItem[] }>('/api/me/export/tasks', { notify: false })
    tasks.value = res.items
  } catch (e: unknown) {
    toast.add({ title: getApiErrorMessage(e), color: 'error' })
  } finally {
    loading.value = false
    refreshing.value = false
  }
}

async function createTask() {
  if (creating.value) {
    return
  }
  creating.value = true
  try {
    await fetchData('/api/me/export/request', {
      method: 'POST',
      body: { maskPolicy: maskPolicy.value },
      notify: false,
    })
    toast.add({ title: '导出任务已创建', color: 'success' })
    await loadTasks()
  } catch (e: unknown) {
    toast.add({ title: getApiErrorMessage(e), color: 'error' })
  } finally {
    creating.value = false
  }
}

async function recreateTask(task: ExportTaskItem) {
  maskPolicy.value = task.maskPolicy
  await createTask()
}

async function deleteTask(task: ExportTaskItem) {
  const ok = window.confirm(`确定删除导出任务 #${task.id} 吗？`)
  if (!ok) {
    return
  }
  try {
    await fetchData(`/api/me/export/tasks/${task.id}`, {
      method: 'DELETE',
      notify: false,
    })
    toast.add({ title: `任务 #${task.id} 已删除`, color: 'success' })
    await loadTasks()
  } catch (e: unknown) {
    toast.add({ title: getApiErrorMessage(e), color: 'error' })
  }
}

onMounted(() => {
  void loadTasks()
})
</script>

<template>
  <UContainer class="max-w-6xl py-8 space-y-6">
    <header class="space-y-1">
      <h1 class="text-2xl font-semibold">
        数据导出
      </h1>
      <p class="text-sm text-muted">
        选择导出策略并发起任务，完成后可直接下载结果包。
      </p>
    </header>

    <UCard>
      <div class="flex flex-col gap-4 md:flex-row md:items-end md:justify-between">
        <UFormField label="导出策略（maskPolicy）" class="w-full md:max-w-sm">
          <USelect
            v-model="maskPolicy"
            class="w-full"
            :items="maskPolicyItems"
            value-key="value"
          />
        </UFormField>
        <div class="flex items-center gap-2">
          <UButton
            icon="i-lucide-file-output"
            :loading="creating"
            :disabled="creating"
            @click="createTask"
          >
            发起导出
          </UButton>
          <UButton
            variant="outline"
            color="neutral"
            icon="i-lucide-refresh-cw"
            :loading="refreshing"
            :disabled="creating || loading"
            @click="loadTasks"
          >
            刷新
          </UButton>
        </div>
      </div>
    </UCard>

    <section class="space-y-3" aria-labelledby="export-task-list-title">
      <div class="flex items-center justify-between gap-3">
        <h2 id="export-task-list-title" class="text-sm font-medium text-muted">
          导出任务（{{ tasks.length }}）
        </h2>
      </div>

      <div v-if="loading" class="text-sm text-muted">
        加载中...
      </div>
      <UEmpty
        v-else-if="!tasks.length"
        title="暂无导出任务"
        description="选择导出策略后，点击“发起导出”创建第一条任务。"
      />
      <div v-else class="space-y-3">
        <UCard v-for="task in tasks" :key="task.id">
          <div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
            <div class="space-y-2 min-w-0">
              <div class="flex flex-wrap items-center gap-2">
                <span class="text-sm font-medium">任务 #{{ task.id }}</span>
                <UBadge :color="statusToneMap[task.status]" variant="soft">
                  {{ statusLabelMap[task.status] }}
                </UBadge>
                <UBadge color="neutral" variant="outline">
                  {{ task.maskPolicy }}
                </UBadge>
              </div>
              <p class="text-xs text-muted">
                创建时间：{{ formatTime(task.createdAt) }}
              </p>
              <p class="text-xs text-muted">
                更新时间：{{ formatTime(task.updatedAt) }}
              </p>
              <p class="text-xs text-muted">
                文件大小：{{ formatBytes(task.totalBytes) }}
              </p>
              <p v-if="task.expiresAt" class="text-xs text-muted">
                下载截止：{{ formatTime(task.expiresAt) }}
              </p>
              <p v-if="task.errorMessage" class="text-xs text-error">
                失败原因：{{ task.errorMessage }}
              </p>
            </div>
            <div class="flex items-center gap-2">
              <UButton
                v-if="task.status === 'succeeded'"
                icon="i-lucide-download"
                :to="taskDownloadUrl(task.id)"
                target="_blank"
                rel="noopener"
                size="sm"
              >
                下载
              </UButton>
              <UButton
                v-else-if="task.status === 'expired'"
                icon="i-lucide-rotate-ccw"
                variant="outline"
                size="sm"
                :loading="creating"
                :disabled="creating"
                @click="recreateTask(task)"
              >
                重新导出
              </UButton>
              <UButton
                v-if="task.status !== 'running'"
                icon="i-lucide-trash-2"
                color="error"
                variant="ghost"
                size="sm"
                :disabled="creating || refreshing"
                @click="deleteTask(task)"
              >
                删除
              </UButton>
            </div>
          </div>
        </UCard>
      </div>
    </section>
  </UContainer>
</template>
