import { notFound } from "next/navigation";
import Image from "next/image";
import { getPostBySlug, getPosts } from "@/lib/query/post";
import type { Metadata } from "next";
import { format } from "date-fns";
import {
  ContentBlock,
  OutputData,
  ParagraphData,
  HeaderData,
  ListData,
  ImageData,
  QuoteData,
  CodeData,
} from "@/types";

export async function generateStaticParams() {
  const posts = await getPosts();
  if (!Array.isArray(posts)) {
    console.error("getPosts did not return an array:", posts);
    return [];
  }
  return posts.map((post) => ({
    slug: post.slug,
  }));
}

function extractDescriptionFromBlocks(
  content: OutputData | null
): string | null {
  if (
    !content ||
    !content.blocks ||
    !Array.isArray(content.blocks) ||
    content.blocks.length === 0
  ) {
    return null;
  }
  const firstParagraph = content.blocks.find(
    (block): block is ContentBlock & { data: ParagraphData } =>
      block.type === "paragraph"
  );
  if (firstParagraph?.data?.text) {
    const plainText = firstParagraph.data.text
      .replace(/<[^>]*>/g, "")
      .replace(/&[^;]+;/g, "");
    return plainText.substring(0, 160) + (plainText.length > 160 ? "..." : "");
  }
  return null;
}

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata> {
  const { slug } = await params;
  const post = await getPostBySlug(slug, {
    fields: [
      "slug",
      "status",
      "user_created",
      "date_created",
      "user_updated",
      "date_updated",
      "title",
      "content",
      "excerpt",
      "featured_image",
    ],
  });

  if (!post) {
    return {
      title: "Post Not Found",
    };
  }

  const imageUrl = post.featured_image;

  const descriptionFromContent =
    post.content &&
    typeof post.content === "object" &&
    Array.isArray(post.content.blocks)
      ? extractDescriptionFromBlocks(post.content as OutputData)
      : null;

  const description =
    post.excerpt || descriptionFromContent || "Read this OMS TechTalk article.";

  const publishedTime = post.date_created
    ? new Date(post.date_created).toISOString()
    : "";

  return {
    title: `${post.title} | OMS TechTalk`,
    description: description,
    alternates: {
      canonical: `/tech-talk/${post.slug}`,
    },
    openGraph: {
      title: post.title,
      description: description,
      url: `https://oms.africa/tech-talk/${post.slug}`,
      type: "article",
      publishedTime: publishedTime,
      ...(imageUrl && {
        images: [
          {
            url: imageUrl,
            width: 1200,
            height: 630,
            alt: post.title,
          },
        ],
      }),
    },
    twitter: {
      card: "summary_large_image",
      title: post.title,
      description: description,
      ...(imageUrl && { images: [imageUrl] }),
    },
  };
}

