import type { Metadata } from "next";
import { notFound, redirect } from "next/navigation";
import { cache } from "react";
import { defineQuery } from "next-sanity";
import { sanity } from "@/lib/sanity";
import { ArtistReleasesTab, type ArtistRelease } from "@/components/artist/ArtistReleasesTab";
import { ReleaseCover } from "@/components/release/ReleaseCover";
import { AnimatedText } from "@/components/AnimatedText";
import { TabsClient, type TabDef } from "@/components/TabsClient";
import { PortableText } from "@portabletext/react";
import { urlFor } from "@/lib/sanityImage";
import { portableTextComponents } from "@/lib/portableTextComponents";
import { ARTIST_PLACEHOLDER_SRC } from "@/lib/constants";
import { Breadcrumb } from "@/components/Breadcrumb";


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

type Work = {
  title?: string;
  slug?: string;
  description?: any;
  composerName?: string;
  composerSlug?: string;
  composerImage?: any;
  arrangerName?: string;
  releases?: ArtistRelease[];
};

const WORK_DETAIL_QUERY = defineQuery(`
*[_type == "work" && slug.current == $slug][0]{
  title,
  description,
  "slug": slug.current,
  "composerName": composer->name,
  "composerSlug": composer->slug.current,
  "composerImage": composer->image,
  "arrangerName": arranger->name,

  "releases": *[
    _type == "release" &&
    count(tracks[work->slug.current == $slug]) > 0
  ]
  | order(releaseDate desc, catalogNo desc) {
    _id,
    name,
    albumArtist,
    catalogNo,
    "slug": slug.current,
    releaseDate,
    albumCover,
    genre,
    instrumentation
  }
}
`);

const getWork = cache(async (slug: string) => {
  try {
    return await sanity.fetch<Work>(WORK_DETAIL_QUERY, { slug });
  } catch (error) {
    console.error("Failed to fetch work:", error);
    return null;
  }
});

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

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

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

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

  const work = await getWork(slug);
  if (!work) notFound();

  const subtitle = work.arrangerName
    ? `${work.composerName} (arr. ${work.arrangerName})`
    : (work.composerName ?? "");

  const description = `Explore releases featuring ${work.title} by ${subtitle} on TRPTK.`;

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

  return {
    title: `${work.title} ${subtitle ? ` • ${subtitle}` : ""}`,
    description,
    alternates: { canonical: `/work/${slug}` },
    openGraph: {
      title: work.title,
      description: `${subtitle}${work.releases?.length ? ` - ${work.releases.length} release(s)` : ""}`,
      type: "music.album",
      ...(ogImage && { images: [{ url: ogImage, width: 1200, height: 630, alt: `${work.title} by ${subtitle}` }] }),
    },
    twitter: {
      card: "summary_large_image",
      title: work.title,
      description,
      ...(ogImage && { images: [ogImage] }),
    },
  };
}

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

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

  const work = await getWork(slug);
  if (!work) notFound();

  const displayTitle = work.title ?? "";
  const displaySubtitle = work.arrangerName
    ? `${work.composerName} (arr. ${work.arrangerName})`
    : (work.composerName ?? "");

  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "MusicComposition",
    name: work.title,
    url: `https://trptk.com/work/${slug}`,
    ...(work.composerName && {
      composer: { "@type": "Person", name: work.composerName },
    }),
    ...(work.composerImage && {
      image: urlFor(work.composerImage).width(800).url(),
    }),
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, "\\u003c") }}
      />
      <main className="mx-auto my-auto max-w-250 px-6 py-12 font-silka md:px-8 md:py-16">
        <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={work.composerImage ? urlFor(work.composerImage).url() : ARTIST_PLACEHOLDER_SRC}
              alt={`Photo of ${work.composerName}`}
            />
          </div>

          <div className="flex-1 content-center">
            <Breadcrumb crumbs={[
              { label: "Composers", href: "/composers" },
              ...(work.composerName && work.composerSlug
                ? [{ label: work.composerName, href: `/composer/${work.composerSlug}` }]
                : []),
            ]} />
            <AnimatedText
              text={displayTitle}
              as="h1"
              className="mb-2 font-argesta text-3xl break-words"
            />
            <AnimatedText
              text={displaySubtitle}
              as="h2"
              className="font-silka text-base break-words text-lightsec dark:text-darksec"
              delay={0.25}
            />
          </div>
        </div>

        <WorkTabs description={work.description} releases={work.releases ?? []} />
      </main>
    </>
  );
}

function WorkTabs({ description, releases }: { description?: any; releases: ArtistRelease[] }) {
  const tabs: TabDef[] = [
    {
      id: "description",
      label: "Description",
      content: (
        <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">
          <h2 className="sr-only">Description</h2>
          {description ? (
            <PortableText value={description} components={portableTextComponents} />
          ) : (
            <p>No description available for this work yet.</p>
          )}
        </article>
      ),
    },
  ];

  if (releases.length > 0) {
    tabs.push({
      id: "releases",
      label: "Releases",
      content: <ArtistReleasesTab releases={releases} />,
    });
  }

  return <TabsClient defaultTabId="description" tabs={tabs} />;
}
