/**
 * Open / QR invitation, `/e/{slug}` (task 2.4, FR-1.2).
 *
 * Public, identical for every visitor, and therefore cacheable with ISR. Carries no guest
 * data at all — task 8.2 asserts that no phone number or email address ever appears in
 * this page's HTML.
 */
import type { Metadata } from "next";
import { notFound } from "next/navigation";

import { InvitationShell } from "@/components/InvitationShell";
import { OpenRsvpInteractive } from "@/components/OpenRsvpInteractive";
import { fetchOpenEvent } from "@/lib/api/server";
import { getDictionary } from "@/lib/i18n";
import { linkPreviewMetadata } from "@/lib/link-preview-metadata";
import { appBaseUrl, turnstileSiteKey } from "@/lib/public-config";
import { toOpenEventView, type Locale } from "@/lib/view-models";

// A bulk send can put hundreds of guests on this page at once, so the API response is
// cached for 60s (see `fetchOpenEvent`), which keeps the spike off the database — the part
// that actually matters for PRD risk #8.
//
// The HTML itself is still rendered per request: a `[slug]` route is only prerendered if
// `generateStaticParams` enumerates the slugs, and doing that requires the API to be
// reachable at build time. With exactly three events that is worth revisiting during the
// Phase 6 load test, where we will have real numbers to justify the build-time coupling.
export const revalidate = 60;

// Deliberately no `searchParams` here. Reading it would opt this route out of static
// rendering entirely, and ISR is what keeps the page cheap when a bulk send puts hundreds
// of guests on it at once. The language toggle therefore lands as a client component in
// task 6.2 rather than as a query parameter.
export default async function OpenEventPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;

  const data = await fetchOpenEvent(slug);
  if (!data) notFound();

  const view = toOpenEventView(data);
  const locale: Locale = view.couple.defaultLocale;
  const dict = getDictionary(locale);

  return (
    <InvitationShell
      event={view.event}
      couple={view.couple}
      locale={locale}
      dict={dict}
      greeting={view.greeting}
      card={view.card}
    >
      <OpenRsvpInteractive
        slug={view.event.slug}
        rsvpOpen={view.rsvpOpen}
        selectableEvents={view.selectableEvents}
        defaultEventType={view.event.type}
        locale={locale}
        dict={dict}
        hostContactPhone={view.couple.hostContactPhone}
        turnstileSiteKey={turnstileSiteKey()}
      />
    </InvitationShell>
  );
}

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata> {
  const { slug } = await params;
  const data = await fetchOpenEvent(slug);
  if (!data) return { title: "Invitation" };

  // The same tags `/i/{token}` emits, from the same model. That the two routes unfurl
  // identically is what makes previewing a tokenized URL safe (design D3).
  return linkPreviewMetadata(toOpenEventView(data).preview, appBaseUrl());
}