const renderBlock = (block: ContentBlock) => {
  const renderListItems = (items: string[]) => {
    return items.map((item, index) => (
      <li
        key={index}
        className="mb-2"
        dangerouslySetInnerHTML={{ __html: item }}
      />
    ));
  };

  switch (block.type) {
    case "header":
      const headerBlock = block as ContentBlock & { data: HeaderData };
      const level = headerBlock.data.level || 2;
      // Ensure HeaderTag has a type that JSX understands for intrinsic elements.
      const HeaderTag = `h${level}` as "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
      return (
        <HeaderTag
          key={block.id}
          className={`text-${
            6 - (headerBlock.data.level || 2)
          }xl font-bold my-4 text-primary`}
          dangerouslySetInnerHTML={{ __html: headerBlock.data.text }}
        />
      );
    case "paragraph":
      const paragraphBlock = block as ContentBlock & { data: ParagraphData };
      return (
        <p
          key={block.id}
          className="my-4 leading-relaxed"
          dangerouslySetInnerHTML={{ __html: paragraphBlock.data.text }}
        />
      );
    case "list":
      const listBlock = block as ContentBlock & { data: ListData };
      const ListTag = listBlock.data.style === "ordered" ? "ol" : "ul";
      return (
        <ListTag
          key={block.id}
          className={`my-4 pl-6 ${
            listBlock.data.style === "ordered" ? "list-decimal" : "list-disc"
          }`}
        >
          {listBlock.data.items &&
            Array.isArray(listBlock.data.items) &&
            renderListItems(listBlock.data.items)}
        </ListTag>
      );
    case "image":
      const imageBlock = block as ContentBlock & { data: ImageData };
      const imageUrl = imageBlock.data.file?.url;

      if (!imageUrl) return null;

      return (
        <div key={block.id} className="my-6">
          <Image
            src={imageUrl}
            alt={imageBlock.data.caption || "Blog post image"}
            width={imageBlock.data.file?.width || 800}
            height={imageBlock.data.file?.height || 450}
            className="rounded-md shadow-sm mx-auto"
          />
          {imageBlock.data.caption && (
            <p className="text-center text-sm text-muted-foreground mt-2">
              {imageBlock.data.caption}
            </p>
          )}
        </div>
      );
    case "quote":
      const quoteBlock = block as ContentBlock & { data: QuoteData };
      return (
        <blockquote
          key={block.id}
          className="my-6 pl-4 border-l-4 border-primary italic text-muted-foreground"
        >
          <p dangerouslySetInnerHTML={{ __html: quoteBlock.data.text }} />
          {quoteBlock.data.caption && (
            <footer className="text-sm mt-2">
              - {quoteBlock.data.caption}
            </footer>
          )}
        </blockquote>
      );
    case "code":
      const codeBlock = block as ContentBlock & { data: CodeData };
      const codeContent = codeBlock.data.code || "";
      return (
        <pre
          key={block.id}
          className="my-6 p-4 bg-muted text-muted-foreground rounded-md overflow-x-auto text-sm"
        >
          <code>{codeContent}</code>
        </pre>
      );
    default:
      console.warn(`Unknown block type: ${block.type}`);
      return null;
  }
};

export default async function PostPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const post = await getPostBySlug(slug);

  if (!post) {
    notFound();
  }

  const contentBlocks =
    post.content &&
    typeof post.content === "object" &&
    Array.isArray(post.content.blocks)
      ? (post.content.blocks as ContentBlock[])
      : null;

  const coverImageUrl =
    post.featured_image + "?width=1200&height=600&quality=80&fit=cover";

  return (
    <article className="container mx-auto px-4 py-8">
      <header className="text-center mb-12 max-w-3xl mx-auto">
        {coverImageUrl && (
          <div className="relative w-full h-64 md:h-96 mb-6 rounded-lg overflow-hidden">
            <Image
              src={coverImageUrl}
              alt={`Cover image for ${post.title}`}
              fill={true}
              style={{ objectFit: "cover" }}
              className="shadow-md"
              priority
            />
          </div>
        )}
        <h1 className="text-4xl md:text-5xl font-extrabold leading-tight mb-4 text-primary">
          {post.title}
        </h1>
        {post.date_created && (
          <p className="text-muted-foreground text-sm mb-2">
            Published on {format(new Date(post.date_created), "MMMM dd, yyyy")}
          </p>
        )}
        {post.excerpt && (
          <p className="text-lg text-muted-foreground italic mt-4">
            {post.excerpt}
          </p>
        )}
      </header>

      <div className="container mx-auto px-4 max-w-3xl">
        <div
          className="prose prose-lg lg:prose-xl dark:prose-invert max-w-none mx-auto
                     prose-headings:text-primary prose-a:text-blue-600 hover:prose-a:text-blue-800 dark:prose-a:text-blue-400 dark:hover:prose-a:text-blue-300
                     prose-strong:font-semibold prose-img:rounded-md prose-img:shadow-sm"
        >
          {contentBlocks && contentBlocks.length > 0 ? (
            contentBlocks.map((block) => renderBlock(block))
          ) : (
            <p>Content is not available or in an unexpected format.</p>
          )}
        </div>
      </div>
    </article>
  );
}
