<template>
  <NCard title="自治编排">
    <div class="space-y-3">
      <div class="flex items-center justify-between gap-3">
        <div class="min-w-0">
          <div class="flex items-center gap-2">
            <NTag v-if="activeRun" :type="statusType(activeRun.status)" size="small">
              {{ statusLabel(activeRun.status) }}
            </NTag>
            <NTag v-else size="small" type="default"> 未启动 </NTag>
            <span v-if="activeRun" class="text-xs text-gray-400 font-mono truncate">
              {{ activeRun.id.slice(0, 8) }}
            </span>
          </div>
          <div v-if="activeRun" class="mt-1 text-xs text-gray-500">
            {{ phaseLabel(activeRun.current_phase) }} · {{ formatDateTime(activeRun.updated_at) }}
          </div>
        </div>
        <NButton size="small" quaternary circle :loading="loading" @click="refresh">
          <template #icon>
            <NIcon><RefreshOutline /></NIcon>
          </template>
        </NButton>
      </div>

      <NAlert v-if="activeRun?.last_error" type="warning" size="small" :show-icon="false">
        {{ activeRun.last_error }}
      </NAlert>

      <div class="flex flex-wrap gap-2">
        <NTooltip :disabled="canStart">
          <template #trigger>
            <NButton
              size="small"
              type="primary"
              :disabled="!canStart"
              :loading="acting === 'start'"
              @click="start"
            >
              启动
            </NButton>
          </template>
          需保持需求开放、已关联 workspace，且没有活跃 run
        </NTooltip>
        <NButton size="small" :disabled="!canPause" :loading="acting === 'pause'" @click="pause">
          暂停
        </NButton>
        <NButton size="small" :disabled="!canResume" :loading="acting === 'resume'" @click="resume">
          继续
        </NButton>
        <NButton
          size="small"
          type="error"
          secondary
          :disabled="!canCancel"
          :loading="acting === 'cancel'"
          @click="cancel"
        >
          取消
        </NButton>
      </div>

      <div v-if="runs.length > 1" class="text-xs text-gray-400">历史运行 {{ runs.length }} 次</div>
    </div>
  </NCard>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { NAlert, NButton, NCard, NIcon, NTag, NTooltip, useMessage } from 'naive-ui'
import { RefreshOutline } from '@vicons/ionicons5'

import {
  orchestratorApi,
  type OrchestratorRun,
  type OrchestratorRunStatus,
} from '@/api/orchestrator'
import type { Phase, Requirement } from '@/api/projects'
import { formatDateTime } from '@/utils/date'

const PHASE_LABELS: Record<Phase, string> = {
  planning: '规划中',
  prototyping: '原型设计',
  auditing: '评审中',
  implementing: '实施中',
  reviewing: '验收中',
  done: '已完成',
}

const props = defineProps<{
  slug: string
  requirement: Requirement
}>()

const emit = defineEmits<{ changed: [] }>()

const msg = useMessage()
const runs = ref<OrchestratorRun[]>([])
const loading = ref(false)
const acting = ref<'start' | 'pause' | 'resume' | 'cancel' | ''>('')

const activeRun = computed(() => runs.value[0] ?? null)
const hasActiveRun = computed(() => {
  const status = activeRun.value?.status
  return status === 'pending' || status === 'running' || status === 'paused'
})
const canStart = computed(
  () =>
    props.requirement.status === 'open' && !!props.requirement.workspace_id && !hasActiveRun.value,
)
const canPause = computed(() => ['pending', 'running'].includes(activeRun.value?.status ?? ''))
const canResume = computed(() => activeRun.value?.status === 'paused')
const canCancel = computed(() => hasActiveRun.value)

function phaseLabel(phase: Phase) {
  return PHASE_LABELS[phase] ?? phase
}

function statusLabel(status: OrchestratorRunStatus) {
  switch (status) {
    case 'pending':
      return '等待中'
    case 'running':
      return '运行中'
    case 'paused':
      return '已暂停'
    case 'succeeded':
      return '已成功'
    case 'failed':
      return '失败'
    case 'canceled':
      return '已取消'
    default:
      return status
  }
}

function statusType(
  status: OrchestratorRunStatus,
): 'default' | 'success' | 'warning' | 'error' | 'info' {
  switch (status) {
    case 'running':
      return 'info'
    case 'succeeded':
      return 'success'
    case 'paused':
    case 'pending':
      return 'warning'
    case 'failed':
    case 'canceled':
      return 'error'
    default:
      return 'default'
  }
}

async function refresh() {
  loading.value = true
  try {
    runs.value = await orchestratorApi.listRuns({ requirement_id: props.requirement.id })
  } finally {
    loading.value = false
  }
}

async function withAction(action: typeof acting.value, fn: () => Promise<unknown>) {
  acting.value = action
  try {
    await fn()
    await refresh()
    emit('changed')
  } catch (e: unknown) {
    msg.error(e instanceof Error ? e.message : String(e))
  } finally {
    acting.value = ''
  }
}

async function start() {
  await withAction('start', () =>
    orchestratorApi.startRun({
      project_slug: props.slug,
      requirement_number: props.requirement.number,
    }),
  )
}

async function pause() {
  if (!activeRun.value) return
  await withAction('pause', () => orchestratorApi.pauseRun(activeRun.value!.id))
}

async function resume() {
  if (!activeRun.value) return
  await withAction('resume', () => orchestratorApi.resumeRun(activeRun.value!.id))
}

async function cancel() {
  if (!activeRun.value) return
  await withAction('cancel', () => orchestratorApi.cancelRun(activeRun.value!.id))
}

onMounted(refresh)
watch(() => props.requirement.id, refresh)
</script>
