<template>
  <div class="store-page">
    <Breadcrumb />

    <a-card title="队列概览" class="card-block">
      <template #extra>
        <a-space>
          <span class="muted" v-if="summaryFetchedAt">更新于 {{ formatTime(summaryFetchedAt) }}</span>
          <span class="muted">自动刷新</span>
          <a-switch v-model="autoRefresh" type="round" />
          <a-select v-model="refreshIntervalSec" :style="{ width: '110px' }" :disabled="!autoRefresh">
            <a-option :value="3">每 3 秒</a-option>
            <a-option :value="5">每 5 秒</a-option>
            <a-option :value="10">每 10 秒</a-option>
            <a-option :value="30">每 30 秒</a-option>
          </a-select>
          <a-button type="primary" :loading="summaryLoading" @click="loadSummary">
            <template #icon><icon-refresh /></template>
            刷新概览
          </a-button>
        </a-space>
      </template>

      <a-table
        :data="summaryRows"
        :loading="summaryLoading"
        :pagination="false"
        :bordered="false"
        row-key="name"
        class="table"
      >
        <template #columns>
          <a-table-column title="队列名称" data-index="name" :width="260" ellipsis tooltip />
          <a-table-column title="待处理消息数" data-index="messageCount" :width="140">
            <template #cell="{ record }">
              <span v-if="record.messageCount != null">{{ record.messageCount }}</span>
              <span v-else class="muted">—</span>
            </template>
          </a-table-column>
          <a-table-column title="消费者数" data-index="consumerCount" :width="120">
            <template #cell="{ record }">
              <span v-if="record.consumerCount != null">{{ record.consumerCount }}</span>
              <span v-else class="muted">—</span>
            </template>
          </a-table-column>
          <a-table-column title="说明" data-index="error">
            <template #cell="{ record }">
              <a-typography-text v-if="record.error" type="danger">{{ record.error }}</a-typography-text>
              <span v-else class="muted">正常</span>
            </template>
          </a-table-column>
        </template>
      </a-table>
    </a-card>

    <a-card title="队列消息窥视（reject_requeue_true，不消费）" class="card-block">
      <AppQueryFilter label="窥视条件">
      <a-row :gutter="16" align="center" class="query-row app-query-form">
        <a-col :span="6">
          <a-form-item label="队列" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
            <a-select v-model="peekForm.queue" placeholder="选择队列">
              <a-option v-for="q in ALLOWED_QUEUES" :key="q" :value="q">{{ q }}</a-option>
            </a-select>
          </a-form-item>
        </a-col>
        <a-col :span="5">
          <a-form-item label="条数" :label-col-props="{ span: 8 }" :wrapper-col-props="{ span: 16 }">
            <a-input-number v-model="peekForm.limit" :min="1" :max="100" mode="button" />
          </a-form-item>
        </a-col>
        <a-col :span="13">
          <a-space>
            <a-button type="primary" :loading="peekLoading" @click="loadPeek">
              <template #icon><icon-unordered-list /></template>
              拉取窥视
            </a-button>
            <span v-if="peekMeta.messageCount != null" class="meta">
              队列深度：{{ peekMeta.messageCount }}，消费者：{{ peekMeta.consumerCount ?? '—' }}，本次条数：{{ peekMeta.peekLimit ?? '—' }}
            </span>
            <span v-if="peekFetchedAt" class="muted">更新于 {{ formatTime(peekFetchedAt) }}</span>
          </a-space>
        </a-col>
      </a-row>
      </AppQueryFilter>

      <a-alert v-if="peekMeta.managementError" type="warning" style="margin-bottom: 12px">
        {{ peekMeta.managementError }}
      </a-alert>

      <a-table
        :data="peekTasks"
        :loading="peekLoading"
        :pagination="false"
        :bordered="false"
        row-key="__key"
        :scroll="{ x: 1200 }"
        class="table"
      >
        <template #columns>
          <a-table-column title="再投递" data-index="redelivered" :width="88">
            <template #cell="{ record }">
              <a-tag v-if="record.redelivered" color="orange">是</a-tag>
              <a-tag v-else color="green">否</a-tag>
            </template>
          </a-table-column>
          <a-table-column title="路由键" data-index="routing_key" :width="160" ellipsis tooltip />
          <a-table-column title="交换机" data-index="exchange" :width="140" ellipsis tooltip />
          <a-table-column title="MessageId" :width="180" ellipsis tooltip>
            <template #cell="{ record }">
              {{ record.properties?.messageId ?? '—' }}
            </template>
          </a-table-column>
          <a-table-column title="时间戳" :width="160">
            <template #cell="{ record }">
              {{ record.properties?.timestamp != null ? String(record.properties.timestamp) : '—' }}
            </template>
          </a-table-column>
          <a-table-column title="负载摘要" data-index="payload">
            <template #cell="{ record }">
              <span class="payload-preview">{{ payloadPreview(record.payload) }}</span>
              <a-button type="text" size="small" @click="openPayloadModal(record)">完整 JSON</a-button>
            </template>
          </a-table-column>
        </template>
      </a-table>
    </a-card>

    <a-modal v-model:visible="payloadVisible" title="消息负载" width="800px" :footer="false" draggable>
      <pre class="json-pre">{{ payloadModalText }}</pre>
    </a-modal>
  </div>
