import { BlogLayout } from "@/components/blog/blog-layout";
import { FAQSection } from "@/components/blog/faq-section";
import { getAuthor, authorJsonLd } from "@/lib/authors";
import { siteConfig } from "@/lib/site";
import { GRAPH_IDS, JsonLd } from "@/lib/json-ld";

import { components } from "@/components/mdx-components";
import { MDXContent } from "@content-collections/mdx/react";
import { allBlogs } from "content-collections";
import type { Metadata } from "next";
import { notFound } from "next/navigation";

const VALID_CATEGORIES = [
  "actualites",
  "guides",
  "reglementation",
  "cas-clients",
] as const;

type Category = (typeof VALID_CATEGORIES)[number];

const SITE_URL = siteConfig.url;

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

// Generate metadata for SEO
export async function generateMetadata({
  params,
}: PageProps): Promise<Metadata> {
  const { category, slug } = await params;

  if (!VALID_CATEGORIES.includes(category as Category)) {
    return {};
  }

  const blog = allBlogs.find((b) => b.category === category && b.slug === slug);

  if (!blog) {
    return {};
  }

  const canonicalUrl = `${SITE_URL}/${category}/${slug}/`;

  // Use seoTitle for <title> tag if available, otherwise use title
  const pageTitle = blog.seoTitle || blog.title;
  const imageAlt = blog.imageAlt || blog.title;

  return {
    title: pageTitle,
    description: blog.description,
    keywords: blog.keywords?.join(", "),
    alternates: {
      canonical: canonicalUrl,
      types: {
        "text/markdown": `${SITE_URL}/${category}/${slug}.md`,
      },
    },
    openGraph: {
      title: pageTitle,
      description: blog.description,
      type: "article",
      url: canonicalUrl,
      images: [
        {
          url: blog.image,
          width: 1200,
          height: 630,
          alt: imageAlt,
        },
      ],
      publishedTime: blog.date,
      modifiedTime: blog.lastmod || blog.updatedAt || blog.date,
      authors: [blog.author],
      tags: blog.categories,
    },
    twitter: {
      card: "summary_large_image",
      title: pageTitle,
      description: blog.description,
      images: [blog.image],
    },
  };
}

// Generate JSON-LD structured data with LLM optimization
function generateJsonLd(blog: (typeof allBlogs)[0], category: string) {
  const canonicalUrl = `${SITE_URL}/${category}/${blog.slug}/`;

  const jsonLd: Record<string, unknown> = {
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    headline: blog.title,
    description: blog.description,
    image: {
      "@type": "ImageObject",
      url: blog.image.startsWith("http") ? blog.image : `${SITE_URL}${blog.image}`,
      width: 1200,
      height: 630,
      ...(blog.imageAlt && { caption: blog.imageAlt }),
    },
    datePublished: `${blog.date}T00:00:00+01:00`,
    dateModified: `${blog.lastmod || blog.updatedAt || blog.date}T00:00:00+01:00`,
    author: authorJsonLd(getAuthor(blog.authorId)),
    publisher: { "@id": GRAPH_IDS.organization },
    mainEntityOfPage: {
      "@type": "WebPage",
      "@id": canonicalUrl,
    },
    keywords: blog.keywords?.join(", "),
    articleSection: category,
    wordCount: blog.content.trim().split(/\s+/).length,
    inLanguage: "fr-FR",
    isAccessibleForFree: true,
  };

  // Add topics as semantic "about" entities
  if (blog.topics && blog.topics.length > 0) {
    jsonLd.about = blog.topics.map((topic) => ({
      "@type": "Thing",
      name: topic,
    }));
  }

  // Add audience targeting for LLMs
  if (blog.audience) {
    const audienceLabels: Record<string, string> = {
      debutant: "Débutant",
      intermediaire: "Intermédiaire",
      expert: "Expert",
      cto: "Dirigeant / CTO",
    };
    jsonLd.audience = {
      "@type": "Audience",
      audienceType: audienceLabels[blog.audience] || blog.audience,
    };
  }

  // Add mentions as secondary entities
  if (blog.mentions && blog.mentions.length > 0) {
    jsonLd.mentions = blog.mentions.map((entity) => ({
      "@type": "Thing",
      name: entity,
    }));
  }

  // Add speakable for voice assistants
  jsonLd.speakable = {
    "@type": "SpeakableSpecification",
    cssSelector: ["h1", "h2", ".key-takeaways", "blockquote"],
  };

  return jsonLd;
}

