<?php

require __DIR__ . '/app/helpers.php';

const MOOZ_TEMP_PERSONAL_SITE = false;

$appConfig = require __DIR__ . '/config/app.php';

function render_temp_personal_site(array $config): void
{
    $file = __DIR__ . '/personal-product.html';
    if (!is_file($file)) {
        http_response_code(500);
        echo 'Temporary page is missing.';
        return;
    }
    header('Content-Type: text/html; charset=UTF-8');
    readfile($file);
}

function render_temp_sitemap(array $config): void
{
    header('Content-Type: application/xml; charset=UTF-8');
    $url = absolute_url('/', $config);
    $today = date('Y-m-d');
    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    echo "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
    echo "  <url><loc>" . h($url) . "</loc><lastmod>" . h($today) . "</lastmod><changefreq>monthly</changefreq><priority>1.0</priority></url>\n";
    echo "</urlset>\n";
}

function render_temp_robots(array $config): void
{
    header('Content-Type: text/plain; charset=UTF-8');
    echo "User-agent: *\n";
    echo "Allow: /\n\n";
    echo "Sitemap: " . absolute_url('/sitemap.xml', $config) . "\n";
}

$path = current_path();
$needsBootstrap = !MOOZ_TEMP_PERSONAL_SITE || str_starts_with($path, '/ywj');
if ($needsBootstrap) {
    require __DIR__ . '/app/bootstrap.php';
}

function is_post(): bool
{
    return ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST';
}

function csrf_token(): string
{
    if (empty($_SESSION['csrf'])) {
        $_SESSION['csrf'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf'];
}

function require_csrf(): void
{
    $token = $_POST['_csrf'] ?? '';
    $sessionToken = $_SESSION['csrf'] ?? '';
    if ($sessionToken === '' || $token === '' || !hash_equals($sessionToken, $token)) {
        http_response_code(419);
        echo 'Invalid CSRF token.';
        exit;
    }
}

function is_logged_in(): bool
{
    return !empty($_SESSION['admin_id']);
}

function require_admin(Store $store): void
{
    if (count($store->admins()) === 0 && current_path() !== '/ywj/setup') {
        redirect_to('/ywj/setup');
    }
    if (!is_logged_in()) {
        redirect_to('/ywj/login');
    }
}

function flash(?string $message = null): ?string
{
    if ($message !== null) {
        $_SESSION['flash'] = $message;
        return null;
    }
    $value = $_SESSION['flash'] ?? null;
    unset($_SESSION['flash']);
    return $value;
}

function upload_image(string $field, array $config, ?string $fallback = ''): string
{
    if (empty($_FILES[$field]) || ($_FILES[$field]['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
        return $fallback ?? '';
    }

    return store_uploaded_image($_FILES[$field], $config);
}

function analytics_visitor_id(): string
{
    $cookie = $_COOKIE['mooz_vid'] ?? '';
    if (is_string($cookie) && preg_match('/^[a-f0-9]{32}$/', $cookie)) {
        return $cookie;
    }
    $visitorId = bin2hex(random_bytes(16));
    setcookie('mooz_vid', $visitorId, [
        'expires' => time() + 60 * 60 * 24 * 365,
        'path' => '/',
        'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
        'httponly' => true,
        'samesite' => 'Lax',
    ]);
    $_COOKIE['mooz_vid'] = $visitorId;
    return $visitorId;
}

function record_public_page_view(Store $store): void
{
    $store->recordPageView(analytics_visitor_id(), current_path());
}

function page_head(array $meta, array $settings, array $config, array $jsonLd = []): void
{
    $title = $meta['title'] ?? ($settings['site_name'] ?? '沐智科技');
    $description = $meta['description'] ?? ($settings['home_description'] ?? '');
    $canonical = $meta['canonical'] ?? absolute_url('/', $config);
    $image = absolute_url($meta['image'] ?? ($settings['og_image'] ?? '/images/banner-1.png'), $config);
    $type = $meta['type'] ?? 'website';
    ?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><?= h($title) ?></title>
<meta name="description" content="<?= h($description) ?>">
<meta name="robots" content="index, follow">
<link rel="canonical" href="<?= h($canonical) ?>">
<meta property="og:type" content="<?= h($type) ?>">
<meta property="og:site_name" content="<?= h($settings['site_name'] ?? '沐智科技') ?>">
<meta property="og:title" content="<?= h($title) ?>">
<meta property="og:description" content="<?= h($description) ?>">
<meta property="og:url" content="<?= h($canonical) ?>">
<meta property="og:image" content="<?= h($image) ?>">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="<?= h($title) ?>">
<meta name="twitter:description" content="<?= h($description) ?>">
<meta name="twitter:image" content="<?= h($image) ?>">
<link rel="icon" href="<?= h(asset_url($settings['logo_image'] ?? '/logo.png')) ?>" type="image/png">
<link rel="shortcut icon" href="<?= h(asset_url($settings['logo_image'] ?? '/logo.png')) ?>" type="image/png">
<link rel="apple-touch-icon" href="<?= h(asset_url($settings['logo_image'] ?? '/images/logo-mark.svg')) ?>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&amp;family=Inter:wght@300;400;500;600&amp;family=JetBrains+Mono:wght@400;500&amp;display=swap" rel="stylesheet">
<link rel="stylesheet" href="/styles.css">
<?php foreach ($jsonLd as $item): ?>
<script type="application/ld+json">
<?= json_ld($item) ?>
</script>
<?php endforeach; ?>
</head>
<body>
<?php
}

function public_nav(array $settings, array $navItems, bool $scrolled = false): void
{
    ?>
<nav class="nav<?= $scrolled ? ' scrolled' : '' ?>" id="nav">
  <div class="nav-left">
    <a class="logo" href="/">
      <?php if (!empty($settings['logo_image'])): ?>
        <img src="<?= h(asset_url($settings['logo_image'])) ?>" alt="<?= h($settings['site_name'] ?? '沐智科技') ?>" style="width:28px;height:28px;object-fit:contain;">
      <?php else: ?>
        <div class="logo-mark"></div>
      <?php endif; ?>
      <span><?= h($settings['logo_text'] ?? $settings['site_name'] ?? '沐智科技') ?></span>
    </a>
    <ul class="nav-links">
      <?php foreach ($navItems as $item): if (empty($item['enabled'])) continue; ?>
        <li><a href="<?= h(normalize_public_url($item['url'])) ?>"><?= h($item['label']) ?></a></li>
      <?php endforeach; ?>
    </ul>
  </div>
  <a class="nav-cta" href="<?= h($settings['primary_cta_url'] ?? '#') ?>" target="_blank" rel="noopener">
    <?= h($settings['primary_cta_text'] ?? '开始使用') ?>
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M7 17L17 7M7 7h10v10"/></svg>
  </a>
</nav>
<?php
}

function public_footer(array $settings, array $navItems): void
{
    ?>
<footer>
  <div class="footer-inner">
    <a class="logo" href="/">
      <?php if (!empty($settings['logo_image'])): ?>
        <img src="<?= h(asset_url($settings['logo_image'])) ?>" alt="<?= h($settings['site_name'] ?? '沐智科技') ?>" style="width:28px;height:28px;object-fit:contain;">
      <?php else: ?>
        <div class="logo-mark"></div>
      <?php endif; ?>
      <span><?= h($settings['logo_text'] ?? $settings['site_name'] ?? '沐智科技') ?></span>
    </a>
    <ul class="footer-links">
      <?php foreach ($navItems as $item): if (empty($item['enabled'])) continue; ?>
        <li><a href="<?= h(normalize_public_url($item['url'])) ?>"><?= h($item['label']) ?></a></li>
      <?php endforeach; ?>
    </ul>
    <div class="footer-copy">© <?= date('Y') ?> <?= h($settings['site_name'] ?? '沐智科技') ?> · <?= h($settings['icp_text'] ?? '') ?></div>
  </div>
</footer>
<script>
  const nav = document.getElementById('nav');
  window.addEventListener('scroll', () => {
    if (window.scrollY > 12) nav?.classList.add('scrolled');
    else nav?.classList.remove('scrolled');
  });
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add('in');
        observer.unobserve(entry.target);
      }
    });
  }, { threshold: 0.1, rootMargin: '0px 0px -60px 0px' });
  document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
  document.querySelectorAll('[data-product-tab]').forEach(tab => {
    tab.addEventListener('click', () => {
      const targetId = tab.dataset.productTab;
      document.querySelectorAll('[data-product-tab]').forEach(item => {
        const isActive = item === tab;
        item.classList.toggle('active', isActive);
        item.setAttribute('aria-selected', isActive ? 'true' : 'false');
      });
      document.querySelectorAll('.product-panel').forEach(panel => {
        panel.classList.toggle('active', panel.id === targetId);
      });
    });
  });
  document.querySelectorAll('[data-product-click]').forEach(link => {
    link.addEventListener('click', () => {
      const payload = new URLSearchParams({
        product_id: link.dataset.productId || '0',
        product_name: link.dataset.productName || '',
        product_url: link.getAttribute('href') || ''
      });
      if (navigator.sendBeacon) {
        navigator.sendBeacon('/track/product-click', payload);
      } else {
        fetch('/track/product-click', { method: 'POST', body: payload, keepalive: true });
      }
    });
  });
  window.addEventListener('load', () => {
    document.querySelectorAll('.banner .reveal').forEach((el, i) => {
      setTimeout(() => el.classList.add('in'), 100 + i * 120);
    });
    const banner = document.querySelector('.banner-image');
    const fallback = document.querySelector('.banner-fallback');
    const slides = Array.from(document.querySelectorAll('.banner-slide')).filter(slide => slide.isConnected);
    if (slides.length === 0 && fallback) fallback.style.display = 'block';
    if (slides.length > 0) slides[0].classList.add('active');
    if (slides.length > 1) {
      let current = 0;
      const showSlide = (next) => {
        slides[current].classList.remove('active');
        current = (next + slides.length) % slides.length;
        slides[current].classList.add('active');
      };
      banner?.classList.add('has-multiple');
      setInterval(() => showSlide(current + 1), 5200);
      document.querySelector('.banner-prev')?.addEventListener('click', () => showSlide(current - 1));
      document.querySelector('.banner-next')?.addEventListener('click', () => showSlide(current + 1));
    }
  });
