import Image from "next/image";
import Link from "next/link";
import Container from "@/components/ui/Container";
import { ButtonLink } from "@/components/ui/Button";
import DynamicForm from "@/components/forms/DynamicForm";
import { FOCUS_AREA_ICONS, ONBOARDING_STEP_ICONS, PORTFOLIO_AREA_ICONS } from "@/components/icons";
import { getEntries, getFormSchema, getStoreProducts, type WebBlock } from "@/lib/api";
import type { Entry } from "@/lib/types";

/**
 * Renders a page's block tree. Every repeatable grid (focus areas,
 * sponsorship benefits, onboarding steps, portfolio areas, get-involved
 * audiences) is driven by a `collectionKey` prop pointing at a
 * fact_web_entries collection — adding/reordering/editing content is a CMS
 * change in ABOS, never a code change here.
 */
export default function BlockRenderer({ blocks }: { blocks: WebBlock[] }) {
  return (
    <>
      {blocks.map((block) => <BlockNode key={block.id} block={block} />)}
    </>
  );
}

async function BlockNode({ block }: { block: WebBlock }) {
  switch (block.type) {
    case "hero":
      return <HeroBlock props={block.props} />;
    case "ticker":
      return <TickerBlock props={block.props} />;
    case "richText":
      return <RichTextBlock props={block.props} />;
    case "button":
      return <ButtonBlock props={block.props} />;
    case "numberedGrid":
      return <NumberedGridBlock props={block.props} />;
    case "pricedGrid":
      return <PricedGridBlock props={block.props} />;
    case "pillarGrid":
      return <PillarGridBlock props={block.props} />;
    case "flatList":
      return <FlatListBlock props={block.props} />;
    case "faqAccordion":
      return <FaqAccordionBlock props={block.props} />;
    case "ctaBanner":
      return <CtaBannerBlock props={block.props} />;
    case "image":
      return <ImageBlock props={block.props} />;
    case "columns":
      return <ColumnsBlock props={block.props} children={block.children} />;
    case "spacer":
      return <SpacerBlock props={block.props} />;
    case "productGrid":
      return <ProductGridBlock props={block.props} />;
    case "formEmbed":
      return <FormEmbedBlock props={block.props} />;
    case "testimonial":
      return <TestimonialBlock props={block.props} />;
    case "sponsorshipSplit":
      return <SponsorshipSplitBlock props={block.props} />;
    case "getInvolvedSplit":
      return <GetInvolvedSplitBlock props={block.props} />;
    default:
      console.error(`[BlockRenderer] unknown block type: ${block.type}`);
      return null;
  }
}

function str(v: unknown, fallback = ""): string {
  return typeof v === "string" ? v : fallback;
}

/** The small mono, underlined "X →" link used next to a section's eyebrow. */
function ViewAllLink({ label, href }: { label: string; href: string }) {
  return (
    <a href={href} className="text-[13px] uppercase tracking-[0.1em] border-b-2 border-teal pb-0.5 text-ink whitespace-nowrap">
      {label}
    </a>
  );
}

