<script setup lang="ts">
import { NButton, NSpin, useDialog } from 'naive-ui'
import { computed, onUnmounted, ref } from 'vue'
import { RouterLink, useRoute, useRouter } from 'vue-router'

import { deleteTask, getTask, listTaskLogs, runTask, updateTask } from '@/api/tasks'
import EmptyCard from '@/components/EmptyCard.vue'
import StatusBadge from '@/components/StatusBadge.vue'
import TaskFormModal from '@/components/task/TaskFormModal.vue'
import TaskTypeIcon from '@/components/task/TaskTypeIcon.vue'
import { parseSnatch, scopeCfgIds, STATUS_META, TYPE_LABEL } from '@/components/task/taskDisplay'
import { fmtRelative, fmtTime, regionCity } from '@/composables/useFormat'
import { useAsync } from '@/composables/useAsync'
import { useScopeStore } from '@/stores/scope'
import { useToast } from '@/composables/useToast'

const route = useRoute()
const router = useRouter()
const message = useToast()
const dialog = useDialog()
const scope = useScopeStore()

const taskId = computed(() => Number(route.params.taskId))

const task = useAsync(() => getTask(taskId.value))
const logs = useAsync(() => listTaskLogs(taskId.value))

// 每 5 秒静默刷新任务与事件流
const refreshTimer = setInterval(() => {
  void task.run({ silent: true })
  void logs.run({ silent: true })
}, 5000)
onUnmounted(() => clearInterval(refreshTimer))

const snatch = computed(() => (task.data.value ? parseSnatch(task.data.value) : null))
const status = computed(() => (task.data.value ? STATUS_META[task.data.value.status] : null))
const cfgAlias = computed(() => {
  const s = snatch.value
  if (!s) return ''
  return (scope.configs.data ?? []).find((c) => c.id === s.cfgId)?.alias ?? `租户 #${s.cfgId}`
})

const pct = computed(() => {
  const s = snatch.value
  if (!s?.total) return 0
  return Math.min(100, Math.round((s.done / s.total) * 100))
})

/** 右栏任务参数键值对（按类型组装） */
const params = computed<[string, string][]>(() => {
  const t = task.data.value
  if (!t) return []
  const s = snatch.value
  if (s) {
    return [
      ['所属租户', cfgAlias.value],
      ['目标 Shape', s.shape],
      ['规格', s.ocpus ? `${s.ocpus} OCPU · ${s.memoryInGBs} GB` : '—'],
      ['引导卷', s.bootGb ? `${s.bootGb} GB` : '默认'],
      ['实例名', s.displayName ?? '—'],
      ['目标数量', `${s.total} 台`],
      ['剩余数量', `${s.remaining} 台`],
      ['调度周期', t.cronExpr],
      ['区域', s.region ? regionCity(s.region) : '默认'],
    ]
  }
  const ids = scopeCfgIds(t)
  const scope = t.type === 'ai_probe'
    ? '号池渠道对应租户'
    : ids.length ? `${ids.length} 个租户` : '全部租户'
  return [
    ['类型', TYPE_LABEL[t.type]],
    ['范围', scope],
    ['调度周期', t.cronExpr],
    ['已运行', `${t.runCount} 次`],
  ]
})

const showEdit = ref(false)

async function act(fn: () => Promise<unknown>, ok: string) {
  try {
    await fn()
    message.success(ok)
    void task.run({ silent: true })
    void logs.run({ silent: true })
  } catch (e) {
    message.error(e instanceof Error ? e.message : '操作失败')
  }
}

/** active ↔ paused 切换；failed（熔断停止）同走恢复交互重新启用 */
function toggle() {
  const t = task.data.value
  if (!t) return
  const resume = t.status !== 'active'
  void act(
    () => updateTask(t.id, { status: resume ? 'active' : 'paused' }),
    resume ? (t.status === 'failed' ? '已重新启用' : '已恢复调度') : '已暂停',
  )
}