</script>
</body>
</html>
<?php
}

function render_home(Store $store, array $config): void
{
    record_public_page_view($store);
    $settings = $store->settings();
    $nav = $store->navItems();
    $articles = array_slice($store->articles(true), 0, 5);
    $products = $store->products(true) ?: default_products($settings);
    $meta = [
        'title' => $settings['home_title'] ?? '',
        'description' => $settings['home_description'] ?? '',
        'canonical' => absolute_url('/', $config),
        'image' => $settings['og_image'] ?? '/images/banner-1.png',
    ];
    $jsonLd = [
        ['@context' => 'https://schema.org', '@type' => 'Organization', 'name' => $settings['site_name'] ?? '沐智科技', 'url' => absolute_url('/', $config), 'logo' => absolute_url($settings['logo_image'] ?? '/images/logo-mark.svg', $config), 'description' => $settings['home_description'] ?? ''],
        ['@context' => 'https://schema.org', '@type' => 'WebSite', 'name' => $settings['site_name'] ?? '沐智科技', 'url' => absolute_url('/', $config), 'description' => $settings['home_description'] ?? ''],
    ];
    page_head($meta, $settings, $config, $jsonLd);
    public_nav($settings, $nav);
    ?>
<header class="banner">
  <div class="banner-inner">
    <div class="banner-image reveal">
      <div class="banner-track">
        <?php foreach ($store->banners(true) as $i => $banner): ?>
          <img class="banner-slide<?= $i === 0 ? ' active' : '' ?>" src="<?= h(asset_url($banner['image'])) ?>" alt="<?= h($banner['alt']) ?>" onerror="this.remove();" />
        <?php endforeach; ?>
      </div>
      <button class="banner-nav banner-prev" type="button" aria-label="上一张 banner"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 18l-6-6 6-6"/></svg></button>
      <button class="banner-nav banner-next" type="button" aria-label="下一张 banner"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg></button>
      <div class="banner-fallback" style="display:none;"><div class="banner-fallback-mark"><div class="big-logo"></div><div class="hint">请在后台上传 banner 图</div></div></div>
    </div>
  </div>
  <div class="banner-intro reveal">
    <h1><?= h($settings['hero_title_prefix'] ?? '让传统行业，用好') ?><span class="accent"><?= h($settings['hero_title_accent'] ?? 'AI 增长') ?></span>。</h1>
    <div class="right"><div class="cta-row">
      <a class="btn-primary" href="<?= h($settings['primary_cta_url'] ?? '#') ?>" target="_blank" rel="noopener"><?= h($settings['primary_cta_text'] ?? '开始使用') ?><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M7 17L17 7M7 7h10v10"/></svg></a>
      <a class="btn-ghost" href="<?= h($settings['secondary_cta_url'] ?? '#products') ?>"><?= h($settings['secondary_cta_text'] ?? '了解沐智GEO') ?><span class="arrow"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12l7 7 7-7"/></svg></span></a>
    </div></div>
  </div>
</header>
<section class="about" id="about">
  <div class="section-inner">
    <div class="about-intro reveal"><h2 class="section-title">围绕真实行业场景，落地可持续的 AI 效率提升。</h2><p>沐智科技专注于将 AI 能力嵌入传统行业的营销、运营与增长流程，帮助企业把模型能力转化为可追踪、可复用、可持续优化的业务结果。</p></div>
    <div class="pillar-row reveal">
      <?php foreach ([
          ['行业理解','从业务场景拆解 AI 落点','<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/></svg>'],
          ['AI 增效','让模型参与内容与决策','<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09a1.65 1.65 0 00-1-1.51 1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09a1.65 1.65 0 001.51-1 1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06a1.65 1.65 0 001.82.33h0a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82v0a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>'],
          ['结果可衡量','围绕曝光、转化与声量复盘','<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg>'],
          ['持续优化','跟随国产大模型生态迭代','<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg>'],
      ] as $pillar): ?>
      <div class="pillar"><div class="icon"><?= $pillar[2] ?></div><h4><?= h($pillar[0]) ?></h4><p><?= h($pillar[1]) ?></p></div>
      <?php endforeach; ?>
    </div>
  </div>
</section>
<section class="products" id="products"><div class="section-inner"><div class="section-head reveal"><div><h2 class="section-title">让品牌与文档资产，在 AI 时代更高效流动。</h2></div></div><div class="product-list">
<div class="product-tabs reveal" role="tablist" aria-label="产品列表">
<?php foreach ($products as $i => $product): $panelId = 'product-panel-' . $i; ?>
  <button class="product-tab<?= $i === 0 ? ' active' : '' ?>" id="<?= h($panelId) ?>-tab" type="button" role="tab" aria-selected="<?= $i === 0 ? 'true' : 'false' ?>" aria-controls="<?= h($panelId) ?>" data-product-tab="<?= h($panelId) ?>">
    <span><?= h($product['name']) ?></span>
    <small><?= h($product['tagline']) ?></small>
  </button>
<?php endforeach; ?>
</div>
<div class="product-panels reveal">
<?php
    foreach ($products as $i => $product):
        $panelId = 'product-panel-' . $i;
?>
<article class="product product-panel<?= $i === 0 ? ' active' : '' ?>" id="<?= h($panelId) ?>" role="tabpanel" aria-labelledby="<?= h($panelId) ?>-tab"><div class="product-info"><h3><?= h($product['name']) ?></h3><div class="tagline"><?= h($product['tagline']) ?></div><p><?= h($product['description']) ?></p><ul class="product-features"><?php foreach ($product['features'] as $feature): ?><li><?= h($feature) ?></li><?php endforeach; ?></ul><a href="<?= h($product['url']) ?>" class="product-link"<?= str_starts_with((string)($product['url'] ?? ''), '#') ? '' : ' target="_blank" rel="noopener"' ?> data-product-click data-product-id="<?= h((string)($product['id'] ?? 0)) ?>" data-product-name="<?= h($product['name']) ?>">开始使用</a></div><div class="product-visual"><img class="product-image" src="<?= h(asset_url($product['image'])) ?>" alt="<?= h($product['image_alt'] ?? $product['name']) ?>" loading="lazy" decoding="async" /></div></article>
<?php endforeach; ?>
</div>
</div></div></section>
<section class="articles" id="articles"><div class="section-inner"><div class="section-head reveal"><div><h2 class="section-title">知识专栏。</h2></div><a class="btn-ghost section-head-link" href="/articles">查看全部文章<span class="arrow">→</span></a></div><div class="article-grid reveal">
<?php foreach ($articles as $i => $article): ?>
<a href="<?= h(article_url($article)) ?>" class="article<?= $i === 0 ? ' featured' : '' ?>"><div class="meta"><span class="dot-tiny"></span><span><?= h($article['category']) ?></span><span>—</span><span><?= h(date_label($article['published_at'])) ?></span></div><h3 class="article-title"><?= h($article['title']) ?></h3><p class="article-excerpt"><?= h($article['excerpt']) ?></p><span class="read-more"><?= $i === 0 ? '阅读全文' : '阅读' ?> →</span></a>
<?php endforeach; ?>
</div></div></section>
<section class="contact" id="contact"><div class="contact-card reveal"><div class="contact-qr"><div class="qr-image-wrap"><img class="qr-image" src="<?= h(asset_url($settings['qr_image'] ?? '/qywx.png')) ?>" alt="企业微信客服二维码" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';" /><div class="qr-placeholder"></div></div><div class="qr-tag">企业微信</div></div><div class="contact-text"><div class="contact-kicker"><?= h($settings['contact_kicker'] ?? '') ?></div><h2><?= h($settings['contact_title'] ?? '') ?></h2><p><?= h($settings['contact_description'] ?? '') ?></p><div class="contact-points"><?php foreach (preg_split('/\r\n|\r|\n/u', $settings['contact_points'] ?? '') as $point): if (trim($point) !== ''): ?><span><?= h(trim($point)) ?></span><?php endif; endforeach; ?></div></div></div></section>
<?php
    public_footer($settings, $nav);
}

