<template>
  <div class="page-content">
    <div class="mb-5 flex items-center justify-between gap-4">
      <div>
        <h2 class="text-xl font-semibold">节点任务</h2>
        <p class="text-g-500 mt-1 text-sm">向节点池下发任务：节点按池认领执行并上报结果，失败自动退避重试</p>
      </div>
      <div class="flex gap-2">
        <ElSelect v-model="statusFilter" class="w-36" @change="load">
          <ElOption label="全部状态" value="" />
          <ElOption label="排队中" value="queued" />
          <ElOption label="已认领" value="claimed" />
          <ElOption label="进行中" value="running" />
          <ElOption label="成功" value="succeeded" />
          <ElOption label="失败" value="failed" />
          <ElOption label="已取消" value="cancelled" />
        </ElSelect>
        <ElButton type="primary" @click="openDispatch">下发任务</ElButton>
      </div>
    </div>

    <ElTable v-loading="loading" :data="items" row-key="id">
      <ElTableColumn label="状态" width="95">
        <template #default="{ row }"><ElTag :type="statusType(row.status)">{{ statusLabel(row.status) }}</ElTag></template>
      </ElTableColumn>
      <ElTableColumn label="类型" width="120"><template #default="{ row }">{{ typeLabel(row.task_type) }}</template></ElTableColumn>
      <ElTableColumn label="目标" min-width="160">
        <template #default="{ row }">{{ row.node_code || `${row.pool_type === 'public' ? '公有' : '私有'}池 / ${row.pool_code}` }}</template>
      </ElTableColumn>
      <ElTableColumn label="Payload" min-width="220">
        <template #default="{ row }"><code class="text-xs">{{ JSON.stringify(row.payload || {}).slice(0, 80) }}</code></template>
      </ElTableColumn>
      <ElTableColumn label="尝试" width="90"><template #default="{ row }">{{ row.attempts }} / {{ row.max_attempts }}</template></ElTableColumn>
      <ElTableColumn label="结果 / 错误" min-width="200">
        <template #default="{ row }">
          <span v-if="row.error" class="text-danger text-xs">{{ row.error.slice(0, 80) }}</span>
          <code v-else-if="row.result" class="text-xs">{{ JSON.stringify(row.result).slice(0, 80) }}</code>
          <span v-else class="text-g-400 text-xs">—</span>
        </template>
      </ElTableColumn>
      <ElTableColumn prop="created_at" label="创建时间" width="175" />
      <ElTableColumn label="操作" width="140" fixed="right">
        <template #default="{ row }">
          <ElButton v-if="row.status === 'queued'" link type="danger" @click="cancel(row)">取消</ElButton>
          <ElButton v-if="row.status === 'failed'" link type="primary" @click="retry(row)">重试</ElButton>
        </template>
      </ElTableColumn>
    </ElTable>

    <ElDialog v-model="visible" title="下发节点任务" width="620px">
      <ElForm label-width="110px">
        <ElFormItem label="任务类型" required>
          <ElSelect v-model="form.task_type" class="w-full">
            <ElOption label="Prompt 执行" value="prompt" />
            <ElOption label="HTTP 调用" value="http" />
            <ElOption label="MCP 调用" value="mcp_invoke" />
            <ElOption label="Skill 运行" value="skill_run" />
            <ElOption label="数字员工" value="digital_employee" />
            <ElOption label="自定义" value="custom" />
          </ElSelect>
        </ElFormItem>
        <div class="grid grid-cols-2 gap-4">
          <ElFormItem label="节点池">
            <ElSelect v-model="form.pool_type" class="w-full">
              <ElOption label="私有池" value="private" />
              <ElOption label="公有池" value="public" />
            </ElSelect>
          </ElFormItem>
          <ElFormItem label="池编码">
            <ElInput v-model="form.pool_code" maxlength="64" />
          </ElFormItem>
        </div>
        <ElFormItem label="指定节点">
          <ElSelect v-model="form.node_id" clearable filterable class="w-full" placeholder="留空 = 池内任意节点认领">
            <ElOption v-for="node in nodes" :key="node.id" :label="`${node.name} (${node.code})`" :value="node.id" />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="Payload JSON" required>
          <ElInput v-model="payloadJSON" type="textarea" :rows="7" placeholder='{"model":"gpt-4o-mini","messages":[{"role":"user","content":"你好"}]}' />
        </ElFormItem>
        <ElFormItem label="最大尝试">
          <ElInputNumber v-model="form.max_attempts" :min="1" :max="10" />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <ElButton @click="visible = false">取消</ElButton>
        <ElButton type="primary" :loading="saving" @click="submit">下发</ElButton>
      </template>
    </ElDialog>
  </div>
</template>
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import { AgentNode, fetchAgentNodes } from '@/api/agent-nodes'
import { AgentTask, cancelAgentTask, createAgentTask, fetchAgentTasks, retryAgentTask } from '@/api/agent-nodes'

const loading = ref(false)
const saving = ref(false)
const visible = ref(false)
const statusFilter = ref('')
const items = ref<AgentTask[]>([])
const nodes = ref<AgentNode[]>([])
const payloadJSON = ref('{}')
const form = reactive({ task_type: 'prompt', pool_type: 'private', pool_code: 'default', node_id: undefined as string | undefined, max_attempts: 3 })

const statusText: Record<string, string> = { queued: '排队中', claimed: '已认领', running: '进行中', succeeded: '成功', failed: '失败', cancelled: '已取消' }
const statusLabel = (v: string) => statusText[v] || v
const statusType = (v: string) => (({ succeeded: 'success', failed: 'danger', cancelled: 'info', queued: 'warning' } as Record<string, string>)[v] || 'primary') as 'success' | 'danger' | 'info' | 'warning' | 'primary'
const typeLabel = (v: string) => ({ prompt: 'Prompt', http: 'HTTP', mcp_invoke: 'MCP', skill_run: 'Skill', digital_employee: '数字员工', custom: '自定义' }[v] || v)

async function load() {
  loading.value = true
  try {
    items.value = await fetchAgentTasks(statusFilter.value)
  } finally {
    loading.value = false
  }
}

async function openDispatch() {
  nodes.value = await fetchAgentNodes()
  payloadJSON.value = '{}'
  Object.assign(form, { task_type: 'prompt', pool_type: 'private', pool_code: 'default', node_id: undefined, max_attempts: 3 })
  visible.value = true
}

async function submit() {
  let payload: Record<string, unknown>
  try {
    payload = JSON.parse(payloadJSON.value)
  } catch {
    ElMessage.error('Payload 不是合法 JSON')
    return
  }
  saving.value = true
  try {
    await createAgentTask({ task_type: form.task_type, payload, pool_type: form.pool_type, pool_code: form.pool_code, node_id: form.node_id, max_attempts: form.max_attempts })
    ElMessage.success('任务已下发')
    visible.value = false
    await load()
  } catch (error) {
    ElMessage.error((error as Error)?.message || '下发失败')
  } finally {
    saving.value = false
  }
}

async function cancel(row: AgentTask) {
  await ElMessageBox.confirm('取消后节点将无法认领该任务，确定取消？', '取消任务', { type: 'warning' })
  await cancelAgentTask(row.id)
  row.status = 'cancelled'
  ElMessage.success('已取消')
}

async function retry(row: AgentTask) {
  await retryAgentTask(row.id)
  ElMessage.success('已重新入队')
  await load()
}

onMounted(load)
</script>