function confirmRemove() {
  const t = task.data.value
  if (!t) return
  dialog.warning({
    title: '删除任务',
    content: `删除任务「${t.name}」及其全部日志？`,
    positiveText: '删除',
    negativeText: '取消',
    onPositiveClick: async () => {
      await deleteTask(t.id)
      message.success('已删除任务及其日志')
      void router.push({ name: 'tasks' })
    },
  })
}

const features = computed(() => {
  const base = [
    ['持久化存储', '任务参数与进度写入数据库，不依赖内存状态'],
    ['重启自动恢复', '服务重启后自动加载未完成任务并继续调度'],
  ]
  if (task.data.value?.type === 'snatch')
    base.push(['抢满自动停止', '达到目标数量后任务自动标记完成，不再调度'])
  else base.push(['日志滚动保留', '每个任务保留最近 100 条执行日志'])
  return base
})
</script>

<template>
  <div class="flex flex-col gap-4 p-6 pb-8 max-md:p-3">
    <RouterLink
      :to="{ name: 'tasks' }"
      class="flex w-fit items-center gap-1.5 text-[13px] text-ink-3 transition-colors hover:text-ink"
    >
      <svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <path d="M15 6l-6 6 6 6" />
      </svg>
      返回任务列表
    </RouterLink>

    <div
      v-if="task.loading.value && !task.data.value"
      class="panel flex items-center justify-center py-20"
    >
      <NSpin size="small" />
    </div>
    <div v-else-if="task.error.value" class="panel px-5 py-10 text-center text-[13px] text-ink-3">
      {{ task.error.value }}
    </div>
    <div
      v-else-if="task.data.value"
      class="grid grid-cols-[minmax(0,1fr)_360px] items-start gap-4 max-lg:grid-cols-1"
    >
      <div class="flex min-w-0 flex-col gap-4">
        <!-- 头部：名称 + 操作 + 进度 -->
        <div class="panel px-6 py-5">
          <div class="flex flex-wrap items-start gap-3.5">
            <div class="flex h-11 w-11 flex-none items-center justify-center rounded-[10px] bg-wash">
              <TaskTypeIcon :type="task.data.value.type" class="h-[22px] w-[22px] text-accent" />
            </div>
            <div class="min-w-0 flex-1">
              <div class="flex flex-wrap items-center gap-2.5">
                <span class="page-title !text-xl">{{ task.data.value.name }}</span>
                <StatusBadge v-if="status" :kind="status.kind" :label="status.label" />
              </div>
              <div class="mono mt-1 text-xs text-ink-3">
                {{ TYPE_LABEL[task.data.value.type] }} · {{ task.data.value.cronExpr }} · 创建于
                {{ fmtTime(task.data.value.createdAt) }}
              </div>
            </div>
            <div class="flex flex-none items-center gap-2">
              <NButton
                size="small"
                @click="act(() => runTask(task.data.value!.id), '已触发执行')"
              >
                立即执行
              </NButton>
              <NButton
                v-if="task.data.value.status !== 'succeeded'"
                size="small"
                @click="toggle"
              >
                {{ task.data.value.status === 'active' ? '暂停' : task.data.value.status === 'failed' ? '启用' : '恢复' }}
              </NButton>
              <NButton v-if="task.data.value.type !== 'ai_probe'" size="small" @click="showEdit = true">编辑</NButton>
              <NButton v-if="task.data.value.type !== 'ai_probe'" size="small" type="error" quaternary @click="confirmRemove">删除</NButton>
            </div>
          </div>

          <div v-if="snatch" class="mt-5">
            <div class="mb-2 flex items-center justify-between">
              <span class="text-[13px] text-ink-3">创建进度</span>
              <span class="mono text-[15px]">
                <b
                  class="text-lg"
                  :style="{
                    color:
                      task.data.value.status === 'succeeded'
                        ? 'var(--color-ok)'
                        : 'var(--color-accent)',
                  }"
                >{{ snatch.done }}</b>
                / {{ snatch.total }} 台
              </span>
            </div>
            <div class="h-2 overflow-hidden rounded-full bg-line-soft">
              <div
                class="h-full rounded-full transition-all"
                :style="{
                  width: pct + '%',
                  background:
                    task.data.value.status === 'succeeded'
                      ? 'var(--color-ok)'
                      : 'var(--color-accent)',
                }"
              />
            </div>
            <div class="mt-2 text-xs text-ink-3">
              已尝试 {{ task.data.value.runCount }} 次 · 上次运行
              {{ fmtRelative(task.data.value.lastRunAt) }}
            </div>
          </div>
          <div
            v-if="task.data.value.lastError"
            class="mt-4 rounded-md border border-err/30 bg-err/10 px-3 py-2 text-[13px] break-all text-err"
          >
            {{ task.data.value.lastError }}
          </div>
        </div>

        <!-- 事件流 -->
        <div class="panel">
          <div class="flex items-center justify-between border-b border-line-soft px-5 py-3.5">
            <div class="text-sm font-semibold">事件流</div>
            <div class="text-xs text-ink-3">最新事件置顶 · 保留近 100 条</div>
          </div>
          <div class="max-h-[560px] overflow-y-auto px-5.5 pt-4 pb-3">
            <div
              v-for="(log, i) in logs.data.value ?? []"
              :key="log.id"
              class="relative flex gap-3 pb-5 last:pb-1"
            >
              <div
                v-if="i < (logs.data.value?.length ?? 0) - 1"
                class="absolute top-4 bottom-0 left-[5px] w-px bg-line-soft"
              />
              <div
                class="mt-1 h-[11px] w-[11px] flex-none rounded-full border-[2.5px]"
                :style="{
                  borderColor: log.success ? 'var(--color-ok)' : 'var(--color-err)',
                  background: `color-mix(in srgb, ${log.success ? 'var(--color-ok)' : 'var(--color-err)'} 22%, var(--color-card))`,
                }"
              />
              <div class="min-w-0">
                <div class="flex items-center gap-2">
                  <span class="mono text-[11.5px] text-ink-3">{{ fmtTime(log.createdAt) }}</span>
                  <span
                    class="rounded px-1.5 text-[10.5px] font-semibold tracking-wide"
                    :style="{
                      color: log.success ? 'var(--color-ok)' : 'var(--color-err)',
                      background: `color-mix(in srgb, ${log.success ? 'var(--color-ok)' : 'var(--color-err)'} 10%, transparent)`,
                    }"
                  >
                    {{ log.success ? 'SUCCESS' : 'FAILED' }}
                  </span>
                  <span class="mono text-[11.5px] text-ink-3">{{ log.durationMs }}ms</span>
                </div>
                <div class="mono mt-0.5 text-[13px] break-all">{{ log.message }}</div>
              </div>
            </div>
            <EmptyCard
              v-if="logs.data.value && !logs.data.value.length"
              title="暂无事件"
              note="任务执行后事件流会出现在这里"
            />
          </div>
        </div>
      </div>

      <!-- 右栏 -->
      <div class="flex flex-col gap-4">
        <div class="panel">
          <div class="border-b border-line-soft px-5 py-3.5 text-sm font-semibold">任务参数</div>
          <div class="px-5 pt-1 pb-2.5">
            <div
              v-for="[k, v] in params"
              :key="k"
              class="flex items-baseline justify-between gap-3 border-b border-line-soft py-2.5 last:border-b-0"
            >
              <span class="flex-none text-[13px] text-ink-3">{{ k }}</span>
              <span class="mono min-w-0 truncate text-[13px]" :title="v">{{ v }}</span>
            </div>
          </div>
        </div>
        <div class="panel">
          <div class="border-b border-line-soft px-5 py-3.5 text-sm font-semibold">运维特性</div>
          <div class="px-5 py-2">
            <div v-for="[t, d] in features" :key="t" class="flex gap-2.5 py-2.5">
              <svg
                class="mt-0.5 h-[15px] w-[15px] flex-none text-ok"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2.2"
                stroke-linecap="round"
                stroke-linejoin="round"
              >
                <path d="M4 12.5l5 5L20 6.5" />
              </svg>
              <div>
                <div class="text-[13px] font-semibold">{{ t }}</div>
                <div class="mt-0.5 text-xs text-ink-3">{{ d }}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <TaskFormModal v-model:show="showEdit" :task="task.data.value" @created="task.run()" />
  </div>
</template>