function render_articles(Store $store, array $config): void
{
    record_public_page_view($store);
    $settings = $store->settings();
    $articles = $store->articles(true);
    page_head([
        'title' => 'AI营销与生成式搜索优化文章 - ' . ($settings['site_name'] ?? '沐智科技'),
        'description' => '阅读沐智科技关于AI营销、生成式搜索优化、GEO、品牌AI可见度和传统行业AI增效的观点文章与实践方法。',
        'canonical' => absolute_url('/articles', $config),
        'image' => $settings['og_image'] ?? '/images/banner-1.png',
    ], $settings, $config, [[
        '@context' => 'https://schema.org',
        '@type' => 'CollectionPage',
        'name' => 'AI营销与生成式搜索优化文章',
        'url' => absolute_url('/articles', $config),
        'description' => '沐智科技关于AI营销、生成式搜索优化、GEO和品牌AI可见度的文章列表。',
    ]]);
    public_nav($settings, $store->navItems(), true);
    ?>
<header class="page-header"><div class="page-header-inner"><h1 class="reveal">笔记与<span class="accent">思考</span>。</h1><p class="reveal">关于 AI 营销、生成式搜索优化、传统行业提质增效的观察。</p></div></header>
<div class="filter-bar"><button class="filter-chip active">全部</button><button class="filter-chip">产品</button><button class="filter-chip">GEO</button><button class="filter-chip">方法</button><button class="filter-chip">案例</button><button class="filter-chip">行业观察</button></div>
<section class="article-list-section"><div class="article-list reveal">
<?php foreach ($articles as $article): ?>
<a href="<?= h(article_url($article)) ?>" class="article-card"><div class="card-image"><?php if (!empty($article['cover_image'])): ?><img src="<?= h(asset_url($article['cover_image'])) ?>" alt="<?= h($article['cover_alt'] ?: $article['title']) ?>" loading="lazy" decoding="async" onerror="this.style.display='none';" /><?php endif; ?><span class="ph"><?= h($article['category']) ?> · <?= h(date('m.d', strtotime($article['published_at']))) ?></span></div><div class="card-body"><div class="card-meta"><span class="dot-tiny"></span><span><?= h($article['category']) ?></span><span>—</span><span><?= h(date_label($article['published_at'])) ?></span></div><h3 class="card-title"><?= h($article['title']) ?></h3><p class="card-excerpt"><?= h($article['excerpt']) ?></p><span class="card-arrow">阅读 →</span></div></a>
<?php endforeach; ?>
</div></section>
<?php public_footer($settings, $store->navItems());
}

