<script setup>
import SiteFooter from '~/components/site/SiteFooter.vue'
import SiteHeader from '~/components/site/SiteHeader.vue'
import UEditor from '~/components/UEditor.vue'

const route = useRoute()
const { bySortAndTime, fetchPublicContent, normalizeArticle } = useOfficialContent()
const slug = String(route.params.slug || '')

const { data: pageData } = await useAsyncData(`public-insight-${slug}`, async () => {
  const rows = await fetchPublicContent('ARTICLE')
  const articles = rows.sort(bySortAndTime).map((item) => normalizeArticle(item, new Map()))
  return {
    articles,
    current: articles.find((item) => item.slug === slug) || null
  }
})

if (!pageData.value?.current) {
  throw createError({ statusCode: 404, statusMessage: '洞察文章不存在' })
}

const article = computed(() => pageData.value.current)
const relatedArticles = computed(() =>
  (pageData.value?.articles || []).filter((item) => item.slug !== article.value.slug).slice(0, 6)
)
const hotArticles = computed(() =>
  (pageData.value?.articles || []).filter((item) => item.slug !== article.value.slug).slice(0, 8)
)
const articleHtml = computed(() => article.value.contentHtml || '<p>暂无正文内容。</p>')
const articleTagList = computed(() =>
  article.value.tags?.length ? article.value.tags : [article.value.category, 'GEO', '品牌增长'].filter(Boolean)
)


useHead(() => ({
  title: `${article.value.title}｜云途全域增长洞察`,
  meta: [
    { name: 'description', content: article.value.excerpt },
    { property: 'og:title', content: article.value.title },
    { property: 'og:description', content: article.value.excerpt },
    { property: 'og:image', content: article.value.cover }
  ]
}))



function escapeHtml(value) {
  return String(value ?? '')
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&#039;')
}

function renderParagraphs(paragraphs = []) {
  return paragraphs.map((paragraph) => `<p>${escapeHtml(paragraph)}</p>`).join('')
}

function renderComparisonTable(rows = []) {
  if (!rows.length) return ''

  return `
    <table>
      <thead>
        <tr>
          <th>比较维度</th>
          <th>传统 SEO</th>
          <th>GEO</th>
        </tr>
      </thead>
      <tbody>
        ${rows
          .map(
            (row) => `
              <tr>
                <td><strong>${escapeHtml(row[0])}</strong></td>
                <td>${escapeHtml(row[1])}</td>
                <td>${escapeHtml(row[2])}</td>
              </tr>
            `
          )
          .join('')}
      </tbody>
    </table>
  `
}

function renderSections(sections = []) {
  if (!sections.length) {
    return `
      <h2>核心观察</h2>
      <p>${escapeHtml(article.value.excerpt)}</p>
      <blockquote>完整内容正在编辑和复核中，当前先保留摘要信息，避免发布未经确认的细节。</blockquote>
    `
  }

  return sections
    .map(
      (section) => `
        <h2>${escapeHtml(section.title)}</h2>
        ${renderParagraphs(section.paragraphs)}
        ${renderComparisonTable(section.comparison)}
      `
    )
    .join('')
}

function buildInsightArticleHtml(articleData) {
  return `
    ${articleData.lead ? `<blockquote>${escapeHtml(articleData.lead)}</blockquote>` : ''}
    ${renderSections(articleData.sections)}
    <blockquote>GEO 的目标不是让品牌在每一个问题里出现，而是在真正影响用户决策的问题中，被准确理解并获得可信推荐。</blockquote>
  `
}
</script>

