import type { Metadata } from "next";
import { notFound, redirect } from "next/navigation";
import { cache } from "react";
import { PortableText } from "@portabletext/react";
import { defineQuery } from "next-sanity";
import { sanity } from "@/lib/sanity";
import { ReleaseCover } from "@/components/release/ReleaseCover";
import { AnimatedText } from "@/components/AnimatedText";
import { urlFor } from "@/lib/sanityImage";
import { portableTextComponents } from "@/lib/portableTextComponents";
import { ARTIST_PLACEHOLDER_SRC } from "@/lib/constants";
import { Breadcrumb } from "@/components/Breadcrumb";
import { ArtistCardCompact } from "@/components/artist/ArtistCardCompact";
import { ReleaseCard, type ReleaseCardData } from "@/components/release/ReleaseCard";
import { formatYears, type ArtistCardData, type ComposerCardData } from "@/components/artist/types";
import type { SanityImageSource } from "@sanity/image-url";

export const dynamicParams = true;
export const revalidate = 86400;

type BlogDetail = {
  title?: string;
  subtitle?: string;
  slug?: string;
  author?: string;
  publishDate?: string;
  category?: string;
  featuredImage?: SanityImageSource;
  content?: any;
  releases?: ReleaseCardData[];
  artists?: ArtistCardData[];
  composers?: ComposerCardData[];
};

const BLOG_DETAIL_QUERY = defineQuery(`
*[_type == "blog" && slug.current == $slug][0]{
  title,
  subtitle,
  "slug": slug.current,
  author,
  publishDate,
  category,
  featuredImage,
  content[]{
    ...,
    _type == "image" => {
      ...,
      asset->
    }
  },
  "releases": releases[]->{
    _id,
    name,
    albumArtist,
    catalogNo,
    releaseDate,
    "slug": slug.current,
    albumCover
  },
  "artists": artists[]->{
    _id,
    name,
    role,
    "slug": slug.current,
    image
  },
  "composers": composers[]->{
    _id,
    name,
    sortKey,
    "slug": slug.current,
    birthYear,
    deathYear,
    image
  }
}
`);

const getBlog = cache(async (slug: string) => {
  try {
    return await sanity.fetch<BlogDetail>(BLOG_DETAIL_QUERY, { slug });
  } catch (error) {
    console.error("Failed to fetch blog:", error);
    return null;
  }
});

const BLOG_SLUGS_QUERY = defineQuery(
  `*[_type == "blog" && defined(slug.current)]{ "slug": slug.current }`,
);

export async function generateStaticParams() {
  const slugs = await sanity.fetch<Array<{ slug: string }>>(BLOG_SLUGS_QUERY);

  return slugs.map((b) => ({ slug: b.slug }));
}

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata> {
  const { slug: rawSlug } = await params;
  const slug = rawSlug.toLowerCase();

  const blog = await getBlog(slug);
  if (!blog) notFound();

  const description = blog.subtitle ?? `${blog.title} • Read more on the TRPTK blog.`;

  const ogImage = blog.featuredImage
    ? urlFor(blog.featuredImage).width(1200).height(630).url()
    : undefined;

  return {
    title: `${blog.title}`,
    description,
    alternates: { canonical: `/blog/${slug}` },
    openGraph: {
      title: blog.title,
      description,
      type: "article",
      ...(blog.publishDate && { publishedTime: blog.publishDate }),
      ...(blog.author && { authors: [blog.author] }),
      ...(ogImage && {
        images: [{ url: ogImage, width: 1200, height: 630, alt: blog.title }],
      }),
    },
    twitter: {
      card: "summary_large_image",
      title: blog.title,
      description,
      ...(ogImage && { images: [ogImage] }),
    },
  };
}

function formatPublishDate(dateString?: string) {
  if (!dateString) return null;
  return new Intl.DateTimeFormat("en-US", {
    day: "numeric",
    month: "long",
    year: "numeric",
  }).format(new Date(dateString));
}