function HeroBlock({ props }: { props: Record<string, unknown> }) {
  const eyebrow = str(props.eyebrow);
  const heading = str(props.heading);
  const subheading = str(props.subheading);
  const ctaLabel = str(props.ctaLabel);
  const ctaHref = str(props.ctaHref, "#");
  const secondaryLabel = str(props.secondaryLabel);
  const secondaryHref = str(props.secondaryHref, "#");
  const statusItems = Array.isArray(props.statusItems) ? (props.statusItems as string[]) : [];
  const visionText = str(props.visionText);
  const visionLabel = str(props.visionLabel, "Our Vision");
  const badges = Array.isArray(props.badges) ? (props.badges as { title: string; subtitle: string; accent?: string }[]) : [];

  return (
    <section id="top" className="relative overflow-hidden bg-ink text-white">
      {/* Large translucent concentric circles behind the headline, matching the source hero background. */}
      <div aria-hidden className="pointer-events-none absolute -right-40 -top-24 h-[520px] w-[520px] rounded-full border border-white/10" />
      <div aria-hidden className="pointer-events-none absolute -right-10 top-10 h-[380px] w-[380px] rounded-full border border-white/10" />
      <div aria-hidden className="pointer-events-none absolute right-20 top-32 h-[240px] w-[240px] rounded-full border border-white/10" />

      <Container className="relative grid grid-cols-1 lg:grid-cols-2 gap-12 items-start pt-16 pb-24 lg:pt-24 lg:pb-28">
        <div>
          {eyebrow ? (
            <span className="inline-flex items-center gap-2 text-xs tracking-[0.14em] uppercase text-white/70">
              <span className="h-px w-6 bg-teal" /> {eyebrow}
            </span>
          ) : null}
          <h1 className="mt-5 font-heading font-extrabold text-4xl md:text-5xl leading-[1.05] tracking-tight max-w-2xl">
            {heading}
          </h1>
          {subheading ? <p className="mt-4 text-white/70 leading-relaxed max-w-xl text-lg">{subheading}</p> : null}
          <div className="mt-8 flex flex-wrap items-center gap-6">
            {ctaLabel ? (
              <Link href={ctaHref} className="inline-flex items-center gap-1.5 rounded-full bg-teal px-6 py-3.5 text-sm font-bold text-ink hover:brightness-95">
                {ctaLabel} <span aria-hidden>↗</span>
              </Link>
            ) : null}
            {secondaryLabel ? (
              <Link href={secondaryHref} className="inline-flex items-center gap-1.5 text-sm font-semibold text-white hover:text-teal">
                {secondaryLabel} <span aria-hidden>→</span>
              </Link>
            ) : null}
          </div>
        </div>

        <div className="relative mt-6 lg:mt-2">
          {visionText ? (
            <div className="rounded-card bg-ink-2/80 border border-white/10 p-7 max-w-sm ml-auto">
              <span className="text-xs tracking-[0.14em] uppercase text-white/50">{visionLabel}</span>
              <p className="mt-3 font-heading font-semibold text-xl leading-snug">{visionText}</p>
              {statusItems.length > 0 ? (
                <div className="mt-6 flex items-center gap-4 text-xs text-white/50">
                  {statusItems.map((item) => <span key={item}>{item}</span>)}
                </div>
              ) : null}
            </div>
          ) : null}

          {badges.map((badge, i) => (
            <div
              key={badge.title}
              className="mt-4 flex items-center gap-3 rounded-2xl bg-ink-2 border border-white/10 p-4 max-w-xs"
              style={i === 0 ? { marginLeft: "auto" } : undefined}
            >
              <span
                className="flex h-9 w-9 flex-none items-center justify-center rounded-full text-xs font-bold text-ink"
                style={{ background: badge.accent || "var(--teal)" }}
              >
                {badge.title.slice(0, 2).toUpperCase()}
              </span>
              <div>
                <p className="text-sm font-semibold text-white">{badge.title}</p>
                <p className="text-xs text-white/50">{badge.subtitle}</p>
              </div>
            </div>
          ))}
        </div>
      </Container>
    </section>
  );
}

/** The solid-teal rotating status strip directly under the hero. */
function TickerBlock({ props }: { props: Record<string, unknown> }) {
  const lines = Array.isArray(props.lines) ? (props.lines as string[]) : [];
  if (lines.length === 0) return null;
  return (
    <div className="bg-teal text-ink">
      <Container className="flex flex-wrap items-center justify-center gap-x-3 gap-y-2 py-4 text-xs md:text-sm font-bold uppercase tracking-[0.08em] text-center">
        {lines.map((line, i) => (
          <span key={line} className="flex items-center gap-3">
            {i > 0 ? <span aria-hidden>·</span> : null}
            {line}
          </span>
        ))}
      </Container>
    </div>
  );
}

function RichTextBlock({ props }: { props: Record<string, unknown> }) {
  const anchor = str(props.anchor) || undefined;
  return (
    <section id={anchor} className="py-16">
      <Container className="max-w-[24ch] md:max-w-none">
        <div className="prose-nsp" dangerouslySetInnerHTML={{ __html: str(props.html) }} />
      </Container>
    </section>
  );
}

