import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { fetchQuery } from "convex/nextjs";
import { api } from "../../../../../../../../convex/_generated/api";
import { ProductDetailContent } from "@/components/product-detail/ProductDetailContent";
import type { ProductDetailParams } from "@/lib/product-detail/constants";
import { getProductDetailPath } from "@/lib/product-detail/constants";
import { isPetCategorySlug } from "@/lib/shop/constants";
import { ProductDetailStructuredData } from "@/components/product-detail/ProductDetailStructuredData";

// PPR: when using Next.js canary, uncomment so PDP uses Partial Prerendering:
// export const experimental_ppr = true;

type Props = {
  params: Promise<ProductDetailParams>;
};

function isValidSlug(slug: string): boolean {
  return typeof slug === "string" && slug.length > 0 && !slug.includes("/");
}

/** Strip HTML tags for plain-text meta description. */
function stripHtml(html: string): string {
  return html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
}

/** Meta description: 150–160 chars per SEO rule. */
function metaDescription(
  seoDescription: string | undefined | null,
  rawDescription: string | undefined | null,
): string | undefined {
  if (seoDescription && seoDescription.trim()) {
    return seoDescription.slice(0, 160);
  }
  if (rawDescription && rawDescription.trim()) {
    return stripHtml(rawDescription).slice(0, 160);
  }
  return undefined;
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { category, subCategory, slug } = await params;
  if (!isPetCategorySlug(category) || !isValidSlug(slug)) {
    return { title: "Not Found" };
  }
  const resolved = await fetchQuery(api.categories.getByPath, {
    categorySlug: category,
    subCategorySlug: subCategory,
  });
  if (!resolved) {
    return { title: "Not Found" };
  }
  const product = await fetchQuery(api.products.getBySlug, { slug });
  if (!product) {
    return { title: "Not Found" };
  }
  const title = product.seoTitle ?? product.name;
  const description = metaDescription(
    product.seoDescription,
    product.description,
  );
  const canonicalPath = getProductDetailPath(category, subCategory, slug);
  const baseUrl =
    process.env.NEXT_PUBLIC_APP_URL ?? process.env.NEXT_PUBLIC_STOREFRONT_URL ?? "";
  const canonical = baseUrl ? `${baseUrl.replace(/\/$/, "")}${canonicalPath}` : undefined;
  const firstImage =
    product.images && product.images.length > 0 ? product.images[0] : null;
  const openGraphImages =
    firstImage?.url != null
      ? [{ url: firstImage.url, alt: firstImage.alt ?? product.name }]
      : undefined;

  return {
    title,
    description,
    alternates: canonical ? { canonical } : undefined,
    openGraph: {
      title,
      description: description ?? undefined,
      url: canonical,
      images: openGraphImages,
      type: "website",
    },
    twitter: {
      card: "summary_large_image",
      title,
      description: description ?? undefined,
      images: firstImage?.url != null ? [firstImage.url] : undefined,
    },
  };
}

export default async function ProductDetailPage({ params }: Props) {
  const { category, subCategory, slug } = await params;

  if (!isPetCategorySlug(category)) {
    notFound();
  }

  const resolved = await fetchQuery(api.categories.getByPath, {
    categorySlug: category,
    subCategorySlug: subCategory,
  });
  if (!resolved) {
    notFound();
  }

  if (!isValidSlug(slug)) {
    notFound();
  }

  const product = await fetchQuery(api.products.getBySlug, { slug });
  if (!product) {
    notFound();
  }

  return (
    <>
      <ProductDetailStructuredData
        category={category}
        subCategory={subCategory}
        slug={slug}
        productName={product.name}
        subCategoryName={resolved.name}
      />
      <ProductDetailContent
        category={category}
        subCategory={subCategory}
        slug={slug}
        categoryId={product.categoryId}
      />
    </>
  );
}