export default async function BlogPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  if (!slug) notFound();

  const normalizedSlug = slug.toLowerCase();
  if (slug !== normalizedSlug) {
    redirect(`/blog/${normalizedSlug}`);
  }

  const blog = await getBlog(slug);
  if (!blog) notFound();

  const displayDate = formatPublishDate(blog.publishDate);
  const artists = blog.artists ?? [];
  const composers = (blog.composers ?? []).sort((a, b) =>
    (a.sortKey ?? "").localeCompare(b.sortKey ?? ""),
  );
  const releases = blog.releases ?? [];

  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    headline: blog.title,
    url: `https://trptk.com/blog/${slug}`,
    ...(blog.publishDate && { datePublished: blog.publishDate }),
    ...(blog.author && {
      author: { "@type": "Person", name: blog.author },
    }),
    ...(blog.featuredImage && {
      image: urlFor(blog.featuredImage).width(1200).url(),
    }),
    ...(blog.subtitle && { description: blog.subtitle }),
    publisher: {
      "@type": "Organization",
      name: "TRPTK",
      url: "https://trptk.com",
    },
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, "\\u003c") }}
      />
      <main className="mx-auto my-auto max-w-300 px-6 py-12 font-silka md:px-8 md:py-16 2xl:max-w-400">
        {/* Hero */}
        <div className="mx-auto grid grid-cols-1 gap-10 sm:grid-cols-2 sm:gap-8 md:gap-12 lg:gap-20">
          <div className="flex-1 content-center">
            <ReleaseCover
              src={blog.featuredImage ? urlFor(blog.featuredImage).url() : ARTIST_PLACEHOLDER_SRC}
              alt={blog.title ? `Featured image for ${blog.title}` : "Blog post image"}
            />
          </div>

          <div className="flex-1 content-center">
            <Breadcrumb
              crumbs={[
                { label: "Blog", href: "/blog" },
                ...(blog.category ? [{ label: blog.category, href: `/blog?category=${encodeURIComponent(blog.category)}` }] : []),
              ]}
            />
            <AnimatedText
              text={blog.title ?? "Untitled post"}
              as="h1"
              className="mb-2 font-argesta text-3xl break-words"
            />
            {blog.subtitle && (
              <AnimatedText
                text={blog.subtitle}
                as="h2"
                className="mb-4 font-silka text-base break-words text-lightsec dark:text-darksec"
                delay={0.25}
              />
            )}
            {(blog.author || displayDate) && (
              <p className="text-sm text-lightsec dark:text-darksec">
                {blog.author && <>Posted by {blog.author}</>}
                {blog.author && displayDate && <> on </>}
                {!blog.author && displayDate && <>Posted on </>}
                {displayDate}
              </p>
            )}
          </div>
        </div>

        {/* Content */}
        {blog.content && (
          <section className="mx-auto mt-16 max-w-200 sm:mt-20">
            <article className="prose max-w-none text-lighttext dark:text-darktext dark:prose-invert prose-h2:!mt-[3em] prose-h2:font-silkasb prose-h2:text-base prose-strong:font-silkasb">
              <PortableText value={blog.content} components={portableTextComponents} />
            </article>
          </section>
        )}

        {/* Related releases */}
        {releases.length > 0 && (
          <section className="mx-auto mt-16 max-w-200 sm:mt-20">
            <AnimatedText text="Related releases" as="h2" className="mb-4 font-argesta text-2xl" />
            <div className="grid grid-cols-2 gap-6 sm:gap-8 md:grid-cols-3">
              {releases.map((r) => (
                <ReleaseCard key={r._id} release={r} />
              ))}
            </div>
          </section>
        )}

        {/* Related artists & composers */}
        {(artists.length > 0 || composers.length > 0) && (
          <section className="mx-auto mt-16 grid max-w-200 grid-cols-1 gap-16 sm:mt-20 md:grid-cols-2 md:gap-12 lg:gap-20">
            {artists.length > 0 && (
              <div>
                <AnimatedText
                  text="Related artists"
                  as="h2"
                  className="mb-4 font-argesta text-2xl"
                />
                <ul className="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-1">
                  {artists.map((artist) => (
                    <ArtistCardCompact
                      key={artist._id}
                      name={artist.name}
                      subtitle={artist.role}
                      image={artist.image}
                      href={artist.slug ? `/artist/${artist.slug}` : "/artists/"}
                    />
                  ))}
                </ul>
              </div>
            )}

            {composers.length > 0 && (
              <div>
                <AnimatedText
                  text="Related composers"
                  as="h2"
                  className="mb-4 font-argesta text-2xl"
                />
                <ul className="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-1">
                  {composers.map((composer) => (
                    <ArtistCardCompact
                      key={composer._id}
                      name={composer.name}
                      subtitle={formatYears(composer.birthYear, composer.deathYear)}
                      image={composer.image}
                      href={composer.slug ? `/composer/${composer.slug}` : "/composers/"}
                      label="Composer"
                    />
                  ))}
                </ul>
              </div>
            )}
          </section>
        )}
      </main>
    </>
  );
}