function ButtonBlock({ props }: { props: Record<string, unknown> }) {
  const variant = props.variant === "outline" ? "outline" : "primary";
  return (
    <div className="py-4">
      <ButtonLink href={str(props.href, "#")} variant={variant}>
        {str(props.label)}
      </ButtonLink>
    </div>
  );
}

const NUMBERED_ICON_SETS: Record<string, Record<string, (p: { className?: string; style?: React.CSSProperties }) => JSX.Element>> = {
  "focus-areas": FOCUS_AREA_ICONS,
  "onboarding-steps": ONBOARDING_STEP_ICONS
};

/** Numbered grid — used for focus-areas (dark section, large icon cards) and
 *  onboarding-steps (light/lavender section, compact icon cards). */
async function NumberedGridBlock({ props }: { props: Record<string, unknown> }) {
  const eyebrow = str(props.eyebrow);
  const heading = str(props.heading);
  const anchor = str(props.anchor) || undefined;
  const collectionKey = str(props.collectionKey);
  const variant = props.variant === "dark" ? "dark" : "light";
  const compact = props.compact === true;
  const entries = await getEntries(collectionKey);
  if (entries.length === 0) return null;
  const icons = NUMBERED_ICON_SETS[collectionKey] || {};

  const sectionClass = variant === "dark" ? "py-16 bg-ink text-white" : "py-16";
  const cardClass = variant === "dark"
    ? "border-b border-white/10 border-r border-white/5 last:border-r-0 p-6"
    : "border-b border-neutral-400 border-r border-neutral-300 last:border-r-0 p-6";
  const numberClass = variant === "dark" ? "text-xs text-white/40" : "text-xs text-ink-faint";
  const bodyClass = variant === "dark" ? "text-sm text-white/60 leading-relaxed" : "text-sm text-ink-soft leading-relaxed";
  const gridCols = compact ? "sm:grid-cols-2 lg:grid-cols-4" : "sm:grid-cols-2 lg:grid-cols-3";

  return (
    <section id={anchor} className={sectionClass}>
      <Container>
        {(eyebrow || heading) ? (
          <div className="mb-2">
            {eyebrow ? (
              <span className={`inline-flex items-center gap-2 text-xs tracking-[0.14em] uppercase ${variant === "dark" ? "text-white/60" : "text-ink-muted"}`}>
                <span className="h-px w-6 bg-teal" /> {eyebrow}
              </span>
            ) : null}
            {heading ? <h2 className="mt-3 font-heading font-extrabold text-2xl md:text-3xl max-w-[24ch]">{heading}</h2> : null}
          </div>
        ) : null}
        <div className={`mt-11 grid grid-cols-1 ${gridCols} ${variant === "dark" ? "border-t border-white/10" : "border-t border-neutral-400"}`}>
          {entries.map((entry) => {
            const Icon = icons[entry.slug];
            return (
              <div key={entry.slug} className={cardClass}>
                <div className="flex items-center justify-between mb-3">
                  <span className={numberClass}>{str(entry.fields.number)}</span>
                  {Icon ? <Icon className="h-6 w-6" style={{ color: iconColorFor(entry.slug) }} /> : null}
                </div>
                <h3 className="font-heading font-bold text-lg">{entry.title}</h3>
                <p className={`mt-2 ${bodyClass}`}>{str(entry.fields.description)}</p>
              </div>
            );
          })}
        </div>
      </Container>
    </section>
  );
}

const ICON_COLOR_CYCLE = ["var(--teal)", "var(--purple)", "var(--orange)", "var(--pink)", "var(--blue)", "var(--orange)"];
function iconColorFor(slug: string): string {
  let hash = 0;
  for (let i = 0; i < slug.length; i++) hash = (hash * 31 + slug.charCodeAt(i)) >>> 0;
  return ICON_COLOR_CYCLE[hash % ICON_COLOR_CYCLE.length] ?? "var(--teal)";
}

