<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import {
  NCard, NSpace, NTag, NText, NSelect, NInput, NButton, NEmpty, NSkeleton, NSpin,
  NPagination,
} from 'naive-ui'
import { articlesApi, sourcesApi, type ArticleListItem, type Source } from '@/api/articles'
import { useAuthStore } from '@/stores/auth'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import 'dayjs/locale/zh-cn'
dayjs.extend(relativeTime)
dayjs.locale('zh-cn')

const router = useRouter()
const auth = useAuthStore()
const items = ref<ArticleListItem[]>([])
const sources = ref<Source[]>([])
const loading = ref(false)

// === 页码分页(替代原来的 cursor 无限滚动)===
const page = ref(1)
const pageSize = ref(50)
const total = ref(0)
const totalPages = ref(1)

const sourceFilter = ref<string[]>([])
const q = ref('')

const sourceOptions = ref<{ label: string; value: string }[]>([])

async function load() {
  if (loading.value) return
  loading.value = true
  try {
    const resp = await articlesApi.list({
      source: sourceFilter.value.join(',') || undefined,
      q: q.value || undefined,
      page: page.value,
      page_size: pageSize.value,
    })
    items.value = resp.items
    total.value = resp.total
    totalPages.value = resp.total_pages
  } finally {
    loading.value = false
  }
}

async function loadSources() {
  sources.value = await sourcesApi.list()
  sourceOptions.value = sources.value.map((s) => ({ label: s.name, value: s.slug }))
}

// 切页 → 重新加载 + 滚到顶部
function onPageChange(p: number) {
  page.value = p
  load()
  window.scrollTo({ top: 0, behavior: 'smooth' })
}

// 筛选/搜索变化 → 回到第 1 页
function resetToFirstPage() {
  page.value = 1
  load()
}

function open(a: ArticleListItem) {
  router.push(`/article/${a.id}`)
}

function star(a: ArticleListItem) {
  a.is_starred = !a.is_starred
}

function fmtTime(s?: string | null) {
  if (!s) return '—'
  return dayjs(s).fromNow()
}

// category 是逗号分隔字符串(LLM 输出),拆成多个 tag
function splitCategory(c?: string | null): string[] {
  if (!c) return []
  return c.split(',').map((s) => s.trim()).filter(Boolean)
}

// 评论预览:长文截断
function previewCommentary(c?: string | null, max = 120): string {
  if (!c) return ''
  const trimmed = c.replace(/\s+/g, ' ').trim()
  return trimmed.length > max ? trimmed.slice(0, max) + '…' : trimmed
}

function commentaryStatusType(s?: string | null): 'success' | 'warning' | 'error' | 'default' {
  if (s === 'ok') return 'success'
  if (s === 'failed') return 'error'
  if (s === 'pending') return 'warning'
  return 'default'
}

// === 评论三态语义 ===
// status 'ok' + 有内容 → 显示评论
// status 'ok' + 无内容 → 视为等待(防御性,正常不会触发)
// status 'pending' / 'n/a' / null → 等待中
// status 'failed' → 显示失败提示
type CommentaryState = 'ok' | 'waiting' | 'failed'
function commentaryState(status?: string | null, content?: string | null): CommentaryState {
  if (status === 'failed') return 'failed'
  if (status === 'ok' && content) return 'ok'
  return 'waiting'
}

// 正文摘要(取 body_zh_text 前 N 字;没有就 fallback 到 summary_zh)
function bodyExcerpt(text?: string | null, max = 200): string {
  if (!text) return ''
  const trimmed = text.replace(/\s+/g, ' ').trim()
  return trimmed.length > max ? trimmed.slice(0, max) + '…' : trimmed
}

const itemsLabel = computed(() => `共 ${total.value} 条`)

onMounted(async () => {
  await loadSources()
  await load()
})
</script>

