import type { Metadata } from "next";
import { redirect } from "next/navigation";
import type { Article } from "@/lib/articles/types";
import {
  getLegacyArticleBySlug,
  getLegacyRecentSlugs,
  getLegacyRelatedArticles,
  getRelatedForumThreads, type RelatedForumThread,
} from "@/lib/articles/legacy-source";
import { linkifyAndExtractMentions } from "@/lib/company-mentions";
import { cleanExcerpt } from "@/lib/articles/excerpt";
import CompanyMentionsHover from "@/components/CompanyMentionsHover";
import CompaniesInThisStory from "@/components/CompaniesInThisStory";
import NewsArticleDetailClient from "./NewsArticleDetailClient";

// ISR: serve cached pages but revalidate hourly. New imported posts surface
// without a redeploy.
export const revalidate = 3600;
export const dynamicParams = true;

interface PageProps {
  params: Promise<{ slug: string }>;
}

const SITE_URL =
  process.env.NEXT_PUBLIC_SITE_URL || "https://avbeat.com";

/** Convert a free-form date (e.g. "April 9, 2026") to ISO 8601 for JSON-LD. */
function toIso(d: string | null | undefined): string {
  if (!d) return new Date().toISOString();
  const parsed = new Date(d);
  return isNaN(parsed.getTime()) ? new Date().toISOString() : parsed.toISOString();
}

/** Make an image path absolute against SITE_URL for Google News compliance. */
function absoluteImage(src: string | undefined | null): string {
  if (!src) return `${SITE_URL}/assets/images/article-placeholder.jpg`;
  if (/^https?:\/\//i.test(src)) return src;
  return `${SITE_URL}${src.startsWith("/") ? "" : "/"}${src}`;
}

async function loadArticle(slug: string): Promise<{
  article: Article | null;
  related: Article[];
  relatedForumThreads: RelatedForumThread[];
}> {
  const imported = await getLegacyArticleBySlug(slug);
  if (!imported) return { article: null, related: [], relatedForumThreads: [] };
  const [related, relatedForumThreads] = await Promise.all([
    getLegacyRelatedArticles(slug, imported.category, 6),
    getRelatedForumThreads(imported.title, 6),
  ]);
  return { article: imported, related, relatedForumThreads };
}

export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
  const { slug } = await params;
  const { article } = await loadArticle(slug);
  if (!article) {
    return { title: "Article Not Found", description: "The article you are looking for does not exist." };
  }
  // Strip HTML from excerpt before stuffing into <meta description> /
  // openGraph / twitter — those MUST be plain text. Raw excerpts sometimes
  // contain <p>...</p>, which Next.js then HTML-escapes, surfacing as
  // literal `&lt;p&gt;` in page source.
  const cleanDesc = cleanExcerpt(article.excerpt);
  const noindex = !!article.noindex;
  return {
    title: `${article.title} — AV Beat`,
    description: cleanDesc,
    alternates: { canonical: `/news/${article.slug}` },
    // Passthrough PR submissions (Mike Nann / Writeturn etc.) get a hard
    // noindex on robots + googlebot-news so they don't pollute Google News.
    robots: noindex
      ? { index: false, follow: false, nocache: true, googleBot: { index: false, follow: false, noimageindex: true } }
      : undefined,
    other: noindex ? { "googlebot-news": "noindex" } : undefined,
    openGraph: {
      type: "article",
      title: article.title,
      description: cleanDesc,
      url: `/news/${article.slug}`,
      images: [{ url: article.image, width: 1200, height: 630, alt: article.alt }],
      authors: [article.author],
      publishedTime: article.date,
      tags: article.tags,
    },
    twitter: {
      card: "summary_large_image",
      title: article.title,
      description: cleanDesc,
      images: [article.image],
      creator: "@AV Beat",
    },
  };
}

export async function generateStaticParams() {
  // Build-time: pre-render the most-recent imported slugs (cap to keep the
  // build fast). Everything else is on-demand ISR via dynamicParams=true.
  const recent = await getLegacyRecentSlugs(50);
  return recent.map((slug) => ({ slug }));
}

export default async function NewsArticlePage({ params }: PageProps) {
  const { slug } = await params;
  const { article, related, relatedForumThreads } = await loadArticle(slug);
  if (!article) {
    // Unknown slug — fall back to the news index instead of 404.
    redirect("/news");
  }

  // Auto-link company-name mentions in the article body and capture the set
  // of matched slugs for the "Companies in this story" sidebar.
  const { html: linkedContent, mentionedSlugs } = await linkifyAndExtractMentions(article.content || "");
  const articleWithLinks: Article = { ...article, content: linkedContent };

  const articleSchema = {
    "@context": "https://schema.org",
    "@type": "NewsArticle",
    headline: article.title,
    description: cleanExcerpt(article.excerpt),
    image: [absoluteImage(article.image)],
    author: { "@type": "Person", name: article.author },
    publisher: {
      "@type": "Organization",
      name: "AV Beat",
      logo: { "@type": "ImageObject", url: `${SITE_URL}/assets/images/logo.png` },
    },
    datePublished: toIso(article.date),
    dateModified: new Date().toISOString(),
    mainEntityOfPage: { "@type": "WebPage", "@id": `${SITE_URL}/news/${article.slug}` },
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(articleSchema) }}
      />
      <NewsArticleDetailClient
        article={articleWithLinks}
        relatedArticles={related}
        relatedForumThreads={relatedForumThreads}
        companiesInStory={
          mentionedSlugs.length > 0 ? (
            <CompaniesInThisStory slugs={mentionedSlugs} />
          ) : null
        }
      />
      <CompanyMentionsHover />
    </>
  );
}