<template>
  <div class="news-detail-page insight-news-detail">
    <a class="skip-link" href="#main-content">跳到文章正文</a>
    <SiteHeader />

    <main id="main-content" class="news-detail-main">
      <div class="news-detail-shell">
        <nav class="news-breadcrumb" aria-label="面包屑">
          <NuxtLink to="/">首页</NuxtLink>
          <span>/</span>
          <NuxtLink to="/insights">增长洞察</NuxtLink>
          <span>/</span>
          <b>{{ article.category }}</b>
        </nav>

        <div class="news-detail-layout">
          <article class="news-article">
            <header class="news-article-header">
              <h1>{{ article.title }}</h1>
              <p class="news-excerpt">{{ article.excerpt }}</p>
              <div class="news-meta">
                <time :datetime="article.date">{{ article.date }}</time>
                <span>{{ article.readingTime }}</span>
                <span>{{ article.views }} 阅读</span>
              </div>
              <div class="news-tag-row">
                <span v-for="tag in articleTagList" :key="tag">{{ tag }}</span>
              </div>
            </header>

            <figure v-if="article.cover" class="news-cover">
              <img :src="article.cover" :alt="article.title" />
            </figure>
            <UEditor :content="articleHtml" />
          </article>

          <aside class="news-sidebar" aria-label="相关推荐">
            <section class="sidebar-panel">
              <h2>推荐文章</h2>
              <ol class="hot-list">
                <li v-for="(item, index) in hotArticles" :key="item.slug">
                  <NuxtLink :to="`/insights/${item.slug}`">
                    <span>{{ index + 1 }}</span>
                    <strong>{{ item.title }}</strong>
                    <time :datetime="item.date">{{ item.date.replaceAll('-', '/') }}</time>
                  </NuxtLink>
                </li>
              </ol>
            </section>

            <section class="sidebar-panel">
              <h2>相关文章</h2>
              <div class="recommend-list">
                <NuxtLink
                  v-for="item in relatedArticles.slice(0, 4)"
                  :key="item.slug"
                  :to="`/insights/${item.slug}`"
                >
                  <img :src="item.cover" :alt="item.title" />
                  <span>
                    <strong>{{ item.title }}</strong>
                    <small>{{ item.date }}</small>
                  </span>
                </NuxtLink>
              </div>
            </section>
          </aside>
        </div>
      </div>
    </main>

    <SiteFooter />
  </div>
</template>