<template>
  <NSpace vertical :size="16">
    <NSpace align="center" justify="space-between" :wrap="true" :size="[10, 10]" class="feed-toolbar">
      <NSpace :size="10" :wrap="true" class="feed-toolbar-left">
        <NSelect
          v-model:value="sourceFilter"
          multiple
          clearable
          placeholder="按源筛选"
          :options="sourceOptions"
          class="feed-source-select"
          @update:value="resetToFirstPage"
        />
        <NInput v-model:value="q" placeholder="关键词搜索" clearable class="feed-search-input"
                @keyup.enter="resetToFirstPage" @clear="resetToFirstPage" />
        <NButton type="primary" @click="resetToFirstPage" round>刷新</NButton>
      </NSpace>
      <NText :depth="3" style="font-size: 13px" class="feed-count-label">{{ itemsLabel }}</NText>
    </NSpace>

    <NSpin :show="loading && items.length === 0">
      <NSkeleton v-if="loading && items.length === 0" :repeat="4" />
      <NEmpty v-else-if="items.length === 0 && !loading" description="暂无新闻" />
      <div v-else>
        <NCard
          v-for="a in items"
          :key="a.id"
          class="article-card"
          hoverable
          @click="open(a)"
        >
          <NSpace vertical :size="10">
            <!-- 顶行:源 / 语言 / 分类 tag / 时间 -->
            <NSpace align="center" :size="6" :wrap="true" style="row-gap: 6px">
              <NTag size="small" type="primary" :bordered="false" round>
                {{ a.source.name }}
              </NTag>
              <NTag v-if="a.lang_src" size="small" round :bordered="false">
                {{ a.lang_src.toUpperCase() }}
              </NTag>
              <NTag v-if="a.translation_status !== 'ok'" size="small" type="warning" :bordered="false" round>
                {{ a.translation_status }}
              </NTag>
              <NTag
                v-for="c in splitCategory(a.category)"
                :key="c"
                size="small"
                type="success"
                :bordered="false"
                round
              >
                {{ c }}
              </NTag>
              <NText :depth="3" style="font-size: 12px; margin-left: auto" class="feed-time-label">
                {{ fmtTime(a.published_at || a.fetched_at) }}
              </NText>
            </NSpace>

            <!-- 中文标题(主) -->
            <div
              v-if="a.title_zh"
              style="
                font-family: var(--font-serif);
                font-size: 20px;
                font-weight: 700;
                color: var(--color-letter);
                line-height: 1.4;
              "
            >
              {{ a.title_zh }}
            </div>

            <!-- 原标题(灰色,辅助) -->
            <div
              v-if="a.title"
              style="font-size: 13px; color: var(--color-text-faint); line-height: 1.4;"
            >
              {{ a.title }}
            </div>

            <!-- AI 插图(若有) -->
            <img
              v-if="a.image_ai_url || a.image_url"
              :src="a.image_ai_url || a.image_url || ''"
              style="
                display: block;
                width: 100%;
                max-height: 280px;
                object-fit: cover;
                border-radius: 8px;
                margin: 4px 0;
                background: var(--color-surface-variant);
              "
              referrerpolicy="no-referrer"
              loading="lazy"
            />

            <!-- 翻译后正文摘要 -->
            <div
              v-if="a.body_zh_text || a.summary_zh"
              style="
                margin-top: 4px;
                color: var(--color-letter);
                font-size: 14px;
                line-height: 1.75;
              "
            >
              {{ bodyExcerpt(a.body_zh_text || a.summary_zh, 220) }}
            </div>

            <!-- 评论钩子(双 provider:Angel + 美团,三态显式显示:有内容 / 等待中 / 失败) -->
            <div class="commentary-stack">
              <!-- Angel 评论 -->
              <div
                class="commentary-item"
                :class="{
                  'commentary-item-waiting': commentaryState(a.commentary_status, a.commentary) === 'waiting',
                  'commentary-item-failed': commentaryState(a.commentary_status, a.commentary) === 'failed',
                  'commentary-item-ok': commentaryState(a.commentary_status, a.commentary) === 'ok',
                }"
              >
                <div class="commentary-head">
                  <span class="commentary-label">💬 Angel 评论</span>
                  <span
                    class="commentary-badge"
                    :class="`commentary-badge-${commentaryState(a.commentary_status, a.commentary)}`"
                  >
                    <span
                      v-if="commentaryState(a.commentary_status, a.commentary) === 'waiting'"
                      class="commentary-spinner"
                    />
                    {{
                      commentaryState(a.commentary_status, a.commentary) === 'ok' ? '已生成'
                      : commentaryState(a.commentary_status, a.commentary) === 'failed' ? '失败'
                      : '生成中'
                    }}
                  </span>
                </div>
                <div
                  v-if="commentaryState(a.commentary_status, a.commentary) === 'ok'"
                  class="commentary-text"
                >{{ previewCommentary(a.commentary, 140) }}</div>
                <div v-else-if="commentaryState(a.commentary_status, a.commentary) === 'failed'" class="commentary-text commentary-text-failed">
                  评论生成失败,后台 enrichment_loop 会重试
                </div>
                <div v-else class="commentary-text commentary-text-waiting">
                  正在生成评论…
                </div>
              </div>
              <!-- 美团评论 -->
              <div
                class="commentary-item"
                :class="{
                  'commentary-item-waiting': commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'waiting',
                  'commentary-item-failed': commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'failed',
                  'commentary-item-ok': commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'ok',
                }"
              >
                <div class="commentary-head">
                  <span class="commentary-label commentary-label-meituan">🐱 美团评论</span>
                  <span
                    class="commentary-badge"
                    :class="`commentary-badge-${commentaryState(a.commentary_meituan_status, a.commentary_meituan)}`"
                  >
                    <span
                      v-if="commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'waiting'"
                      class="commentary-spinner"
                    />
                    {{
                      commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'ok' ? '已生成'
                      : commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'failed' ? '失败'
                      : '生成中'
                    }}
                  </span>
                </div>
                <div
                  v-if="commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'ok'"
                  class="commentary-text"
                >{{ previewCommentary(a.commentary_meituan, 140) }}</div>
                <div v-else-if="commentaryState(a.commentary_meituan_status, a.commentary_meituan) === 'failed'" class="commentary-text commentary-text-failed">
                  评论生成失败,后台 enrichment_loop 会重试
                </div>
                <div v-else class="commentary-text commentary-text-waiting">
                  正在生成评论…
                </div>
              </div>
            </div>
          </NSpace>
        </NCard>

        <!-- 页码分页 -->
        <NSpace v-if="total > 0" justify="center" style="margin: 32px 0 24px">
          <NPagination
            v-model:page="page"
            :page-count="totalPages"
            :page-size="pageSize"
            show-quick-jumper
            @update:page="onPageChange"
          />
        </NSpace>
        <NText v-else :depth="3" style="display:block; text-align:center; padding: 16px">— 暂无数据 —</NText>
      </div>
    </NSpin>
  </NSpace>
