<script setup lang="ts">
import { ref, onMounted, h } from 'vue'
import { NDataTable, NButton, NTag, NAlert, NCard, NGrid, NGridItem, NPopover } from 'naive-ui'
import { api } from '../../api/client'
import { useToast } from '../../composables/useToast'

const toast = useToast()
const runs = ref<any[]>([])
const total = ref(0)
const loading = ref(true)

// Action loading states
const running = ref(false)
const refreshingCitations = ref(false)
const extractingPico = ref(false)
const backfillingDesign = ref(false)
const backfillingOA = ref(false)

function fmt(ts: string | null | undefined): string {
  if (!ts) return '—'
  const d = new Date(ts)
  if (isNaN(d.getTime())) return ts
  return d.toLocaleString('zh-CN', {
    timeZone: 'Asia/Shanghai',
    year: 'numeric', month: '2-digit', day: '2-digit',
    hour: '2-digit', minute: '2-digit',
    hour12: false,
  }).replace(/\//g, '-')
}

onMounted(loadData)
async function loadData() {
  loading.value = true
  try {
    const { data } = await api.get('/admin/pipeline/runs', { params: { page_size: 50 } })
    runs.value = data.items || []
    total.value = data.total || 0
  } catch (e) { toast.apiError(e, '加载管道记录失败') }
  finally { loading.value = false }
}

async function triggerPipeline() {
  running.value = true
  try {
    await api.post('/admin/pipeline/run', { params: { mode: 'ftp' } })
    toast.success('FTP 增量管道已触发')
    await loadData()
  } catch (e) { toast.apiError(e, '触发失败') }
  finally { running.value = false }
}
async function refreshCitations() {
  refreshingCitations.value = true
  try { const { data } = await api.post('/admin/pipeline/refresh-citations'); toast.success('引用更新完成: ' + data.updated + ' 篇'); await loadData() }
  catch (e) { toast.apiError(e, '刷新失败') }
  finally { refreshingCitations.value = false }
}
async function extractPico() {
  extractingPico.value = true
  try { const { data } = await api.post('/admin/pipeline/extract-pico'); toast.success('PICO 提取完成: ' + data.processed + ' 篇'); await loadData() }
  catch (e) { toast.apiError(e, '提取失败') }
  finally { extractingPico.value = false }
}
async function backfillDesign() {
  backfillingDesign.value = true
  try { const { data } = await api.post('/admin/pipeline/backfill-study-designs'); toast.success('回填完成: ' + data.updated + ' 篇'); await loadData() }
  catch (e) { toast.apiError(e, '回填失败') }
  finally { backfillingDesign.value = false }
}
async function backfillOA() {
  backfillingOA.value = true
  try { const { data } = await api.post('/admin/pipeline/backfill-oa-text?limit=5000'); toast.success('OA全文回填完成: ' + data.fetched + ' 篇'); await loadData() }
  catch (e) { toast.apiError(e, '回填失败') }
  finally { backfillingOA.value = false }
}

function fmtDuration(started: string | null, completed: string | null): string {
  if (!started || !completed) return '—'
  const s = new Date(started).getTime()
  const e = new Date(completed).getTime()
  if (isNaN(s) || isNaN(e)) return '—'
  const sec = Math.round((e - s) / 1000)
  if (sec < 60) return sec + '秒'
  return Math.floor(sec / 60) + '分' + (sec % 60) + '秒'
}

const typeLabels: Record<string, string> = {
  daily_ftp_update: '📡 FTP 增量',
  daily_pubmed_pipeline: '🔍 精搜(旧)',
  weekly_broad_pipeline: '🌐 宽搜(旧)',
  daily_mesh_retagger: '🏷️ Retagger(旧)',
  baseline_import: '📦 基线导入',
  manual_full: '⚡ 手动全量',
  manual_majr: '⚡ 手动精搜',
  manual_broad: '⚡ 手动宽搜',
  manual_full_epmc: '⚡ EPMC 全量',
  daily_citation_update: '📊 引用刷新',
}

const cols = [
  {
    title: '类型', key: 'type', width: 110, fixed: 'left' as const,
    render: (r: any) => h(NTag, { size: 'tiny', type: r.type === 'daily_ftp_update' ? 'success' : 'default' },
      () => typeLabels[r.type] || r.type),
  },
  {
    title: '状态', key: 'status', width: 60,
    render: (r: any) => h(NTag, { size: 'tiny', type: r.status === 'success' ? 'success' : 'error' },
      () => r.status === 'success' ? '✅' : '❌'),
  },
  { title: '开始', key: 'started', width: 130, render: (r: any) => fmt(r.started) },
  { title: '完成', key: 'completed', width: 130, render: (r: any) => fmt(r.completed) },
  {
    title: '耗时', key: 'duration', width: 70,
    render: (r: any) => fmtDuration(r.started, r.completed),
  },
  { title: '文件数', key: 'files_processed', width: 60 },
  { title: '总文献', key: 'total_articles', width: 60 },
  { title: '➕新增', key: 'articles_new', width: 60 },
  { title: '🔄更新', key: 'articles_updated', width: 60 },
  { title: '🗑️删除', key: 'articles_deleted', width: 60 },
  { title: '🚫过滤', key: 'articles_filtered', width: 60 },
  { title: '📨Feed', key: 'feeds_generated', width: 60 },
  {
    title: '检查点', key: 'processed_date', width: 90,
    render: (r: any) => r.processed_date || '—',
  },
  {
    title: '元数据', key: 'metadata', width: 140, ellipsis: true,
    render: (r: any) => {
      if (!r.metadata) return '—'
      const parts: string[] = []
      if (r.metadata.ftp_year) parts.push('年份:' + r.metadata.ftp_year)
      if (r.metadata.last_sequence) parts.push('序号:' + r.metadata.last_sequence)
      if (r.metadata.year) parts.push('基线:' + r.metadata.year)
      return parts.join(' ')
    },
  },
  {
    title: '错误', key: 'error', width: 100, ellipsis: true,
    render: (r: any) => {
      if (!r.error) return '—'
      return h(NPopover, { trigger: 'hover' }, () => h('pre', { style: 'max-width:400px;font-size:12px;white-space:pre-wrap;margin:0' }, r.error))
    },
  },
]
const scrollX = 1350
</script>

<template>
  <div class="pipeline-view">
    <div class="header-row">
      <div class="header-left">
        <h2>📡 数据管道</h2>
        <span class="total-badge">共 {{ total }} 次运行</span>
      </div>
      <NButton type="primary" :loading="running" @click="triggerPipeline" class="sky-btn">🔄 FTP 增量更新</NButton>
    </div>

    <NAlert type="info" style="margin-bottom:16px" title="管道架构（FTP 每日增量）">
      <div style="font-size:13px;line-height:1.8">
        • 🟢 默认管道：每天 03:07 UTC FTP 下载当日更新文件 → 解析 → 过滤 → upsert<br>
        • 2026-07-25 已从 E-utilities API 多路搜索切换为 FTP 每日更新文件<br>
        • 旧管道（精搜 MAJR / 宽搜 / retagger）标记为 @deprecated，仅保留兼容
      </div>
    </NAlert>

    <!-- Action cards -->
    <n-grid :cols="4" :x-gap="12" responsive="screen" style="margin-bottom:20px">
      <n-grid-item>
        <NCard size="small" style="text-align:center">
          <div style="font-size:12px;color:var(--text-secondary);margin-bottom:8px">📊 刷新被引次数</div>
          <NButton size="tiny" :loading="refreshingCitations" @click="refreshCitations" class="sky-btn">执行</NButton>
        </NCard>
      </n-grid-item>
      <n-grid-item>
        <NCard size="small" style="text-align:center">
          <div style="font-size:12px;color:var(--text-secondary);margin-bottom:8px">📝 PICO 提取</div>
          <NButton size="tiny" :loading="extractingPico" @click="extractPico" class="sky-btn">执行</NButton>
        </NCard>
      </n-grid-item>
      <n-grid-item>
        <NCard size="small" style="text-align:center">
          <div style="font-size:12px;color:var(--text-secondary);margin-bottom:8px">🏗️ 研究设计回填</div>
          <NButton size="tiny" :loading="backfillingDesign" @click="backfillDesign" class="sky-btn">执行</NButton>
        </NCard>
      </n-grid-item>
      <n-grid-item>
        <NCard size="small" style="text-align:center">
          <div style="font-size:12px;color:var(--text-secondary);margin-bottom:8px">📄 OA 全文回填</div>
          <NButton size="tiny" :loading="backfillingOA" @click="backfillOA" class="sky-btn">执行</NButton>
        </NCard>
      </n-grid-item>
    </n-grid>

    <!-- Run history table -->
    <NCard title="运行历史" size="small">
      <NDataTable
        :columns="cols"
        :data="runs"
        :loading="loading"
        size="small"
        :bordered="false"
        :max-height="600"
        :scroll-x="scrollX"
        :single-line="false"
      />
    </NCard>
  </div>
</template>

<style scoped>
.pipeline-view {
  padding: 16px;
}
.header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}
.header-left {
  display: flex;
  align-items: center;
  gap: 12px;
}
.header-left h2 {
  margin: 0;
  white-space: nowrap;
}
.total-badge {
  font-size: 12px;
  color: var(--text-secondary);
  background: var(--border-color);
  padding: 2px 8px;
  border-radius: 10px;
}
@media (max-width: 768px) {
  .pipeline-view { padding: 12px; }
  .header-row { flex-direction: column; align-items: flex-start; gap: 8px; }
  .n-grid { grid-template-columns: 1fr 1fr; }
}
</style>