import type { Metadata } from 'next';
import Link from 'next/link';
import { notFound } from 'next/navigation';
import {
  CATEGORY_PATH,
  CATEGORIES,
  isLocale,
  localePath,
  postPath,
  type Category,
  type Locale,
} from '@ai-radar/shared';
import { getPost } from '@/lib/api';
import { getDictionary } from '@/lib/dictionary';
import { SITE, absoluteUrl, localeAlternates } from '@/lib/site';
import { CategoryLabel } from '@/components/ui/CategoryLabel';
import { SourceIcon } from '@/components/ui/SourceIcon';
import { TimeAgo } from '@/components/ui/TimeAgo';
import { CompactCard } from '@/components/cards/StoryCards';
import { Section } from '@/components/sections/Section';
import { AdSlot } from '@/components/ads/AdSlot';
import { StoryImage } from '@/components/story/StoryImage';

/** URL segment back to the category it belongs to. */
const SEGMENT_TO_CATEGORY = Object.fromEntries(
  CATEGORIES.map((c) => [CATEGORY_PATH[c], c]),
) as Record<string, Category>;

type Params = Promise<{ lang: string; category: string; slug: string }>;

export async function generateMetadata({ params }: { params: Params }): Promise<Metadata> {
  const { lang, category, slug } = await params;
  if (!isLocale(lang) || !SEGMENT_TO_CATEGORY[category]) return {};

  const data = await getPost(slug, lang);
  if (!data) return {};

  const { post } = data;
  const path = `/${category}/${slug}`;

  return {
    title: post.seoTitle ?? post.title,
    description: post.seoDescription ?? post.summary,
    alternates: {
      canonical: absoluteUrl(`/${lang}${path}`),
      // Each language canonicals to itself, never to the other — a
      // translated page is its own page, not a duplicate.
      languages: localeAlternates(path),
    },
    openGraph: {
      type: 'article',
      title: post.seoTitle ?? post.title,
      description: post.seoDescription ?? post.summary,
      url: absoluteUrl(`/${lang}${path}`),
      publishedTime: post.publishedAt ?? undefined,
      siteName: SITE[lang].name,
      // Where an image earns most of its value: a shared link with a
      // picture gets read, one without often does not.
      ...(post.image ? { images: [{ url: post.image.url, alt: post.image.alt }] } : {}),
    },
    twitter: {
      // summary_large_image with no image degrades to a plain card, so
      // this stays correct either way.
      card: 'summary_large_image',
      title: post.seoTitle ?? post.title,
      description: post.seoDescription ?? post.summary,
      ...(post.image ? { images: [post.image.url] } : {}),
    },
  };
}

/**
 * A story page.
 *
 * Calmer than the homepage by design: one column, no rail, no competing
 * cards. The reading order is fixed by docs/DESIGN.md — category, title,
 * summary, what changed, why it matters, ad, who should care, worth
 * trying, source, related.
 *
 * It should read as a briefing, not a blog post.
 */