function render_article(Store $store, array $config, string $slug): void
{
    record_public_page_view($store);
    $article = $store->findArticleBySlug($slug, true);
    if (!$article) {
        http_response_code(404);
        echo 'Article not found.';
        return;
    }
    $settings = $store->settings();
    $title = $article['seo_title'] ?: ($article['title'] . ' - ' . ($settings['site_name'] ?? '沐智科技'));
    $description = $article['seo_description'] ?: ($article['excerpt'] ?: excerpt($article['body']));
    $url = absolute_url(article_url($article), $config);
    $image = $article['seo_image'] ?: ($article['cover_image'] ?: ($settings['og_image'] ?? '/images/banner-1.png'));
    page_head(['title' => $title, 'description' => $description, 'canonical' => $url, 'image' => $image, 'type' => 'article'], $settings, $config, [[
        '@context' => 'https://schema.org',
        '@type' => 'Article',
        'headline' => $article['title'],
        'description' => $description,
        'image' => absolute_url($image, $config),
        'author' => ['@type' => 'Organization', 'name' => $article['author'] ?: ($settings['site_name'] ?? '沐智科技')],
        'publisher' => ['@type' => 'Organization', 'name' => $settings['site_name'] ?? '沐智科技', 'url' => absolute_url('/', $config)],
        'datePublished' => $article['published_at'],
        'dateModified' => $article['updated_at'] ?: $article['published_at'],
        'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $url],
    ]]);
    public_nav($settings, $store->navItems(), true);
    ?>
<article class="article-page"><div class="article-detail-head"><div class="tag-row"><span class="tag"><?= h($article['category']) ?></span><span class="date"><?= h(str_replace('-', ' · ', $article['published_at'])) ?> · 阅读约 8 分钟</span></div><h1><?= h($article['title']) ?></h1><p class="lede"><?= h($article['excerpt']) ?></p><div class="author"><div class="author-avatar"><?= h(mb_substr($settings['site_name'] ?? '沐', 0, 1)) ?></div><div class="author-info"><div class="name"><?= h($article['author']) ?></div><div class="role"><?= h($settings['site_name'] ?? '沐智科技') ?> 产品与行业解决方案</div></div></div></div><?php if (!empty($article['cover_image'])): ?><div class="article-hero-image"><img src="<?= h(asset_url($article['cover_image'])) ?>" alt="<?= h($article['cover_alt'] ?: $article['title']) ?>" loading="lazy" decoding="async" /></div><?php endif; ?><div class="article-body"><?= sanitize_html($article['body']) ?></div><div class="article-footer"><a href="/articles" class="back-to-list">← BACK TO ARTICLES</a></div></article>
<?php public_footer($settings, $store->navItems());
}

function render_sitemap(Store $store, array $config): void
{
    header('Content-Type: application/xml; charset=UTF-8');
    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    echo "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
    $urls = [['loc' => absolute_url('/', $config), 'lastmod' => date('Y-m-d'), 'priority' => '1.0'], ['loc' => absolute_url('/articles', $config), 'lastmod' => date('Y-m-d'), 'priority' => '0.8']];
    foreach ($store->articles(true) as $article) {
        $urls[] = ['loc' => absolute_url(article_url($article), $config), 'lastmod' => $article['updated_at'] ?: $article['published_at'], 'priority' => '0.7'];
    }
    foreach ($urls as $url) {
        echo "  <url><loc>" . h($url['loc']) . "</loc><lastmod>" . h($url['lastmod']) . "</lastmod><changefreq>weekly</changefreq><priority>" . h($url['priority']) . "</priority></url>\n";
    }
    echo "</urlset>\n";
}

function render_robots(Store $store, array $config): void
{
    header('Content-Type: text/plain; charset=UTF-8');
    $content = trim($store->settings()['robots_content'] ?? "User-agent: *\nAllow: /");
    echo $content . "\n\nSitemap: " . absolute_url('/sitemap.xml', $config) . "\n";
}

function handle_product_click(Store $store): void
{
    if (!is_post()) {
        http_response_code(405);
        echo 'Method Not Allowed';
        return;
    }
    $store->recordProductClick(
        (int) ($_POST['product_id'] ?? 0),
        trim((string) ($_POST['product_name'] ?? '')),
        trim((string) ($_POST['product_url'] ?? '')),
        analytics_visitor_id()
    );
    http_response_code(204);
}

function admin_text(string $name, string $label, string $value = ''): void
{
    admin_field($name, $label, $value);
}