// Generate breadcrumb JSON-LD
function generateBreadcrumbJsonLd(
  category: string,
  categoryLabel: string,
  blogTitle: string,
  slug: string
) {
  return {
    "@context": "https://schema.org",
    "@type": "BreadcrumbList",
    itemListElement: [
      {
        "@type": "ListItem",
        position: 1,
        name: "Accueil",
        item: SITE_URL,
      },
      {
        "@type": "ListItem",
        position: 2,
        name: categoryLabel,
        item: `${SITE_URL}/${category}/`,
      },
      {
        "@type": "ListItem",
        position: 3,
        name: blogTitle,
        item: `${SITE_URL}/${category}/${slug}/`,
      },
    ],
  };
}

const CATEGORY_LABELS: Record<Category, string> = {
  actualites: "Actualités",
  guides: "Guides",
  reglementation: "Réglementation",
  "cas-clients": "Cas clients",
};

export default async function BlogPage({ params }: PageProps) {
  const { category, slug } = await params;

  // Validate category
  if (!VALID_CATEGORIES.includes(category as Category)) {
    notFound();
  }

  const blog = allBlogs.find((b) => b.category === category && b.slug === slug);

  if (!blog) {
    notFound();
  }

  const categoryLabel = CATEGORY_LABELS[category as Category];
  const articleJsonLd = generateJsonLd(blog, category);
  const breadcrumbJsonLd = generateBreadcrumbJsonLd(
    category,
    categoryLabel,
    blog.title,
    slug
  );

  return (
    <>
      {/* Pas de <link rel="preload"> manuel ici : il pointait l'image BRUTE
          (/blog/*.webp) alors que le rendu consomme /_next/image. Le navigateur
          téléchargeait donc l'original en fetchPriority=high sans jamais s'en
          servir ("preloaded but not used"), pendant que le vrai LCP partait en
          priorité normale. Le <Image priority> de blog-layout.tsx émet déjà le
          preload de l'URL optimisée, qui est la seule correcte. */}

      <div>
        <JsonLd data={articleJsonLd} />
        <JsonLd data={breadcrumbJsonLd} />
        {blog.howTo && (
          <JsonLd
            data={{
              "@context": "https://schema.org",
              "@type": "HowTo",
              name: blog.title,
              description: blog.howTo.description,
              ...(blog.howTo.totalTime && { totalTime: blog.howTo.totalTime }),
              ...(blog.howTo.estimatedCost && {
                estimatedCost: {
                  "@type": "MonetaryAmount",
                  currency: "EUR",
                  value: blog.howTo.estimatedCost,
                },
              }),
              step: blog.howTo.steps.map((step, i) => ({
                "@type": "HowToStep",
                position: i + 1,
                name: step.name,
                text: step.text,
                url: `${SITE_URL}/${category}/${slug}/#etape-${i + 1}`,
              })),
            }}
          />
        )}

        <BlogLayout
          blog={blog}
          category={category}
          categoryLabel={categoryLabel}
        >
          <MDXContent components={components} code={blog.body} />
          {/* FAQ Section with JSON-LD */}
          {blog.faqs && blog.faqs.length > 0 && (
            <FAQSection faqs={blog.faqs} title="Questions fréquentes" />
          )}
        </BlogLayout>
      </div>
    </>
  );
}

export async function generateStaticParams() {
  return allBlogs.map((post) => ({
    category: post.category,
    slug: post.slug,
  }));
}