export default async function StoryPage({ params }: { params: Params }) {
  const { lang, category, slug } = await params;
  if (!isLocale(lang)) notFound();

  const expectedCategory = SEGMENT_TO_CATEGORY[category];
  if (!expectedCategory) notFound();

  const data = await getPost(slug, lang);
  if (!data) notFound();

  const { post, related } = data;

  // The slug is unique across categories, so a wrong segment would serve
  // the same story at two URLs. 404 rather than duplicate the content.
  if (post.category !== expectedCategory) notFound();

  const dict = getDictionary(lang);

  return (
    <main id="main" className="page story">
      <Link href={localePath('/', lang)} className="story-back">
        <span className="arrow">←</span> {dict.story.back}
      </Link>

      <article>
        <header className="story-head">
          <div className="story-meta">
            <CategoryLabel category={post.category} locale={lang} sponsored={post.sponsored} />
            <span className="t-meta">
              {post.companyName && (
                <>
                  {post.companyName} <span className="dot-sep">·</span>{' '}
                </>
              )}
              <TimeAgo date={post.publishedAt} locale={lang} />
            </span>
          </div>

          <h1 className="t-h1 story-title">{post.title}</h1>
          <p className="story-summary">{post.summary}</p>
        </header>

        {/* After the summary, never between it and the title: the reader
            gets the point in words first, and an image inserted there
            would push the summary below the fold on a phone. */}
        {post.image && <StoryImage image={post.image} />}

        <div className="story-fields">
          <Field label={dict.story.whatChanged} value={post.whatChanged} />
          <Field label={dict.story.whyItMatters} value={post.whyItMatters} />
        </div>

        {/* First ad only after the reader has had what changed and why it
            matters. Never between title and summary. */}
        <AdSlot slotKey="article_middle" label={dict.meta.advertisement} />

        <div className="story-fields">
          {post.whoShouldCare.length > 0 && (
            <div className="story-field">
              <div className="why-label">{dict.story.whoShouldCare}</div>
              <div className="audience-row">
                {post.whoShouldCare.map((who) => (
                  <span key={who} className="audience-chip">
                    {dict.audience[who] ?? who}
                  </span>
                ))}
              </div>
            </div>
          )}

          <div className="story-field">
            <div className="why-label">{dict.story.worthTrying}</div>
            <p className="t-body">
              <span className={post.worthTrying === 'yes' ? 'worth-yes' : 'worth-other'}>
                {dict.worth[post.worthTrying as 'yes' | 'no' | 'maybe']}
              </span>
              {post.worthTryingNote && <> — {post.worthTryingNote}</>}
            </p>
          </div>
        </div>

        <footer className="story-source">
          <div className="why-label">{dict.story.source}</div>
          <a href={post.sourceUrl} target="_blank" rel="noopener noreferrer" className="source-out">
            <SourceIcon src={post.sourceIconUrl} size={26} />
            {post.sourceName} <span className="arrow">↗</span>
          </a>
          {post.sourceCount > 1 && (
            <p className="t-meta" style={{ marginTop: 'var(--s2)' }}>
              {dict.story.alsoCovered} {post.sourceCount} {dict.meta.sources}
            </p>
          )}
          {/* Confidence is shown only when the item was actually verified,
              so the badge means something rather than decorating. */}
          {post.confidence >= 80 && (
            <p className="verified">
              <TickIcon /> {dict.story.verified}
            </p>
          )}
        </footer>
      </article>

      {related.length > 0 && (
        <Section title={dict.story.related}>
          <div className="grid-4">
            {related.map((item) => (
              <CompactCard key={item.id} post={item} locale={lang} dict={dict} />
            ))}
          </div>
        </Section>
      )}

      <AdSlot slotKey="article_bottom" label={dict.meta.advertisement} />

      <StoryJsonLd post={post} locale={lang} path={`/${category}/${slug}`} />
    </main>
  );
}

function Field({ label, value }: { label: string; value: string }) {
  if (!value) return null;
  return (
    <div className="story-field">
      <div className="why-label">{label}</div>
      <p className="t-body">{value}</p>
    </div>
  );
}

/**
 * NewsArticle structured data.
 *
 * Declares the original source as `isBasedOn` — an honest signal that
 * this is a briefing about someone else's announcement, not original
 * reporting, which is both accurate and safer for search.
 */
function StoryJsonLd({
  post,
  locale,
  path,
}: {
  post: { title: string; summary: string; publishedAt: string | null; sourceUrl: string; sourceName: string };
  locale: Locale;
  path: string;
}) {
  const data = {
    '@context': 'https://schema.org',
    '@type': 'NewsArticle',
    headline: post.title,
    description: post.summary,
    datePublished: post.publishedAt,
    inLanguage: locale,
    url: absoluteUrl(`/${locale}${path}`),
    isBasedOn: post.sourceUrl,
    publisher: {
      '@type': 'Organization',
      name: SITE[locale].name,
      url: absoluteUrl(`/${locale}`),
    },
    citation: {
      '@type': 'CreativeWork',
      name: post.sourceName,
      url: post.sourceUrl,
    },
  };

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
    />
  );
}

function TickIcon() {
  return (
    <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
      <path
        d="M2.5 6.5 4.75 8.75 9.5 3.5"
        stroke="currentColor"
        strokeWidth="1.7"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}