function handle_admin(Store $store, array $config): void
{
    $path = current_path();
    if ($path === '/ywj/setup') {
        if (count($store->admins()) > 0) {
            redirect_to('/ywj/login');
        }
        if (is_post()) {
            require_csrf();
            $username = trim($_POST['username'] ?? 'admin');
            $password = (string) ($_POST['password'] ?? '');
            if (mb_strlen($password) < 8) {
                flash('密码至少 8 位。');
            } else {
                $store->createAdmin($username, $password);
                flash('管理员已创建，请登录。');
                redirect_to('/ywj/login');
            }
        }
        admin_auth_layout('初始化管理员', function () {
            ?><form method="post"><input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>"><?php admin_field('username', '管理员账号', 'admin', ['required' => true]); admin_field('password', '密码', '', ['type' => 'password', 'required' => true, 'hint' => '至少 8 位']); ?><button class="btn btn-primary">创建管理员</button></form><?php
        }, '第一次部署时创建唯一管理员账号。');
        return;
    }
    if ($path === '/ywj/login') {
        if (count($store->admins()) === 0) {
            redirect_to('/ywj/setup');
        }
        if (is_post()) {
            require_csrf();
            $username = trim($_POST['username'] ?? '');
            $password = (string) ($_POST['password'] ?? '');
            foreach ($store->admins() as $admin) {
                if ($admin['username'] === $username && password_verify($password, $admin['password_hash'])) {
                    session_regenerate_id(true);
                    $_SESSION['admin_id'] = $admin['id'];
                    redirect_to('/ywj');
                }
            }
            flash('账号或密码错误。');
        }
        admin_auth_layout('管理员登录', function () {
            ?><form method="post"><input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>"><?php admin_field('username', '账号', 'admin', ['required' => true]); admin_field('password', '密码', '', ['type' => 'password', 'required' => true]); ?><button class="btn btn-primary">登录</button></form><?php
        }, '登录后维护首页、Banner、文章和 SEO 内容。');
        return;
    }
    if ($path === '/ywj/logout') {
        if (!is_post()) {
            redirect_to('/ywj');
        }
        require_csrf();
        session_destroy();
        redirect_to('/ywj/login');
    }

    require_admin($store);
    if ($path === '/ywj' || $path === '/ywj/') {
        admin_layout('Mooz 内容后台', function () use ($store) {
            $articles = $store->articles(false);
            $published = $store->articles(true);
            $banners = $store->banners(false);
            $enabledBanners = $store->banners(true);
            $products = $store->products(false);
            $enabledProducts = $store->products(true);
            ?>
            <section class="stat-grid">
              <div class="stat-card"><span>存储模式</span><strong>MySQL</strong></div>
              <div class="stat-card"><span>全部文章</span><strong><?= count($articles) ?></strong></div>
              <div class="stat-card"><span>已发布文章</span><strong><?= count($published) ?></strong></div>
              <div class="stat-card"><span>启用产品</span><strong><?= count($enabledProducts) ?>/<?= count($products) ?></strong></div>
            </section>
            <section class="quick-grid">
              <a class="quick-card" href="/ywj/settings"><strong>编辑首页配置</strong><span>维护 logo、导航、SEO、首屏 CTA 和联系信息。</span></a>
              <a class="quick-card" href="/ywj/banners"><strong>管理 Banner</strong><span>调整图片、链接、排序和启用状态。</span></a>
              <a class="quick-card" href="/ywj/products"><strong>管理产品</strong><span>维护首页产品 tab、截图、链接和卖点。</span></a>
              <a class="quick-card" href="/ywj/articles/edit"><strong>新建文章</strong><span>发布知识专栏内容并配置封面与 SEO。</span></a>
            </section>
            <section class="panel">
              <div class="panel-header"><div><h2>最近文章</h2><p>快速进入内容编辑或查看公开页面。</p></div><a class="btn btn-muted" href="/ywj/articles">全部文章</a></div>
              <?php if (!$articles): admin_empty('还没有文章', '创建第一篇文章后会显示在这里。'); else: ?>
              <div class="table-wrap"><table class="admin-table"><thead><tr><th>标题</th><th>状态</th><th>日期</th><th>操作</th></tr></thead><tbody>
              <?php foreach (array_slice($articles, 0, 5) as $article): ?>
                <tr><td class="title-cell"><strong><?= h($article['title']) ?></strong><span><?= h($article['slug']) ?></span></td><td><?php admin_badge($article['status'] === 'published' ? '已发布' : '草稿', $article['status'] === 'published' ? 'success' : 'warning'); ?></td><td><?= h($article['published_at'] ?? '') ?></td><td><a href="/ywj/articles/edit?id=<?= h((string)$article['id']) ?>">编辑</a> · <a href="<?= h(article_url($article)) ?>" target="_blank">查看</a></td></tr>
              <?php endforeach; ?>
              </tbody></table></div><?php endif; ?>
            </section>
            <?php
        }, ['description' => '集中维护网站内容、首页配置和发布状态。']);
        return;
    }
    if ($path === '/ywj/analytics') {
        $defaultEnd = date('Y-m-d');
        $defaultStart = date('Y-m-d', strtotime('-29 days'));
        $start = preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['start'] ?? '') ? $_GET['start'] : $defaultStart;
        $end = preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['end'] ?? '') ? $_GET['end'] : $defaultEnd;
        if ($start > $end) {
            [$start, $end] = [$end, $start];
        }
        $summary = $store->analyticsSummary($start, $end);
        $daily = $store->analyticsDaily($start, $end);
        $productClicks = $store->productClickStats($start, $end);
        admin_layout('数据浏览', function () use ($start, $end, $summary, $daily, $productClicks) {
            ?><form class="panel analytics-filter" method="get"><label class="field"><span>开始日期</span><input type="date" name="start" value="<?= h($start) ?>"></label><label class="field"><span>结束日期</span><input type="date" name="end" value="<?= h($end) ?>"></label><button class="btn btn-primary">筛选</button></form>
            <section class="analytics-total-grid">
              <div class="stat-card"><span>PV</span><strong><?= h((string)$summary['pv']) ?></strong></div>
              <div class="stat-card"><span>UV</span><strong><?= h((string)$summary['uv']) ?></strong></div>
              <div class="stat-card"><span>产品点击</span><strong><?= h((string)$summary['product_clicks']) ?></strong></div>
            </section>
            <section class="panel"><div class="panel-header"><div><h2>每日访问</h2><p>按日期汇总 PV 和 UV。</p></div></div><?php if (!$daily): admin_empty('暂无访问数据', '当前日期范围内还没有页面访问。'); else: ?><div class="table-wrap"><table class="admin-table"><thead><tr><th>日期</th><th>PV</th><th>UV</th></tr></thead><tbody><?php foreach ($daily as $row): ?><tr><td><?= h($row['date']) ?></td><td><?= h((string)$row['pv']) ?></td><td><?= h((string)$row['uv']) ?></td></tr><?php endforeach; ?></tbody></table></div><?php endif; ?></section>
            <section class="panel"><div class="panel-header"><div><h2>产品按钮点击</h2><p>统计首页产品详情里的“开始使用”点击。</p></div></div><?php if (!$productClicks): admin_empty('暂无点击数据', '当前日期范围内还没有产品按钮点击。'); else: ?><div class="table-wrap"><table class="admin-table"><thead><tr><th>产品</th><th>链接</th><th>点击数</th></tr></thead><tbody><?php foreach ($productClicks as $row): ?><tr><td class="title-cell"><strong><?= h($row['product_name'] ?: '未命名产品') ?></strong><span>ID: <?= h((string)$row['product_id']) ?></span></td><td><?= h($row['product_url']) ?></td><td><?= h((string)$row['clicks']) ?></td></tr><?php endforeach; ?></tbody></table></div><?php endif; ?></section><?php
        }, ['description' => '默认查看最近 30 天，可按日期筛选 PV、UV 和产品按钮点击。']);
        return;
    }
    if ($path === '/ywj/settings') {
        if (is_post()) {
            require_csrf();
            $settings = $store->settings();
            foreach (['site_name','logo_text','home_title','home_description','hero_title_prefix','hero_title_accent','primary_cta_text','primary_cta_url','secondary_cta_text','secondary_cta_url','contact_kicker','contact_title','contact_description','contact_points','icp_text','robots_content'] as $key) {
                $settings[$key] = (string) ($_POST[$key] ?? '');
            }
            try {
                $settings['logo_image'] = upload_image('logo_upload', $config, $_POST['logo_image'] ?? ($settings['logo_image'] ?? ''));
                $settings['og_image'] = upload_image('og_upload', $config, $_POST['og_image'] ?? ($settings['og_image'] ?? ''));
                $settings['qr_image'] = upload_image('qr_upload', $config, $_POST['qr_image'] ?? ($settings['qr_image'] ?? ''));
            } catch (RuntimeException $e) {
                flash($e->getMessage());
                redirect_to('/ywj/settings');
            }
            $store->saveSettings($settings);
            $nav = [];
            foreach (($_POST['nav_label'] ?? []) as $i => $label) {
                if (trim($label) === '') continue;
                $nav[] = ['id' => (int) (($_POST['nav_id'][$i] ?? 0) ?: ($i + 1)), 'label' => trim($label), 'url' => trim($_POST['nav_url'][$i] ?? '#'), 'sort' => (int) ($_POST['nav_sort'][$i] ?? (($i + 1) * 10)), 'enabled' => !empty($_POST['nav_enabled'][$i])];
            }
            $store->saveNavItems($nav);
            flash('首页配置已保存。');
            redirect_to('/ywj/settings');
        }
        $settings = $store->settings();
        $nav = $store->navItems();
        admin_layout('首页配置', function () use ($settings, $nav) {
            ?><form class="section-stack" method="post" enctype="multipart/form-data"><input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
            <section class="panel"><div class="panel-header"><div><h2>站点基础</h2><p>控制品牌显示、Logo 和首页 SEO 默认信息。</p></div></div><div class="form-grid"><?php admin_field('site_name', '站点名', $settings['site_name'] ?? ''); admin_field('logo_text', 'Logo 文案', $settings['logo_text'] ?? ''); admin_image_upload('logo_image', 'logo_upload', 'Logo 图片', $settings['logo_image'] ?? '', ['hint' => '用于前台导航品牌标识。']); admin_image_upload('og_image', 'og_upload', '默认 OG 图', $settings['og_image'] ?? '', ['hint' => '用于首页和文章缺省分享图。']); admin_field('home_title', '首页 SEO Title', $settings['home_title'] ?? '', ['class' => 'full']); admin_textarea('home_description', '首页描述', $settings['home_description'] ?? '', ['class' => 'full', 'rows' => 4]); ?></div></section>
            <section class="panel"><div class="panel-header"><div><h2>导航</h2><p>最多维护 6 个导航入口，排序越小越靠前。</p></div></div><?php for ($i=0;$i<6;$i++): $item=$nav[$i]??['id'=>$i+1,'label'=>'','url'=>'','sort'=>($i+1)*10,'enabled'=>false]; ?><div class="nav-row"><input type="hidden" name="nav_id[]" value="<?= h((string)$item['id']) ?>"><?php admin_field('nav_sort[]', '排序', (string)$item['sort']); admin_field('nav_label[]', '名称', $item['label']); admin_field('nav_url[]', '链接', $item['url']); ?><label class="check-field"><input type="checkbox" name="nav_enabled[<?= $i ?>]" <?= !empty($item['enabled']) ? 'checked' : '' ?>> 启用</label></div><?php endfor; ?></section>
            <section class="panel"><div class="panel-header"><div><h2>首屏与联系</h2><p>维护首页主标题、行动按钮和联系区内容。</p></div></div><div class="form-grid"><?php admin_field('hero_title_prefix', '主标题前半', $settings['hero_title_prefix'] ?? ''); admin_field('hero_title_accent', '主标题强调', $settings['hero_title_accent'] ?? ''); admin_field('primary_cta_text', '主按钮文字', $settings['primary_cta_text'] ?? ''); admin_field('primary_cta_url', '主按钮链接', $settings['primary_cta_url'] ?? ''); admin_field('secondary_cta_text', '副按钮文字', $settings['secondary_cta_text'] ?? ''); admin_field('secondary_cta_url', '副按钮链接', $settings['secondary_cta_url'] ?? ''); admin_field('contact_kicker', '联系区标签', $settings['contact_kicker'] ?? ''); admin_field('contact_title', '联系区标题', $settings['contact_title'] ?? ''); admin_image_upload('qr_image', 'qr_upload', '二维码图片', $settings['qr_image'] ?? '', ['hint' => '用于首页联系区二维码。']); admin_field('icp_text', 'ICP备案文案', $settings['icp_text'] ?? ''); admin_textarea('contact_description', '联系区描述', $settings['contact_description'] ?? '', ['class' => 'full']); admin_textarea('contact_points', '联系卖点（一行一个）', $settings['contact_points'] ?? '', ['class' => 'full']); admin_textarea('robots_content', 'Robots 内容', $settings['robots_content'] ?? '', ['class' => 'full', 'rows' => 5]); ?></div></section>
            <div class="form-actions"><button class="btn btn-primary">保存首页配置</button></div></form><?php
        }, ['description' => '分组维护品牌、SEO、导航、CTA 和联系信息。']);
        return;
    }
    if ($path === '/ywj/banners') {
        if (is_post()) {
            require_csrf();
            $items = [];
            foreach (($_POST['banner_id'] ?? []) as $i => $id) {
                $image = $_POST['banner_image'][$i] ?? '';
                if (!empty($_FILES['banner_upload']['name'][$i])) {
                    $_FILES['one_banner'] = ['name' => $_FILES['banner_upload']['name'][$i], 'type' => $_FILES['banner_upload']['type'][$i], 'tmp_name' => $_FILES['banner_upload']['tmp_name'][$i], 'error' => $_FILES['banner_upload']['error'][$i], 'size' => $_FILES['banner_upload']['size'][$i]];
                    try {
                        $image = upload_image('one_banner', $config, $image);
                    } catch (RuntimeException $e) {
                        flash($e->getMessage());
                        redirect_to('/ywj/banners');
                    }
                }
                if (trim($image) === '') continue;
                $items[] = ['id' => (int) ($id ?: ($i + 1)), 'image' => $image, 'alt' => trim($_POST['banner_alt'][$i] ?? ''), 'link_url' => trim($_POST['banner_link'][$i] ?? ''), 'sort' => (int) ($_POST['banner_sort'][$i] ?? (($i + 1) * 10)), 'enabled' => !empty($_POST['banner_enabled'][$i])];
            }
            $store->saveBanners($items);
            flash('Banner 已保存。');
            redirect_to('/ywj/banners');
        }
        $banners = $store->banners(false);
        admin_layout('Banner 管理', function () use ($banners) {
            ?><form class="section-stack" method="post" enctype="multipart/form-data"><input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>"><section class="panel"><div class="panel-header"><div><h2>Banner 队列</h2><p>使用上传预览组件维护图片，不暴露路径输入。</p></div></div><?php for ($i=0;$i<6;$i++): $b=$banners[$i]??['id'=>$i+1,'image'=>'','alt'=>'','link_url'=>'','sort'=>($i+1)*10,'enabled'=>false]; ?><div class="banner-row"><input type="hidden" name="banner_id[]" value="<?= h((string)$b['id']) ?>"><?php admin_field('banner_sort[]','排序',(string)$b['sort']); admin_image_upload('banner_image[]', 'banner_upload[]', 'Banner 图片', $b['image'], ['hint' => '选择新图后保存，当前图片会被替换。']); admin_field('banner_alt[]','Alt 文案',$b['alt']); admin_field('banner_link[]','链接',$b['link_url']); ?><label class="check-field"><input type="checkbox" name="banner_enabled[<?= $i ?>]" <?= !empty($b['enabled'])?'checked':'' ?>> 启用</label></div><?php endfor; ?></section><div class="form-actions"><button class="btn btn-primary">保存 Banner</button></div></form><?php
        }, ['description' => '维护首页轮播图片、跳转链接和发布状态。']);
        return;
    }
    if ($path === '/ywj/products') {
        if (is_post()) {
            require_csrf();
            $items = [];
            foreach (($_POST['product_id'] ?? []) as $i => $id) {
                $name = trim($_POST['product_name'][$i] ?? '');
                if ($name === '') continue;
                $image = $_POST['product_image'][$i] ?? '';
                if (!empty($_FILES['product_upload']['name'][$i])) {
                    $_FILES['one_product'] = ['name' => $_FILES['product_upload']['name'][$i], 'type' => $_FILES['product_upload']['type'][$i], 'tmp_name' => $_FILES['product_upload']['tmp_name'][$i], 'error' => $_FILES['product_upload']['error'][$i], 'size' => $_FILES['product_upload']['size'][$i]];
                    try {
                        $image = upload_image('one_product', $config, $image);
                    } catch (RuntimeException $e) {
                        flash($e->getMessage());
                        redirect_to('/ywj/products');
                    }
                }
                $items[] = [
                    'id' => (int) ($id ?: ($i + 1)),
                    'name' => $name,
                    'tagline' => trim($_POST['product_tagline'][$i] ?? ''),
                    'description' => trim($_POST['product_description'][$i] ?? ''),
                    'image' => trim($image),
                    'image_alt' => trim($_POST['product_image_alt'][$i] ?? ''),
                    'url' => trim($_POST['product_url'][$i] ?? ''),
                    'features' => $_POST['product_features'][$i] ?? '',
                    'sort' => (int) ($_POST['product_sort'][$i] ?? (($i + 1) * 10)),
                    'enabled' => !empty($_POST['product_enabled'][$i]),
                ];
            }
            $store->saveProducts($items);
            flash('产品已保存。');
            redirect_to('/ywj/products');
        }
        $products = $store->products(false);
        if (!$products) {
            $products = default_products($store->settings());
        }
        admin_layout('产品管理', function () use ($products) {
            ?><form class="section-stack" method="post" enctype="multipart/form-data"><input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>"><section class="panel"><div class="panel-header"><div><h2>首页产品</h2><p>维护前台产品 tab、详情文案、截图、跳转链接和启用状态。</p></div></div><?php for ($i=0;$i<8;$i++): $p=$products[$i]??['id'=>$i+1,'name'=>'','tagline'=>'','description'=>'','image'=>'','image_alt'=>'','url'=>'','features'=>[],'sort'=>($i+1)*10,'enabled'=>false]; $features=is_array($p['features'] ?? null)?implode("\n",$p['features']):($p['features'] ?? ''); ?><div class="product-admin-row"><input type="hidden" name="product_id[]" value="<?= h((string)($p['id'] ?? ($i+1))) ?>"><div class="form-grid three"><?php admin_field('product_sort[]','排序',(string)($p['sort'] ?? (($i+1)*10))); admin_field('product_name[]','产品名称',$p['name'] ?? ''); admin_field('product_tagline[]','短标题',$p['tagline'] ?? ''); admin_field('product_url[]','跳转链接',$p['url'] ?? '', ['class'=>'full']); admin_textarea('product_description[]','产品描述',$p['description'] ?? '', ['class'=>'full','rows'=>3]); admin_textarea('product_features[]','卖点（一行一个）',$features, ['class'=>'full','rows'=>3]); admin_image_upload('product_image[]', 'product_upload[]', '产品截图', $p['image'] ?? '', ['hint'=>'选择新图后保存；不选则保留当前图片。']); admin_field('product_image_alt[]','图片 Alt',$p['image_alt'] ?? ''); ?></div><label class="check-field"><input type="checkbox" name="product_enabled[<?= $i ?>]" <?= !empty($p['enabled'])?'checked':'' ?>> 启用</label></div><?php endfor; ?></section><div class="form-actions"><button class="btn btn-primary">保存产品</button></div></form><?php
        }, ['description' => '产品数据保存到数据库，前台首页从数据库读取。']);
        return;
    }
    if ($path === '/ywj/articles') {
        admin_layout('文章管理', function () use ($store) {
            $articles = $store->articles(false);
            ?><section class="panel"><div class="panel-header"><div><h2>内容列表</h2><p>管理草稿、发布状态、封面和 SEO 信息。</p></div><a class="btn btn-primary" href="/ywj/articles/edit">新建文章</a></div><?php if (!$articles): admin_empty('还没有文章', '点击新建文章开始维护知识专栏。'); else: ?><div class="table-wrap"><table class="admin-table"><thead><tr><th>文章</th><th>分类</th><th>状态</th><th>发布日期</th><th>操作</th></tr></thead><tbody><?php foreach ($articles as $article): ?><tr><td class="title-cell"><strong><?= h($article['title']) ?></strong><span><?= h($article['slug']) ?></span></td><td><?= h($article['category']) ?></td><td><?php admin_badge($article['status'] === 'published' ? '已发布' : '草稿', $article['status'] === 'published' ? 'success' : 'warning'); ?></td><td><?= h($article['published_at']) ?></td><td><a href="/ywj/articles/edit?id=<?= h((string)$article['id']) ?>">编辑</a> · <a href="<?= h(article_url($article)) ?>" target="_blank">查看</a></td></tr><?php endforeach; ?></tbody></table></div><?php endif; ?></section><?php
        }, ['description' => '维护知识专栏文章、发布状态和公开页面入口。']);
        return;
    }
    if ($path === '/ywj/articles/edit') {
        $id = (int) ($_GET['id'] ?? 0);
        $article = $id ? $store->findArticleById($id) : null;
        if (is_post()) {
            require_csrf();
            try {
                $cover = upload_image('cover_upload', $config, $_POST['cover_image'] ?? '');
                $seoImage = upload_image('seo_upload', $config, $_POST['seo_image'] ?? '');
            } catch (RuntimeException $e) {
                flash($e->getMessage());
                redirect_to('/ywj/articles/edit' . ($id ? '?id=' . $id : ''));
            }
            $slug = strtolower(trim($_POST['slug'] ?? ''));
            $slug = preg_replace('/[^a-z0-9-]+/', '-', $slug) ?: ('article-' . time());
            $existing = $store->findArticleBySlug($slug, false);
            if ($existing && (int) $existing['id'] !== $id) {
                flash('Slug 已存在，请换一个。');
                redirect_to('/ywj/articles/edit' . ($id ? '?id=' . $id : ''));
            }
            $newId = $store->saveArticle([
                'id' => $id,
                'title' => trim($_POST['title'] ?? ''),
                'slug' => $slug,
                'category' => trim($_POST['category'] ?? ''),
                'cover_image' => $cover,
                'cover_alt' => trim($_POST['cover_alt'] ?? ''),
                'excerpt' => trim($_POST['excerpt'] ?? ''),
                'body' => $_POST['body'] ?? '',
                'author' => trim($_POST['author'] ?? '沐智科技研究团队'),
                'published_at' => trim($_POST['published_at'] ?? date('Y-m-d')),
                'updated_at' => date('Y-m-d'),
                'status' => $_POST['status'] ?? 'draft',
                'seo_title' => trim($_POST['seo_title'] ?? ''),
                'seo_description' => trim($_POST['seo_description'] ?? ''),
                'seo_image' => $seoImage,
            ]);
            flash('文章已保存。');
            redirect_to('/ywj/articles/edit?id=' . $newId);
        }
        $article = $article ?: ['id'=>0,'title'=>'','slug'=>'','category'=>'','cover_image'=>'','cover_alt'=>'','excerpt'=>'','body'=>'','author'=>'沐智科技研究团队','published_at'=>date('Y-m-d'),'status'=>'draft','seo_title'=>'','seo_description'=>'','seo_image'=>''];
        admin_layout($id ? '编辑文章' : '新建文章', function () use ($article) {
            ?><form class="section-stack" method="post" enctype="multipart/form-data"><input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>"><section class="panel"><div class="panel-header"><div><h2>正文内容</h2><p>正文 HTML 会经过安全清洗后保存。</p></div><?php admin_badge($article['status']==='published' ? '已发布' : '草稿', $article['status']==='published' ? 'success' : 'warning'); ?></div><div class="form-grid"><?php admin_field('title','标题',$article['title'], ['class' => 'full']); admin_field('slug','Slug',$article['slug']); admin_field('category','分类',$article['category']); admin_field('author','作者',$article['author']); admin_field('published_at','发布日期',$article['published_at'], ['type' => 'date']); admin_select('status', '状态', $article['status'], ['draft' => '草稿', 'published' => '发布']); admin_image_upload('cover_image', 'cover_upload', '文章封面', $article['cover_image'], ['hint' => '用于文章列表和详情页封面。']); admin_field('cover_alt','封面 Alt',$article['cover_alt']); admin_textarea('excerpt', '摘要', $article['excerpt'], ['class' => 'full', 'rows' => 4]); admin_rich_textarea('body', '正文内容', $article['body'], ['class' => 'full']); ?></div></section><section class="panel"><div class="panel-header"><div><h2>SEO</h2><p>为空时会回退使用文章标题、摘要或默认 OG 图。</p></div></div><div class="form-grid"><?php admin_field('seo_title','SEO Title',$article['seo_title'], ['class' => 'full']); admin_textarea('seo_description', 'SEO Description', $article['seo_description'], ['class' => 'full', 'rows' => 3]); admin_image_upload('seo_image', 'seo_upload', 'SEO/OG 图', $article['seo_image'], ['hint' => '用于社交分享图；不上传则保留当前图片或留空。']); ?></div></section><div class="form-actions"><a class="btn btn-muted" href="/ywj/articles">返回列表</a><button class="btn btn-primary">保存文章</button></div></form><?php
        }, ['description' => '编辑文章内容、封面、发布状态和搜索展示信息。']);
        return;
    }
    http_response_code(404);
    echo 'Admin page not found.';
}

