---
import type { CollectionEntry } from 'astro:content';
import { render } from 'astro:content';
import ArticleList from '../components/ArticleList.astro';
import AtAGlance from '../components/AtAGlance.astro';
import Breadcrumbs from '../components/Breadcrumbs.astro';
import PostMedia from '../components/PostMedia.astro';
import PostThumbnail from '../components/PostThumbnail.astro';
import TagList from '../components/TagList.astro';
import {
  absoluteUrl,
  adjacentArticles,
  articlePath,
  buildBreadcrumbJsonLd,
  buildPersonJsonLd,
  buildBreadcrumbTrail,
  formatDate,
  getArticles,
  getHeaderVideo,
  getRelatedArticles,
  optimizeOgImage,
  visibleBreadcrumbs,
} from '../lib/site';
import Base from './Base.astro';

interface Props {
  post: CollectionEntry<'work'>;
}

const { post } = Astro.props;
const { Content, headings } = await render(post);

const allPosts = await getArticles();
const { previous, next } = adjacentArticles(allPosts, post);
const related = getRelatedArticles(allPosts, post, 3);

const ogImageOptimized = await optimizeOgImage(post.data.thumbnail.src);

const trail = buildBreadcrumbTrail({ post });
const breadcrumbTrail = visibleBreadcrumbs(trail);

// Reading time: words in body / 200 wpm, rounded up.
const wordCount = post.body ? post.body.trim().split(/\s+/).filter(Boolean).length : 0;
const readingMinutes = Math.max(1, Math.ceil(wordCount / 200));

// Only preload the monospace font if the post body actually contains code
// (inline `…` or fenced ``` blocks). Saves ~15 KB on every code-free article.
const hasCode = !!post.body && /(^|[^`])`[^`\n]+`|```/m.test(post.body);

// TOC: only show when there are >= 3 h2 headings.
const h2Headings = headings.filter((h) => h.depth === 2);
const showToc = h2Headings.length >= 3;

// Don't repeat header media at the end; PostThumbnail already rendered the
// banner image and, when present, plays the header video inline.
const thumbnailSrc = post.data.thumbnail.src.src;
const headerVideo = getHeaderVideo(post);
const trailingMedia = (post.data.article?.media ?? []).filter((item) => {
  if (item === headerVideo) return false;
  if (item.type === 'video') return true;
  return item.src.src !== thumbnailSrc;
});

const personId = absoluteUrl('/about/#person');

const blogPosting = {
  '@context': 'https://schema.org',
  '@type': 'BlogPosting',
  headline: post.data.title,
  description: post.data.description,
  datePublished: post.data.date.toISOString(),
  ...(post.data.article?.updated && {
    dateModified: post.data.article.updated.toISOString(),
  }),
  author: { '@id': personId },
  publisher: { '@id': personId },
  image: absoluteUrl(ogImageOptimized.src),
  url: absoluteUrl(articlePath(post)),
  keywords: (post.data.article?.tags ?? []).join(', '),
  mainEntityOfPage: {
    '@type': 'WebPage',
    '@id': absoluteUrl(articlePath(post)),
  },
};

const breadcrumbJsonLd = buildBreadcrumbJsonLd(trail);
const personJsonLd = buildPersonJsonLd();
---

<Base
  title={post.data.title}
  description={post.data.description}
  canonicalPath={articlePath(post)}
  ogImage={ogImageOptimized.src}
  ogImageAlt={post.data.thumbnail.alt}
  ogImageWidth={1200}
  ogImageHeight={630}
  ogType="article"
  preloadMono={hasCode}
  article={{
    publishedTime: post.data.date.toISOString(),
    modifiedTime: post.data.article?.updated?.toISOString(),
    tags: post.data.article?.tags ?? [],
  }}
  jsonLd={[blogPosting, breadcrumbJsonLd, personJsonLd]}
>
  <article class="post">
    <header class="post-header">
      <Breadcrumbs items={breadcrumbTrail} />
      <p class="eyebrow">{post.data.period ?? 'Article'}</p>
      <h1>{post.data.title}</h1>
      <p class="dek">{post.data.description}</p>
      <div class="post-meta">
        <time datetime={post.data.date.toISOString()}>
          {formatDate(post.data.date)}
        </time>
        {
          post.data.article?.updated && (
            <>
              {' · '}
              <span>
                Updated{' '}
                <time datetime={post.data.article.updated.toISOString()}>
                  {formatDate(post.data.article.updated)}
                </time>
              </span>
            </>
          )
        }
        {' · '}
        <span>{readingMinutes} min read</span>
      </div>
      <TagList tags={post.data.article?.tags ?? []} />
    </header>

    <PostThumbnail post={post} />

    <AtAGlance
      headingId={`at-a-glance-${post.id}`}
      projectPeriod={post.data.period}
      stack={post.data.article?.stack}
      scale={post.data.article?.scale}
      links={post.data.links}
    />

    {
      showToc && (
        <nav class="post-toc" aria-label="On this page">
          <ol>
            {h2Headings.map((heading) => (
              <li>
                <a href={`#${heading.slug}`}>{heading.text}</a>
              </li>
            ))}
          </ol>
        </nav>
      )
    }

    <div class="prose">
      <Content />
    </div>

    <PostMedia items={trailingMedia} />

    {
      related.length > 0 && (
        <section class="related-posts">
          <h2>Related articles</h2>
          <ArticleList posts={related} />
        </section>
      )
    }

    {
      (previous || next) && (
        <nav class="post-nav" aria-label="Adjacent articles">
          <ul class="post-nav__list">
            {previous && (
              <li class="post-nav__prev">
                <a class="previous" href={articlePath(previous)} rel="prev">
                  <span class="post-nav__label">
                    <span aria-hidden="true">←</span> Previous
                  </span>
                  <span class="post-nav__title">{previous.data.title}</span>
                </a>
              </li>
            )}
            {next && (
              <li class="post-nav__next">
                <a class="next" href={articlePath(next)} rel="next">
                  <span class="post-nav__label">
                    Next <span aria-hidden="true">→</span>
                  </span>
                  <span class="post-nav__title">{next.data.title}</span>
                </a>
              </li>
            )}
          </ul>
        </nav>
      )
    }
  </article>
</Base>