<style scoped>
.news-detail-page {
  min-height: 100vh;
  color: #132033;
  background:
    radial-gradient(circle at 90% 0, rgba(73, 144, 255, 0.12), transparent 320px),
    linear-gradient(180deg, #f7fbff 0, #fff 330px);
}
.skip-link {
  position: fixed;
  z-index: 100;
  top: 12px;
  left: 12px;
  padding: 10px 14px;
  border-radius: 8px;
  color: #fff;
  background: #1677ff;
  transform: translateY(-150%);
  transition: transform 0.2s ease;
}
.skip-link:focus {
  transform: translateY(0);
}
.news-detail-main {
  padding: 42px 0 96px;
}
.news-detail-shell {
  width: min(1296px, calc(100% - 48px));
  margin: 0 auto;
}
.news-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  color: #718197;
  font-size: 14px;
}
.news-breadcrumb a {
  color: #61738b;
  text-decoration: none;
}
.news-breadcrumb a:hover,
.news-breadcrumb b {
  color: #1677ff;
}
.news-detail-layout {
  display: grid;
  grid-template-columns: minmax(0, 880px) 320px;
  align-items: start;
  gap: 72px;
  margin-top: 34px;
}
.news-article {
  min-width: 0;
}
.news-article-header {
  padding-bottom: 34px;
  border-bottom: 1px solid #e6edf6;
}
.news-kicker {
  margin: 0;
  color: #1677ff;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
.news-article h1 {
  margin: 18px 0 0;
  color: #111d2f;
  font-size: clamp(30px, 3vw, 44px);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.38;
  text-wrap: pretty;
}
.news-excerpt {
  max-width: 820px;
  margin: 24px 0 0;
  color: #6c7b90;
  font-size: 16px;
  line-height: 1.9;
}
.news-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 18px 28px;
  margin-top: 26px;
  color: #7b8da3;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.news-tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}
.news-tag-row span {
  padding: 5px 10px;
  color: #6b7f96;
  background: #eef5fd;
  font-size: 13px;
}
.news-consult-banner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 28px;
  margin: 34px 0 38px;
  padding: 28px 34px;
  overflow: hidden;
  background:
    radial-gradient(circle at 8% 20%, rgba(255, 255, 255, 0.28), transparent 24%),
    linear-gradient(105deg, #0f63ff 0%, #08b9d8 100%);
  color: #fff;
}
.news-consult-banner p {
  margin: 0;
  font-size: clamp(18px, 2vw, 24px);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.48;
}
.news-consult-banner span {
  display: block;
}
.news-consult-banner button {
  min-width: 136px;
  height: 48px;
  padding: 0 28px;
  border: 0;
  background: #fff;
  color: #1677ff;
  cursor: pointer;
  font-size: 16px;
  font-weight: 700;
  transition:
    transform 0.2s ease,
    box-shadow 0.2s ease;
}
.news-consult-banner button:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 26px rgba(4, 67, 152, 0.24);
}
.news-cover {
  margin: 42px 0 44px;
  overflow: hidden;
  border-radius: 10px;
  background: #eef5fd;
}
.news-cover img {
  width: 100%;
  max-height: 420px;
  display: block;
  object-fit: cover;
}
.news-article :deep(.ueditor-content) {
  color: #27364a;
  font-size: 16px;
  line-height: 2;
}
.news-article :deep(.ueditor-content h2) {
  margin-top: 58px;
  color: #111d2f;
  font-size: 25px;
  line-height: 1.45;
}
.news-article :deep(.ueditor-content h3) {
  margin-top: 34px;
  font-size: 20px;
}
.news-article :deep(.ueditor-content blockquote) {
  margin: 36px 0;
  border-left: 4px solid #d9e8fb;
  border-radius: 0;
  color: #53657c;
  background: transparent;
}
.news-article :deep(.ueditor-content table) {
  font-size: 14px;
}
.news-sidebar {
  position: sticky;
  top: 88px;
  display: grid;
  gap: 34px;
}
.sidebar-panel h2 {
  position: relative;
  margin: 0 0 18px;
  color: #111d2f;
  font-size: 16px;
  font-weight: 700;
}
.sidebar-panel h2::after {
  color: #ff7a1a;
  content: '▼';
  font-size: 10px;
  margin-left: 2px;
}
.hot-list {
  display: grid;
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
  background: #f5f9fd;
}
.hot-list a {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 13px 14px;
  color: #172236;
  text-decoration: none;
  background: #f8fbff;
  transition:
    color 0.2s ease,
    background 0.2s ease,
    transform 0.2s ease;
}
.hot-list a:hover {
  color: #1677ff;
  background: #eef6ff;
  transform: translateX(2px);
}
.hot-list span {
  color: #ff8a2a;
  font-weight: 700;
}
.hot-list strong {
  overflow: hidden;
  font-size: 14px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hot-list time {
  color: #7b8b9e;
  font-size: 13px;
}
.tag-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.tag-cloud span {
  padding: 9px 15px;
  border: 1px solid #e2eaf4;
  color: #27364a;
  background: #fff;
  font-size: 14px;
}
.recommend-list {
  display: grid;
  gap: 15px;
}
.recommend-list a {
  display: grid;
  grid-template-columns: 82px minmax(0, 1fr);
  gap: 12px;
  color: #172236;
  text-decoration: none;
}
.recommend-list img {
  width: 82px;
  height: 56px;
  object-fit: cover;
  background: #eef5fd;
}
.recommend-list strong {
  display: -webkit-box;
  overflow: hidden;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.recommend-list small {
  display: block;
  margin-top: 6px;
  color: #7d8da1;
  font-size: 13px;
}
@media (max-width: 980px) {
  .news-detail-layout {
    grid-template-columns: 1fr;
    gap: 48px;
  }
  .news-sidebar {
    position: static;
  }
}
@media (max-width: 640px) {
  .news-detail-main {
    padding: 28px 0 68px;
  }
  .news-detail-shell {
    width: min(100% - 24px, 560px);
  }
  .news-detail-layout {
    margin-top: 24px;
  }
  .news-article h1 {
    font-size: 28px;
  }
  .news-consult-banner {
    grid-template-columns: 1fr;
    gap: 18px;
    margin: 28px 0 32px;
    padding: 24px;
  }
  .news-consult-banner button {
    width: 100%;
  }
  .news-cover img {
    max-height: 260px;
  }
  .hot-list a {
    grid-template-columns: 24px minmax(0, 1fr);
  }
  .hot-list time {
    display: none;
  }
}
</style>