if ($path === '/track/product-click') {
    handle_product_click($store);
} elseif (str_starts_with($path, '/ywj')) {
    handle_admin($store, $appConfig);
} elseif (MOOZ_TEMP_PERSONAL_SITE && in_array($path, ['/', '/index.html', '/articles', '/articles.html', '/article.html'], true)) {
    render_temp_personal_site($appConfig);
} elseif (MOOZ_TEMP_PERSONAL_SITE && preg_match('#^/articles/([a-z0-9-]+)(?:\.html)?$#', $path, $matches)) {
    render_temp_personal_site($appConfig);
} elseif (MOOZ_TEMP_PERSONAL_SITE && $path === '/sitemap.xml') {
    render_temp_sitemap($appConfig);
} elseif (MOOZ_TEMP_PERSONAL_SITE && $path === '/robots.txt') {
    render_temp_robots($appConfig);
} elseif ($path === '/' || $path === '/index.html') {
    render_home($store, $appConfig);
} elseif ($path === '/articles' || $path === '/articles.html') {
    render_articles($store, $appConfig);
} elseif ($path === '/article.html') {
    $first = $store->articles(true)[0] ?? null;
    if ($first) {
        header('Location: ' . article_url($first), true, 301);
    } else {
        redirect_to('/articles');
    }
} elseif (preg_match('#^/articles/([a-z0-9-]+)(?:\.html)?$#', $path, $matches)) {
    render_article($store, $appConfig, $matches[1]);
} elseif ($path === '/sitemap.xml') {
    render_sitemap($store, $appConfig);
} elseif ($path === '/robots.txt') {
    render_robots($store, $appConfig);
} else {
    http_response_code(404);
    echo 'Page not found.';
}