/** "cards" variant = the four packaged solutions (bordered, shadowed, mint bg). */
async function PricedGridBlock({ props }: { props: Record<string, unknown> }) {
  const eyebrow = str(props.eyebrow);
  const variant = props.variant === "list" ? "list" : "cards";
  const viewAllLabel = str(props.viewAllLabel);
  const viewAllHref = str(props.viewAllHref, "#");
  const entries = await getEntries(str(props.collectionKey));
  if (entries.length === 0) return null;

  if (variant === "list") {
    return (
      <section className="py-16">
        <Container>
          <div className="flex flex-wrap items-baseline justify-between gap-3.5 mb-5">
            {eyebrow ? <span className="text-xs tracking-[0.14em] uppercase text-ink-muted">{eyebrow}</span> : null}
            {viewAllLabel ? <ViewAllLink label={viewAllLabel} href={viewAllHref} /> : null}
          </div>
          <div className="grid grid-cols-1 sm:grid-cols-2 border-t border-neutral-300">
            {entries.map((entry) => (
              <div key={entry.slug} className="flex items-baseline justify-between gap-3 py-[14px] px-3 border-b border-neutral-300 text-base font-medium">
                <span className="text-ink">{entry.title}</span>
                <span className="text-xs text-ink-faint">{str(entry.fields.priceFrom, "Scoped")}</span>
              </div>
            ))}
          </div>
        </Container>
      </section>
    );
  }

  return (
    <section className="py-16">
      <Container>
        <div className="flex flex-wrap items-baseline justify-between gap-4 mb-8">
          {eyebrow ? <span className="text-xs tracking-[0.14em] uppercase text-ink-muted">{eyebrow}</span> : null}
          {viewAllLabel ? <ViewAllLink label={viewAllLabel} href={viewAllHref} /> : null}
        </div>
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
          {entries.map((entry) => {
            const cardBody = (
              <>
                <span className="text-[11px] tracking-[0.12em] uppercase text-teal">{entry.title}</span>
                {entry.fields.tagline ? <h3 className="font-heading font-bold text-lg text-ink leading-snug">{str(entry.fields.tagline)}</h3> : null}
                {entry.fields.description ? <p className="text-sm text-ink-soft leading-relaxed flex-1">{str(entry.fields.description)}</p> : null}
                <p className="text-xs text-ink-faint">{str(entry.fields.priceFrom, "Scoped")}</p>
              </>
            );
            const cardClass = "flex flex-col gap-3.5 rounded-card border border-neutral-400 shadow-1 bg-neutral-100 p-6";
            const solutionHref = entry.slug === "go-digital" ? "/go-digital" : entry.slug === "abos-solution" ? "/abos" : null;
            return solutionHref ? (
              <Link key={entry.slug} href={solutionHref} className={`${cardClass} hover:border-teal transition-colors`}>
                {cardBody}
              </Link>
            ) : (
              <div key={entry.slug} className={cardClass}>
                {cardBody}
              </div>
            );
          })}
        </div>
      </Container>
    </section>
  );
}

const PILLAR_ICON_SETS: Record<string, Record<string, (p: { className?: string; style?: React.CSSProperties }) => JSX.Element>> = {
  "portfolio-areas": PORTFOLIO_AREA_ICONS
};

/** Pillar grid — three variants: "list" (plain stacked, hairline dividers, no
 *  card — sponsorship-benefits/get-involved-audiences), "cards-icon" (white
 *  cards with a colored icon badge — portfolio-areas/in-action), or the
 *  original bordered "cards" fallback for anything else. */
