import { notFound } from "next/navigation";
import type { Metadata } from "next";
import { BlockRenderer } from "@/components/storefront/block-renderer";
import { formatAddress, normalizeHours } from "@/components/storefront/hours";
import { loadProductsForBlocks } from "@/components/storefront/products";
import { buildContext, getPage, getShell } from "./storefront-data";

const DAY_SCHEMA = [
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
] as const;

/**
 * Both the landing page and every sub-page render through here — the only
 * difference between `/s/{slug}` and `/s/{slug}/hours` is which page slug is
 * fetched.
 */
export async function StorefrontPageView({
  slug,
  pageSlug,
}: {
  slug: string;
  pageSlug: string;
}) {
  const [shell, page] = await Promise.all([getShell(slug), getPage(slug, pageSlug)]);

  if (!shell || !page) notFound();

  const ctx = await buildContext(slug, shell);
  const blocks = page.data.blocks ?? [];
  const productsByBlock = await loadProductsForBlocks(blocks, shell.store?.id);

  return (
    <>
      {page.data.is_home && (
        <script
          type="application/ld+json"
          // Structured data for the landing page only — a store's hours and
          // address belong to the business, not to each sub-page.
          dangerouslySetInnerHTML={{ __html: JSON.stringify(localBusinessJsonLd(shell)) }}
        />
      )}
      <BlockRenderer blocks={blocks} ctx={ctx} productsByBlock={productsByBlock} />
    </>
  );
}

export async function buildStorefrontMetadata(
  slug: string,
  pageSlug: string,
): Promise<Metadata> {
  const page = await getPage(slug, pageSlug);

  if (!page) {
    return {
      title: "Page not found",
      robots: { index: false, follow: true },
    };
  }

  const shell = page.meta.storefront;
  const storeName = shell.store?.name ?? "";
  const isHome = page.data.is_home;

  const title = page.data.seo?.title || (isHome ? storeName : `${page.data.title} — ${storeName}`);
  const description =
    page.data.seo?.description ||
    shell.seo?.description ||
    shell.tagline ||
    `Shop ${storeName} online.`;

  // Canonical always points at the slug path so a store reachable on both its
  // own domain and alqove.com is indexed once.
  const canonical = isHome
    ? shell.canonical_url
    : `${shell.canonical_url}/${page.data.slug}`;

  const image = shell.seo?.og_image_url ?? undefined;

  return {
    title,
    description,
    alternates: canonical ? { canonical } : undefined,
    openGraph: {
      title,
      description,
      type: "website",
      url: canonical,
      siteName: storeName,
      images: image ? [{ url: image }] : undefined,
    },
    twitter: {
      card: image ? "summary_large_image" : "summary",
      title,
      description,
      images: image ? [image] : undefined,
    },
  };
}

function localBusinessJsonLd(shell: Awaited<ReturnType<typeof getShell>>) {
  if (!shell) return {};

  const store = shell.store;
  const address = formatAddress(store);

  const openingHours = normalizeHours(shell.hours)
    .filter((row) => !row.closed)
    .map((row) => {
      const entry = (shell.hours ?? []).find((h) => h?.day === row.day);
      return {
        "@type": "OpeningHoursSpecification",
        dayOfWeek: `https://schema.org/${DAY_SCHEMA[row.day]}`,
        opens: entry?.open,
        closes: entry?.close,
      };
    });

  return {
    "@context": "https://schema.org",
    "@type": "Store",
    name: store?.name,
    description: shell.seo?.description ?? shell.tagline ?? undefined,
    url: shell.canonical_url,
    image: shell.logo_url ?? store?.logo_image ?? undefined,
    email: shell.contact_email ?? undefined,
    telephone: shell.contact_phone ?? undefined,
    address: address
      ? {
          "@type": "PostalAddress",
          streetAddress: [store?.street1, store?.street2].filter(Boolean).join(", ") || undefined,
          addressLocality: store?.city ?? undefined,
          addressRegion: store?.state ?? undefined,
          postalCode: store?.zip ?? undefined,
          addressCountry: store?.country ?? undefined,
        }
      : undefined,
    openingHoursSpecification: openingHours.length > 0 ? openingHours : undefined,
    aggregateRating:
      store?.review_count && store.review_count > 0 && store.average_rating
        ? {
            "@type": "AggregateRating",
            ratingValue: store.average_rating,
            reviewCount: store.review_count,
          }
        : undefined,
  };
}