</template>

<style scoped>
/* === 评论钩子(双 provider,三态视觉化) === */
.commentary-stack {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}

.commentary-item {
  position: relative;
  padding: 10px 12px;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.65;
  min-height: 56px;  /* 避免占位卡片太矮导致视觉跳 */
}

/* === OK 状态(有内容)== */
.commentary-item-ok {
  background: var(--color-primary-soft);
  border-left: 3px solid var(--color-primary);
  color: var(--color-letter);
}
.commentary-item-ok .commentary-label {
  color: var(--color-primary);
}
.commentary-item-ok .commentary-text {
  color: var(--color-letter);
  font-size: 13px;
  line-height: 1.7;
}

/* === 等待中(生成中)== */
.commentary-item-waiting {
  background: #f0f4fa;  /* 浅蓝底 */
  border: 1.5px dashed #94a3b8;  /* 虚线边框,提示"未完成" */
  border-left: 4px solid #64748b;  /* 左侧稍粗的灰条,跟 ok 状态一致位置 */
  color: var(--color-text-faint);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.commentary-item-waiting .commentary-label {
  color: #475569;
}
.commentary-item-waiting .commentary-text {
  color: #64748b;
  font-size: 13px;
  font-style: italic;
}

/* === 失败 === */
.commentary-item-failed {
  background: #fef2f2;  /* 浅红底 */
  border: 1.5px solid #fca5a5;
  border-left: 4px solid #ef4444;
  color: #991b1b;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.commentary-item-failed .commentary-label {
  color: #dc2626;
}
.commentary-item-failed .commentary-text {
  color: #b91c1c;
  font-size: 12px;
  font-style: italic;
}

.commentary-label {
  font-size: 12px;
  font-weight: 600;
}

.commentary-label-meituan {
  color: #c2410c;  /* 橙色,与 Angel 区分 */
}

.commentary-text-failed,
.commentary-text-waiting {
  font-size: 12px;
  font-style: italic;
}

.commentary-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.commentary-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 8px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
}
.commentary-badge-ok {
  background: #d1fae5;
  color: #065f46;
}
.commentary-badge-waiting {
  background: #e2e8f0;
  color: #334155;
}
.commentary-badge-failed {
  background: #fee2e2;
  color: #991b1b;
}

/* 旋转的 spinner(等待中) */
.commentary-spinner {
  display: inline-block;
  width: 10px;
  height: 10px;
  border: 1.5px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: commentary-spin 0.8s linear infinite;
}
@keyframes commentary-spin {
  to { transform: rotate(360deg); }
}

/* ===== 桌面端默认宽度 ===== */
.feed-source-select {
  min-width: 240px;
}
.feed-search-input {
  width: 220px;
}

/* ===== 移动端(<= 768px):过滤条全宽,允许换行 ===== */
@media (max-width: 768px) {
  .feed-source-select {
    min-width: 0;
    width: 100%;
  }
  .feed-search-input {
    width: 100%;
  }
  .feed-toolbar-left > * {
    width: 100%;
  }
  .feed-count-label {
    display: block;
    width: 100%;
    margin-top: 4px;
  }
  .feed-toolbar {
    align-items: stretch !important;
  }
  .feed-time-label {
    margin-left: 0 !important;
    width: 100%;
    text-align: right;
  }
}
</style>