import Rule from "@/components/ui/Rule";
import { cn } from "@/lib/utils";

type NumberedCardItem = {
  /** Stable React key — pass the i18n key of the card, never the index. */
  id: string;
  title: string;
  body: string;
};

type NumberedCardGridProps = {
  items: readonly NumberedCardItem[];
  /**
   * Text alignment inside each card. "center" for the standalone centered
   * sections (Home), "start" for editorial sections that read left-aligned.
   */
  align?: "start" | "center";
  /**
   * "surface" — hairline card on a light section background.
   * "inverse" — translucent card sitting on a dark scrim / photographic background.
   */
  tone?: "surface" | "inverse";
  /**
   * Decorative marker above the title: the derived ordinal ("01", "02"…) or a
   * gold hairline. Both are `aria-hidden` — they carry no meaning for a
   * screen reader, the cards are not an ordered sequence.
   */
  marker?: "number" | "rule";
  /**
   * Columns from `lg`. Below `lg` the grid is always 1 then 2 columns, so a
   * three-card section never strands an orphan in a four-column track.
   */
  columns?: 3 | 4;
  className?: string;
};

// Explicit breakpoints rather than `auto-fit`/`minmax`: mobile-first, and the
// 1 → 2 → n transitions happen at declared, testable widths.
const COLUMN_CLASS = {
  3: "lg:grid-cols-3",
  4: "lg:grid-cols-4",
} as const;

const CARD_CLASS = {
  surface:
    "border-hairline bg-background px-6 py-8 motion-safe:transition-all motion-safe:duration-300 motion-safe:hover:-translate-y-1 lg:px-8 lg:py-9",
  inverse: "border-white/16 bg-white/6 p-8 backdrop-blur-sm",
} as const;

const TITLE_CLASS = {
  surface: "text-foreground",
  inverse: "text-white",
} as const;

// The gold hairline keeps the charter `bg-gold` on light cards; on the dark
// `inverse` card it takes the lighter burnished gold, which is the token meant
// for decorative marks on a dark surface (`docs/brand.md`).
const RULE_CLASS = {
  surface: undefined,
  inverse: "bg-burnished-gold",
} as const;

const BODY_CLASS = {
  surface: "text-on-surface-variant",
  inverse: "text-on-inverse-surface",
} as const;

/**
 * The shared grid of bordered cards used by the value proposition, materials
 * and philosophy sections: a decorative gold marker, a display title and a
 * short body, revealed with a stagger as the grid scrolls into view.
 *
 * Server Component with no client boundary at all: the reveal is the CSS-only
 * `.reveal` / `.reveal-stagger` pair of `globals.css`. Deliberately not built
 * on the shadcn `Card`, whose rounded corners and drop shadow contradict the
 * "Sharp (0px)" / "cards do not float" rules of `docs/brand.md`.
 */
export default function NumberedCardGrid({
  items,
  align = "start",
  tone = "surface",
  marker = "number",
  columns = 4,
  className,
}: NumberedCardGridProps) {
  const centered = align === "center";

  return (
    <div
      className={cn(
        "reveal-stagger grid grid-cols-1 gap-4 sm:grid-cols-2 lg:gap-6",
        COLUMN_CLASS[columns],
        className,
      )}
    >
      {items.map((item, index) => (
        <div key={item.id} className="reveal h-full">
          <div className={cn("h-full border", CARD_CLASS[tone], centered && "text-center")}>
            {marker === "number" ? (
              <span aria-hidden="true" className="font-display text-sm text-burnished-gold">
                {String(index + 1).padStart(2, "0")}
              </span>
            ) : (
              <Rule size="lg" className={cn("mb-5", centered && "mx-auto", RULE_CLASS[tone])} />
            )}
            <h3
              className={cn(
                "mb-3.5 font-display text-card-title font-normal",
                marker === "number" && "mt-4",
                TITLE_CLASS[tone],
              )}
            >
              {item.title}
            </h3>
            <p className={cn("text-sm leading-body", BODY_CLASS[tone])}>{item.body}</p>
          </div>
        </div>
      ))}
    </div>
  );
}