async function PillarGridBlock({ props }: { props: Record<string, unknown> }) {
  const heading = str(props.heading);
  const description = str(props.description);
  const anchor = str(props.anchor) || undefined;
  const collectionKey = str(props.collectionKey);
  const variant = str(props.variant, "cards");
  const dark = props.dark === true;
  const entries = await getEntries(collectionKey);
  if (entries.length === 0) return null;

  if (variant === "list") {
    return (
      <ListEntries heading={heading} description={description} anchor={anchor} entries={entries} dark={dark} />
    );
  }

  if (variant === "cards-icon") {
    const icons = PILLAR_ICON_SETS[collectionKey] || {};
    return (
      <section id={anchor} className="py-16">
        <Container>
          <div className="max-w-2xl mb-10">
            {heading ? <h2 className="font-heading font-extrabold text-2xl md:text-3xl text-ink">{heading}</h2> : null}
            {description ? <p className="mt-3 text-ink-soft leading-relaxed">{description}</p> : null}
          </div>
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
            {entries.map((entry) => {
              const Icon = icons[entry.slug];
              return (
                <div key={entry.slug} className="rounded-card border border-neutral-400 bg-neutral-100 p-6">
                  {Icon ? (
                    <span
                      className="mb-4 inline-flex h-11 w-11 items-center justify-center rounded-xl"
                      style={{ background: `color-mix(in srgb, ${iconColorFor(entry.slug)} 16%, transparent)` }}
                    >
                      <Icon className="h-5 w-5" style={{ color: iconColorFor(entry.slug) }} />
                    </span>
                  ) : null}
                  <h3 className="font-heading font-bold text-[17px] text-ink mb-2">{entry.title}</h3>
                  <p className="text-sm text-ink-soft leading-relaxed">{str(entry.fields.description)}</p>
                </div>
              );
            })}
          </div>
        </Container>
      </section>
    );
  }

  return (
    <section id={anchor} className="py-16 bg-neutral-100">
      <Container>
        <div className="max-w-2xl mb-10">
          {heading ? <h2 className="font-heading font-extrabold text-2xl md:text-3xl text-ink">{heading}</h2> : null}
          {description ? <p className="mt-3 text-ink-soft leading-relaxed">{description}</p> : null}
        </div>
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
          {entries.map((entry) => (
            <div key={entry.slug} className="border-l-4 border-ink pl-[18px]">
              <h3 className="font-heading font-bold text-[19px] text-ink mb-2">{entry.title}</h3>
              <p className="text-sm text-ink-soft leading-relaxed">{str(entry.fields.description)}</p>
            </div>
          ))}
        </div>
      </Container>
    </section>
  );
}

/** Plain stacked list with hairline dividers — no card, no icon. Shared by
 *  the sponsorship-benefits (light) and get-involved-audiences (dark)
 *  sections, which both use this exact treatment in the source design. */
