<script lang="ts" setup>
/**
 * 队列任务列表（业务/基础设施共用）
 * 支持详情、取消、重跑；点标题看操作记录；业务队列可筛普通/延迟
 */
import { onMounted } from 'vue';
import { useRoute } from 'vue-router';

import { Page, useVbenModal } from '@vben/common-ui';

import { message, Modal, Tag } from 'ant-design-vue';

import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction } from '#/components/table-action';

import {
  cancelQueueJob,
  getQueueJobNameOption,
  getQueueJobStatusOption,
  retryQueueJob,
} from '../api';
import {
  QUEUE_JOB_CATEGORY,
  formatDelaySeconds,
  statusTagColor,
} from '../config/constants';
import { createFormOptions } from '../config/search';
import { createGridOptions } from '../config/table';
import DetailModal from './detail-modal.vue';
import OpLogModal from './op-log-modal.vue';

const props = defineProps<{
  /** 1 业务 2 基础设施 */
  category: number;
  /** 页面标题 */
  title: string;
}>();

const route = useRoute();
const isBusiness = props.category === QUEUE_JOB_CATEGORY.BUSINESS;
const formOptions = createFormOptions({ showDelayFilter: isBusiness });
const gridOptions = createGridOptions(props.category);

const [Grid, gridApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
});

const [DetailModalComp, detailModalApi] = useVbenModal({
  connectedComponent: DetailModal,
});

const [OpLogModalComp, opLogModalApi] = useVbenModal({
  connectedComponent: OpLogModal,
});

function openDetail(row: Record<string, any>) {
  detailModalApi.setData({
    id: Number(row?.id || 0),
    values: row,
    onRetried: () => gridApi.query(),
  });
  detailModalApi.open();
}

/**
 * 点标题查看取消/重跑操作记录
 */
function openOpLog(row: Record<string, any>) {
  opLogModalApi.setData({
    id: Number(row?.id || 0),
    title: String(row?.title || ''),
  });
  opLogModalApi.open();
}

function previewError(msg: unknown) {
  try {
    const s = typeof msg === 'string' ? msg : JSON.stringify(msg);
    if (!s) return '-';
    return s.length > 80 ? `${s.slice(0, 80)}…` : s;
  } catch {
    return '-';
  }
}

/**
 * 取消：仅排队中(status=0)
 */
function onCancel(row: Record<string, any>) {
  Modal.confirm({
    title: '确认取消该任务？',
    content: `任务 #${row.id}「${row.title || ''}」将被标记为已取消，worker 取到后不再执行。`,
    onOk: async () => {
      await cancelQueueJob(Number(row.id));
      message.success('已取消');
      gridApi.query();
    },
  });
}

/**
 * 重跑：失败(3)/取消(4)，有副作用风险需二次确认
 */
function onRetry(row: Record<string, any>) {
  Modal.confirm({
    title: '确认重新执行？',
    content:
      `将基于 #${row.id} 新建一条任务并重新投递。` +
      '订单/退款等业务重跑可能产生副作用，请确认业务幂等后再操作。',
    okType: 'danger',
    onOk: async () => {
      const res = await retryQueueJob(Number(row.id));
      const newId = res?.id ?? res?.data?.id;
      message.success(newId ? `已重新投递，新任务 #${newId}` : '已重新投递');
      gridApi.query();
    },
  });
}

function buildActions(row: Record<string, any>) {
  const status = Number(row.status);
  const actions: any[] = [
    {
      label: '详情',
      type: 'link',
      size: 'small',
      onClick: () => openDetail(row),
    },
  ];
  if (status === 0) {
    actions.push({
      label: '取消',
      type: 'link',
      size: 'small',
      onClick: () => onCancel(row),
    });
  }
  if (status === 3 || status === 4) {
    actions.push({
      label: '重跑',
      type: 'link',
      size: 'small',
      onClick: () => onRetry(row),
    });
  }
  return actions;
}

onMounted(async () => {
  try {
    const [statusOpts, jobOpts] = await Promise.all([
      getQueueJobStatusOption(),
      getQueueJobNameOption(props.category),
    ]);
    const statusOptions = Array.isArray(statusOpts)
      ? statusOpts
      : statusOpts?.data || [];
    const jobOptions = Array.isArray(jobOpts) ? jobOpts : jobOpts?.data || [];
    gridApi.formApi?.updateSchema?.([
      {
        fieldName: 'status',
        componentProps: {
          allowClear: true,
          options: statusOptions,
          placeholder: '全部',
        },
      },
      {
        fieldName: 'job_name',
        componentProps: {
          allowClear: true,
          options: jobOptions,
          placeholder: '全部',
          showSearch: true,
          optionFilterProp: 'label',
        },
      },
    ]);
    // 监控页跳转可带 ?status=3 预填筛选
    const qStatus = route.query.status;
    if (qStatus !== undefined && qStatus !== null && qStatus !== '') {
      await gridApi.formApi?.setValues?.({ status: Number(qStatus) });
      gridApi.reload?.();
    }
  } catch {
    // 接口失败时沿用 constants 兜底
  }
});
</script>

<template>
  <Page auto-content-height :title="title">
    <DetailModalComp />
    <OpLogModalComp />
    <Grid>
      <template #toolbar-actions />
      <template #title="{ row }">
        <a
          class="cursor-pointer text-primary"
          title="查看操作记录"
          @click.prevent="openOpLog(row)"
        >
          {{ row.title || '-' }}
        </a>
      </template>
      <template #delay_type="{ row }">
        <Tag :color="Number(row.is_delayed) === 1 ? 'purple' : 'default'">
          {{ row.delay_type_txt || (Number(row.is_delayed) === 1 ? '延迟' : '普通') }}
        </Tag>
      </template>
      <template #status="{ row }">
        <Tag :color="statusTagColor(Number(row.status))">
          {{ row.status_txt || row.status }}
        </Tag>
      </template>
      <template #error="{ row }">
        <span class="text-xs text-gray-600">{{
          previewError(row.error_message)
        }}</span>
      </template>
      <template #available_at="{ row }">
        <div>
          <div>{{ row.available_at || row.created_at || '-' }}</div>
          <Tag
            v-if="Number(row.is_delayed) === 1"
            color="purple"
            class="mt-1"
          >
            延迟
            {{
              Number(row.delay_seconds) > 0
                ? formatDelaySeconds(Number(row.delay_seconds))
                : ''
            }}
          </Tag>
        </div>
      </template>
      <template #action="{ row }">
        <TableAction :actions="buildActions(row)" />
      </template>
    </Grid>
  </Page>
</template>
