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 { ArtistTabs } from "@/components/artist/ArtistTabs";
import { ArtistReleasesTab, type ArtistRelease } from "@/components/artist/ArtistReleasesTab";
import { ArtistConcertsTab } from "@/components/artist/ArtistConcertsTab";
import { ReleaseCover } from "@/components/release/ReleaseCover";
import { AnimatedText } from "@/components/AnimatedText";
import { urlFor } from "@/lib/sanityImage";
import { ARTIST_PLACEHOLDER_SRC } from "@/lib/constants";
import { Breadcrumb } from "@/components/Breadcrumb";
import type { ConcertData } from "@/components/concert/ConcertTable";

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

type Artist = {
  name?: string;
  slug?: string;
  role?: string;
  bio?: any;
  image?: any;
  releases?: ArtistRelease[];
  upcomingConcerts?: ConcertData[];
  pastConcerts?: ConcertData[];
};

const CONCERT_PROJECTION = `{
  _id,
  title,
  subtitle,
  date,
  time,
  locationName,
  city,
  country,
  "artists": artists[]->{ _id, name, "slug": slug.current },
  ticketUrl
}`;

const ARTIST_DETAIL_QUERY = defineQuery(`
*[_type == "artist" && slug.current == $slug][0]{
  name,
  role,
  "slug": slug.current,
  bio,
  image,
  "releases": *[
    _type == "release" &&
    references(^._id)
  ]
  | order(releaseDate desc, catalogNo desc) {
    _id,
    name,
    albumArtist,
    catalogNo,
    "slug": slug.current,
    releaseDate,
    albumCover,
    genre,
    instrumentation
  },
  "upcomingConcerts": *[
    _type == "concert" &&
    references(^._id) &&
    date >= $today
  ] | order(date asc, time asc) ${CONCERT_PROJECTION},
  "pastConcerts": *[
    _type == "concert" &&
    references(^._id) &&
    date < $today
  ] | order(date desc, time desc) ${CONCERT_PROJECTION}
}
`);

const getArtist = cache(async (slug: string) => {
  const today = new Date().toISOString().slice(0, 10);
  try {
    return await sanity.fetch<Artist>(ARTIST_DETAIL_QUERY, { slug, today });
  } catch (error) {
    console.error("Failed to fetch artist:", error);
    return null;
  }
});

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

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

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

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

  const artist = await getArtist(slug);
  if (!artist) notFound();

  const description = `Explore ${artist.name}'s releases${artist.role ? `, ${artist.role}` : ""} on TRPTK.`;

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

  return {
    title: `${artist.name} ${artist.role ? ` • ${artist.role}` : ""}`,
    description,
    alternates: { canonical: `/artist/${slug}` },
    openGraph: {
      title: artist.name,
      description: `${artist.role || "Artist"}${artist.releases?.length ? ` - ${artist.releases.length} releases` : ""}`,
      type: "profile",
      ...(ogImage && { images: [{ url: ogImage, width: 1200, height: 630, alt: artist.name }] }),
    },
    twitter: {
      card: "summary_large_image",
      title: artist.name,
      description,
      ...(ogImage && { images: [ogImage] }),
    },
  };
}

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

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

  const artist = await getArtist(slug);
  if (!artist) notFound();

  const displayName = artist.name ?? "";
  const displayRole = artist.role ?? "";

  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "Person",
    name: artist.name,
    url: `https://trptk.com/artist/${slug}`,
    ...(artist.role && { jobTitle: artist.role }),
    ...(artist.image && { image: urlFor(artist.image).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={artist.image ? urlFor(artist.image).url() : ARTIST_PLACEHOLDER_SRC}
              alt={`Photo of ${artist.name}`}
            />
          </div>

          <div className="flex-1 content-center">
            <Breadcrumb crumbs={[{ label: "Artists", href: "/artists" }]} />
            <AnimatedText
              text={displayName}
              as="h1"
              className="mb-2 font-argesta text-3xl break-words"
            />
            <AnimatedText
              text={displayRole}
              as="h2"
              className="font-silka text-base break-words text-lightsec dark:text-darksec"
              delay={0.25}
            />
          </div>
        </div>

        <ArtistTabs
          bio={artist.bio}
          concerts={
            artist.upcomingConcerts?.length || artist.pastConcerts?.length ? (
              <ArtistConcertsTab
                upcoming={artist.upcomingConcerts ?? []}
                past={artist.pastConcerts ?? []}
              />
            ) : undefined
          }
          hasReleases={!!artist.releases?.length}
          releasesTab={<ArtistReleasesTab releases={artist.releases ?? []} />}
        />
      </main>
    </>
  );
}