function ListEntries({
  heading, description, anchor, entries, dark
}: { heading: string; description: string; anchor?: string; entries: Entry[]; dark: boolean }) {
  const titleClass = dark ? "text-white" : "text-ink";
  const bodyClass = dark ? "text-white/60" : "text-ink-soft";
  const lineClass = dark ? "border-white/10" : "border-neutral-300";
  return (
    <div id={anchor}>
      {heading ? <h2 className={`font-heading font-extrabold text-2xl md:text-3xl mb-2 ${titleClass}`}>{heading}</h2> : null}
      {description ? <p className={`mb-6 leading-relaxed ${bodyClass}`}>{description}</p> : null}
      <div className={`border-t ${lineClass}`}>
        {entries.map((entry) => (
          <div key={entry.slug} className={`py-5 border-b ${lineClass}`}>
            <h3 className={`font-heading font-bold text-base mb-1.5 ${titleClass}`}>{entry.title}</h3>
            <p className={`text-sm leading-relaxed ${bodyClass}`}>{str(entry.fields.description)}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

/** Flat divided list — services and industries both use this (no pills/cards). */
async function FlatListBlock({ props }: { props: Record<string, unknown> }) {
  const eyebrow = str(props.eyebrow);
  const viewAllLabel = str(props.viewAllLabel);
  const viewAllHref = str(props.viewAllHref, "#");
  const entries = await getEntries(str(props.collectionKey));
  if (entries.length === 0) return null;
  return (
    <section className="py-16">
      <Container>
        <div className="flex flex-wrap items-baseline justify-between gap-3.5 mb-5">
          {eyebrow ? <span className="text-xs tracking-[0.14em] uppercase text-ink-muted">{eyebrow}</span> : null}
          {viewAllLabel ? <ViewAllLink label={viewAllLabel} href={viewAllHref} /> : null}
        </div>
        <div className="grid grid-cols-1 sm:grid-cols-2 border-t border-neutral-300">
          {entries.map((entry) => (
            <div key={entry.slug} className="py-[14px] px-3 border-b border-neutral-300 text-base font-medium text-ink">
              {entry.title}
            </div>
          ))}
        </div>
      </Container>
    </section>
  );
}

async function FaqAccordionBlock({ props }: { props: Record<string, unknown> }) {
  const heading = str(props.heading);
  const entries = await getEntries(str(props.collectionKey));
  if (entries.length === 0) return null;
  return (
    <section className="py-16">
      <Container>
        {heading ? <h2 className="font-heading font-extrabold text-2xl md:text-3xl text-ink mb-8">{heading}</h2> : null}
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-11 border-t border-neutral-400">
          {entries.map((entry) => (
            <details key={entry.slug} className="group py-[18px] px-3 border-b border-neutral-300">
              <summary className="cursor-pointer list-none flex items-center justify-between gap-4 font-heading font-semibold text-[17px] text-ink">
                {entry.title}
                <span aria-hidden className="text-ink-muted group-open:rotate-45 transition-transform">+</span>
              </summary>
              <p className="mt-2 text-sm text-ink-soft leading-relaxed">{str(entry.fields.answer)}</p>
            </details>
          ))}
        </div>
      </Container>
    </section>
  );
}

function ImageBlock({ props }: { props: Record<string, unknown> }) {
  const url = str(props.url);
  if (!url) return null;
  const altText = str(props.altText);
  const caption = str(props.caption);
  const widthPx = typeof props.widthPx === "number" ? props.widthPx : undefined;
  return (
    <section className="py-8">
      <Container>
        <Image
          src={url}
          alt={altText}
          width={widthPx || 1200}
          height={Math.round((widthPx || 1200) * 0.6)}
          className="w-full h-auto rounded-card"
          style={widthPx ? { maxWidth: widthPx, marginInline: "auto" } : undefined}
          sizes="100vw"
        />
        {caption ? <p className="mt-2 text-sm text-ink-faint text-center">{caption}</p> : null}
      </Container>
    </section>
  );
}

async function ColumnsBlock({ props, children }: { props: Record<string, unknown>; children: WebBlock[] }) {
  const columnCount = typeof props.columnCount === "number" ? props.columnCount : 2;
  const gapPx = typeof props.gapPx === "number" ? props.gapPx : 32;
  if (children.length === 0) return null;
  return (
    <section className="py-8">
      <Container
        className="grid grid-cols-1"
        style={{ gridTemplateColumns: `repeat(${columnCount}, 1fr)`, gap: `${gapPx}px` }}
      >
        {children.map((child) => <BlockNode key={child.id} block={child} />)}
      </Container>
    </section>
  );
}

function SpacerBlock({ props }: { props: Record<string, unknown> }) {
  const heightPx = typeof props.heightPx === "number" ? props.heightPx : 40;
  return <div style={{ height: `${heightPx}px` }} aria-hidden />;
}

async function ProductGridBlock({ props }: { props: Record<string, unknown> }) {
  const columns = typeof props.columns === "number" ? props.columns : 3;
  const limit = typeof props.limit === "number" ? props.limit : undefined;
  const collectionSlug = str(props.collectionSlug);
  const all = await getStoreProducts();
  const filtered = collectionSlug ? all.filter((p) => p.categoryKey === collectionSlug) : all;
  const products = limit ? filtered.slice(0, limit) : filtered;
  if (products.length === 0) return null;
  return (
    <section className="py-16">
      <Container>
        <div
          className="grid grid-cols-1 sm:grid-cols-2 gap-6"
          style={{ gridTemplateColumns: `repeat(${Math.min(columns, 4)}, minmax(0, 1fr))` }}
        >
          {products.map((p) => (
            <div key={p.slug} className="flex flex-col gap-2.5 rounded-card border border-neutral-400 shadow-1 bg-neutral-100 overflow-hidden">
              {p.images[0] ? (
                <div className="relative w-full aspect-square bg-neutral-200">
                  <Image src={p.images[0]} alt={p.name} fill className="object-cover" sizes="(min-width: 1024px) 25vw, 50vw" />
                </div>
              ) : null}
              <div className="p-4 pt-1">
                <h3 className="font-heading font-bold text-base text-ink leading-snug">{p.name}</h3>
                <p className="mt-1.5 text-xs text-ink-faint">
                  {p.currency} {p.basePrice.toFixed(2)}
                </p>
              </div>
            </div>
          ))}
        </div>
      </Container>
    </section>
  );
}

async function FormEmbedBlock({ props }: { props: Record<string, unknown> }) {
  const formKey = str(props.formKey);
  if (!formKey) return null;
  const schema = await getFormSchema(formKey);
  if (!schema) return null;
  return (
    <section className="py-16">
      <Container className="max-w-xl">
        <DynamicForm formKey={schema.formKey} fields={schema.fields} successMessage={schema.successMessage} submitLabel={schema.name} />
      </Container>
    </section>
  );
}

function TestimonialBlock({ props }: { props: Record<string, unknown> }) {
  const quote = str(props.quote);
  if (!quote) return null;
  const authorName = str(props.authorName);
  const rating = typeof props.rating === "number" ? props.rating : undefined;
  return (
    <section className="py-16 bg-neutral-100">
      <Container className="max-w-2xl text-center">
        <p className="font-heading text-xl md:text-2xl text-ink leading-snug">&ldquo;{quote}&rdquo;</p>
        <p className="mt-4 text-xs uppercase tracking-[0.1em] text-ink-muted">
          {authorName}
          {rating != null ? ` · ${rating}★` : ""}
        </p>
      </Container>
    </section>
  );
}

function CtaBannerBlock({ props }: { props: Record<string, unknown> }) {
  const heading = str(props.heading);
  const description = str(props.description);
  const ctaLabel = str(props.ctaLabel);
  const ctaHref = str(props.ctaHref, "#");
  return (
    <section className="py-14 bg-lavender">
      <Container className="flex flex-wrap items-center justify-between gap-6">
        <div className="max-w-xl">
          {heading ? <h2 className="font-heading font-extrabold text-2xl md:text-3xl text-ink">{heading}</h2> : null}
          {description ? <p className="mt-2 text-ink-soft leading-relaxed">{description}</p> : null}
        </div>
        {ctaLabel ? (
          <Link href={ctaHref} className="text-base font-bold text-purple border-b-2 border-purple pb-0.5 whitespace-nowrap">
            {ctaLabel} →
          </Link>
        ) : null}
      </Container>
    </section>
  );
}

/** The "Fiscal Sponsorship & Venture Studio" section — a lavender-bg block
 *  with sponsorship benefits as a plain stacked list on the left and
 *  onboarding steps as small icon cards in a 2x2 grid on the right, exactly
 *  as laid out in the source design (not two separate stacked sections). */
async function SponsorshipSplitBlock({ props }: { props: Record<string, unknown> }) {
  const anchor = str(props.anchor) || undefined;
  const eyebrow = str(props.eyebrow);
  const heading = str(props.heading);
  const stepsEyebrow = str(props.stepsEyebrow);
  const stepsHeading = str(props.stepsHeading);
  const ctaLabel = str(props.ctaLabel);
  const ctaHref = str(props.ctaHref, "#");
  const [benefits, steps] = await Promise.all([
    getEntries(str(props.benefitsCollectionKey)),
    getEntries(str(props.stepsCollectionKey))
  ]);
  const icons = ONBOARDING_STEP_ICONS;

  return (
    <section id={anchor} className="py-16 bg-lavender">
      <Container className="grid grid-cols-1 lg:grid-cols-2 gap-12">
        <div>
          {eyebrow ? (
            <span className="inline-flex items-center gap-2 text-xs tracking-[0.14em] uppercase text-purple">
              <span className="h-px w-6 bg-purple" /> {eyebrow}
            </span>
          ) : null}
          {heading ? <h2 className="mt-3 font-heading font-extrabold text-3xl leading-tight text-ink max-w-md">{heading}</h2> : null}
          <div className="mt-8 border-t border-ink/10">
            {benefits.map((entry) => (
              <div key={entry.slug} className="py-4 border-b border-ink/10">
                <h3 className="font-heading font-bold text-base text-ink">{entry.title}</h3>
                <p className="mt-1 text-sm text-ink-soft leading-relaxed">{str(entry.fields.description)}</p>
              </div>
            ))}
          </div>
        </div>

        <div>
          {stepsEyebrow ? <span className="text-xs tracking-[0.14em] uppercase text-purple">{stepsEyebrow}</span> : null}
          {stepsHeading ? <h3 className="mt-2 font-heading font-bold text-lg text-ink">{stepsHeading}</h3> : null}
          <div className="mt-5 grid grid-cols-1 sm:grid-cols-2 gap-4">
            {steps.map((entry) => {
              const Icon = icons[entry.slug];
              return (
                <div key={entry.slug} className="rounded-card bg-white p-5">
                  <div className="flex items-center justify-between mb-2">
                    <span className="text-xs text-purple font-bold">{str(entry.fields.number)}</span>
                    {Icon ? <Icon className="h-5 w-5 text-purple" /> : null}
                  </div>
                  <h4 className="font-heading font-bold text-[15px] text-ink">{entry.title}</h4>
                  <p className="mt-1 text-sm text-ink-soft leading-relaxed">{str(entry.fields.description)}</p>
                </div>
              );
            })}
          </div>
          {ctaLabel ? (
            <Link href={ctaHref} className="mt-6 inline-block text-sm font-bold text-ink border-b-2 border-ink pb-0.5">
              {ctaLabel} →
            </Link>
          ) : null}
        </div>
      </Container>
    </section>
  );
}

/** The "Get Involved" section — dark full-bleed background with the
 *  audiences list + direct-contact block on the left, and the contact form
 *  rendered inside a floating white card on the right, matching the source
 *  design's contrast layout. */
async function GetInvolvedSplitBlock({ props }: { props: Record<string, unknown> }) {
  const anchor = str(props.anchor) || undefined;
  const eyebrow = str(props.eyebrow);
  const heading = str(props.heading);
  const formKey = str(props.formKey);
  const contactEmail = str(props.contactEmail);
  const partnershipsEmail = str(props.partnershipsEmail);
  const phone = str(props.phone);
  const address = str(props.address);
  const contactLabel = str(props.contactLabel, "Direct Contact");
  const entries = await getEntries(str(props.collectionKey));
  const schema = formKey ? await getFormSchema(formKey) : null;

  return (
    <section id={anchor} className="py-16 bg-ink text-white">
      <Container className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-start">
        <div>
          {eyebrow ? (
            <span className="inline-flex items-center gap-2 text-xs tracking-[0.14em] uppercase text-white/60">
              <span className="h-px w-6 bg-teal" /> {eyebrow}
            </span>
          ) : null}
          {heading ? <h2 className="mt-3 font-heading font-extrabold text-3xl leading-tight max-w-md">{heading}</h2> : null}

          <div className="mt-8 border-t border-white/10">
            {entries.map((entry) => (
              <div key={entry.slug} className="py-4 border-b border-white/10">
                <h3 className="font-heading font-bold text-base">{entry.title}</h3>
                <p className="mt-1 text-sm text-white/60 leading-relaxed">{str(entry.fields.description)}</p>
              </div>
            ))}
          </div>

          {(contactEmail || phone) ? (
            <div className="mt-8">
              <span className="text-xs tracking-[0.14em] uppercase text-white/40">{contactLabel}</span>
              <div className="mt-2 space-y-1">
                {contactEmail ? <a href={`mailto:${contactEmail}`} className="block text-sm font-semibold text-teal">{contactEmail}</a> : null}
                {partnershipsEmail ? <a href={`mailto:${partnershipsEmail}`} className="block text-sm font-semibold text-teal">{partnershipsEmail}</a> : null}
                <p className="text-sm text-white/60">{[phone, address].filter(Boolean).join(" · ")}</p>
              </div>
            </div>
          ) : null}
        </div>

        {schema ? (
          <div className="rounded-card bg-white p-7 md:p-9">
            <DynamicForm formKey={schema.formKey} fields={schema.fields} successMessage={schema.successMessage} submitLabel={schema.name} />
          </div>
        ) : null}
      </Container>
    </section>
  );
}
