<template>
  <div class="space-y-3">
    <div class="flex items-center justify-between">
      <span class="text-sm text-gray-500">在 main 工作区托管启动的运行档</span>
      <NButton
        type="primary"
        size="small"
        @click="openCreate"
      >
        新建运行档
      </NButton>
    </div>

    <NDataTable
      :columns="columns"
      :data="store.profiles"
      :loading="store.loading"
      :row-key="(row: RunProfile) => row.id"
      size="small"
    />

    <div v-if="selectedId">
      <RunLogViewer
        :key="selectedId"
        :profile-id="selectedId"
      />
    </div>

    <RunProfileDialog
      v-if="dialogOpen"
      :ws-id="ws.id"
      :profile="editing"
      @close="dialogOpen = false"
      @saved="onSaved"
    />
  </div>
</template>

<script setup lang="ts">
import { h, onMounted, ref } from 'vue'
import {
  NButton,
  NDataTable,
  NSpace,
  NTag,
  useMessage,
  useDialog,
  type DataTableColumns,
} from 'naive-ui'
import { ApiException } from '@/api/types'
import type { Workspace } from '@/api/types'
import { useRunsStore } from '@/stores/runs'
import type { RunProfile, RunState } from '@/api/runs'
import RunProfileDialog from './RunProfileDialog.vue'
import RunLogViewer from './RunLogViewer.vue'

const props = defineProps<{ ws: Workspace }>()
const store = useRunsStore()
const msg = useMessage()
const dialog = useDialog()

const selectedId = ref<string | null>(null)
const dialogOpen = ref(false)
const editing = ref<RunProfile | null>(null)

onMounted(() => {
  store.fetch(props.ws.id).catch((e: unknown) => msg.error('加载运行档失败：' + errText(e)))
})

function errText(e: unknown): string {
  return e instanceof ApiException ? e.body.message : e instanceof Error ? e.message : String(e)
}

const tagType: Record<RunState, 'success' | 'default' | 'error'> = {
  running: 'success',
  stopped: 'default',
  crashed: 'error',
}

function openCreate() {
  editing.value = null
  dialogOpen.value = true
}
function openEdit(p: RunProfile) {
  editing.value = p
  dialogOpen.value = true
}
function onSaved() {
  dialogOpen.value = false
}

async function act(fn: () => Promise<unknown>, ok: string) {
  try {
    await fn()
    msg.success(ok)
  } catch (e: unknown) {
    msg.error(errText(e))
  }
}

function confirmDelete(p: RunProfile) {
  dialog.warning({
    title: '删除运行档',
    content: `确定删除「${p.name}」？运行中的进程会被先停止。`,
    positiveText: '删除',
    negativeText: '取消',
    onPositiveClick: async () => {
      await act(() => store.remove(p.id), '已删除')
      if (selectedId.value === p.id) selectedId.value = null
    },
  })
}

const columns: DataTableColumns<RunProfile> = [
  { title: '名称', key: 'name' },
  { title: 'Slug', key: 'slug' },
  { title: '命令', key: 'command', ellipsis: { tooltip: true } },
  {
    title: '状态',
    key: 'status',
    render: (row) =>
      h(NTag, { type: tagType[row.status], size: 'small' }, { default: () => row.status }),
  },
  {
    title: '操作',
    key: 'actions',
    render: (row) =>
      h(NSpace, { size: 'small' }, () => [
        row.status === 'running'
          ? h(
              NButton,
              { size: 'tiny', onClick: () => act(() => store.stop(row.id), '已停止') },
              () => '停止',
            )
          : h(
              NButton,
              {
                size: 'tiny',
                type: 'primary',
                disabled: !row.enabled,
                onClick: () => act(() => store.start(row.id), '已启动'),
              },
              () => '启动',
            ),
        h(
          NButton,
          { size: 'tiny', onClick: () => act(() => store.restart(row.id), '已重启') },
          () => '重启',
        ),
        h(NButton, { size: 'tiny', onClick: () => (selectedId.value = row.id) }, () => '日志'),
        h(NButton, { size: 'tiny', onClick: () => openEdit(row) }, () => '编辑'),
        h(
          NButton,
          { size: 'tiny', type: 'error', onClick: () => confirmDelete(row) },
          () => '删除',
        ),
      ]),
  },
]
</script>