</template>

<script setup>
import { ref, reactive, watch, onMounted, onUnmounted } from 'vue'
import { adminGetQueueTasks } from '@/api/mq'
import { Notification } from '@arco-design/web-vue'

/** 与后端 ALLOWED_QUEUES 保持一致，用于下拉与展示 */
const ALLOWED_QUEUES = [
  'runforge_task_queue',
  'runforge_task_result_queue',
  'runforge_task_dead_queue',
  'runforge_message_queue',
  'order_payment_check',
  'mq_health_check'
]

const summaryLoading = ref(false)
const summaryRows = ref([])
const summaryFetchedAt = ref(null)

const peekLoading = ref(false)
const peekTasks = ref([])
const peekFetchedAt = ref(null)
const peekMeta = reactive({
  messageCount: null,
  consumerCount: null,
  peekLimit: null,
  managementError: null
})

const peekForm = reactive({
  queue: 'runforge_task_queue',
  limit: 30
})

const autoRefresh = ref(false)
const refreshIntervalSec = ref(5)
let pollTimer = null

const payloadVisible = ref(false)
const payloadModalText = ref('')

const formatTime = (ts) => {
  if (ts == null) return ''
  return new Date(ts).toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  })
}

const payloadPreview = (payload) => {
  if (payload == null) return '—'
  const s = typeof payload === 'string' ? payload : JSON.stringify(payload)
  return s.length > 100 ? `${s.slice(0, 100)}…` : s
}

const openPayloadModal = (record) => {
  try {
    payloadModalText.value =
      typeof record.payload === 'string'
        ? record.payload
        : JSON.stringify(record.payload, null, 2)
  } catch {
    payloadModalText.value = String(record.payload)
  }
  payloadVisible.value = true
}

const loadSummary = async (silent = false) => {
  if (!silent) summaryLoading.value = true
  try {
    const res = await adminGetQueueTasks({ summary: '1' })
    if (!res || res.code !== 0) {
      Notification.error({
        title: '获取队列概览失败',
        content: res?.msg ?? '请稍后再试'
      })
      return
    }
    const queues = res.data?.queues || {}
    summaryRows.value = ALLOWED_QUEUES.map((name) => {
      const info = queues[name] || {}
      return {
        name,
        messageCount: info.messageCount ?? null,
        consumerCount: info.consumerCount ?? null,
        error: info.error
      }
    })
    summaryFetchedAt.value = res.data?.fetchedAt ?? Date.now()
  } catch (e) {
    Notification.error({
      title: '获取队列概览失败',
      content: e.message || '请稍后再试'
    })
  } finally {
    if (!silent) summaryLoading.value = false
  }
}

const loadPeek = async (silent = false) => {
  if (!silent) peekLoading.value = true
  try {
    const res = await adminGetQueueTasks({
      queue: peekForm.queue,
      limit: peekForm.limit
    })
    if (!res || res.code !== 0) {
      Notification.error({
        title: '窥视队列失败',
        content: res?.msg ?? '请稍后再试'
      })
      return
    }
    const d = res.data || {}
    peekMeta.messageCount = d.messageCount ?? null
    peekMeta.consumerCount = d.consumerCount ?? null
    peekMeta.peekLimit = d.peekLimit ?? null
    peekMeta.managementError = d.managementError || null
    peekFetchedAt.value = d.fetchedAt ?? Date.now()
    const list = Array.isArray(d.tasks) ? d.tasks : []
    peekTasks.value = list.map((row, i) => ({
      ...row,
      __key: `${peekForm.queue}-${peekFetchedAt.value}-${i}`
    }))
  } catch (e) {
    Notification.error({
      title: '窥视队列失败',
      content: e.message || '请稍后再试'
    })
  } finally {
    if (!silent) peekLoading.value = false
  }
}

const refreshAll = (silent = false) => {
  loadSummary(silent)
  loadPeek(silent)
}

const clearPoll = () => {
  if (pollTimer) {
    clearInterval(pollTimer)
    pollTimer = null
  }
}

const setupPoll = () => {
  clearPoll()
  if (!autoRefresh.value) return
  pollTimer = setInterval(() => {
    refreshAll(true)
  }, refreshIntervalSec.value * 1000)
}

watch([autoRefresh, refreshIntervalSec], () => {
  setupPoll()
  if (autoRefresh.value) refreshAll(true)
})

onMounted(() => {
  refreshAll(false)
  setupPoll()
})

onUnmounted(() => {
  clearPoll()
})
</script>

<style scoped>
.card-block {
  margin-bottom: 16px;
}

.table {
  margin-top: 8px;
}

.muted {
  color: var(--color-text-3);
  font-size: 13px;
}

.meta {
  font-size: 13px;
  color: var(--color-text-2);
}

.payload-preview {
  display: inline-block;
  max-width: 360px;
  margin-right: 8px;
  vertical-align: middle;
  color: var(--color-text-2);
  font-size: 13px;
  word-break: break-all;
}

.json-pre {
  margin: 0;
  max-height: 480px;
  overflow: auto;
  padding: 12px;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
  background: var(--color-fill-2);
  border-radius: var(--border-radius-medium);
}
</style>
