import * as React from "react";
import { cn } from "~/editor/lib/utils";

export type TypographyVariant =
  | "h1"
  | "h2"
  | "h3"
  | "h4"
  | "h5"
  | "h6"
  | "subtitle1"
  | "subtitle2"
  | "body1"
  | "body2"
  | "caption";

const sizeClasses: Record<TypographyVariant, string> = {
  h1: "text-5xl md:text-6xl lg:text-7xl font-semibold tracking-tight leading-[1.05]",
  h2: "text-4xl md:text-5xl font-semibold tracking-tight leading-[1.1]",
  h3: "text-3xl md:text-4xl font-semibold tracking-tight leading-tight",
  h4: "text-2xl md:text-3xl font-semibold tracking-tight leading-snug",
  h5: "text-xl md:text-2xl font-semibold leading-snug",
  h6: "text-lg md:text-xl font-semibold leading-snug",
  subtitle1: "text-lg md:text-xl leading-relaxed text-muted-foreground",
  subtitle2: "text-base md:text-lg leading-relaxed text-muted-foreground",
  body1: "text-lg leading-relaxed",
  body2: "text-base leading-relaxed",
  caption: "text-sm leading-relaxed text-muted-foreground",
};

// Inline-style fallbacks so headings size correctly even when Tailwind
// preflight resets <h1>..<h6> to font-size: inherit and the iframe CDN
// hasn't compiled utility classes yet. The Tailwind classes above still
// apply on top once available (responsive breakpoints, leading, etc.).
const sizeStyles: Record<TypographyVariant, React.CSSProperties> = {
  h1: { fontSize: "clamp(2.5rem, 6vw, 4.5rem)", lineHeight: 1.05, fontWeight: 600, letterSpacing: "-0.02em" },
  h2: { fontSize: "clamp(2rem, 4vw, 3rem)",     lineHeight: 1.1,  fontWeight: 600, letterSpacing: "-0.02em" },
  h3: { fontSize: "clamp(1.75rem, 3.5vw, 2.25rem)", lineHeight: 1.15, fontWeight: 600, letterSpacing: "-0.015em" },
  h4: { fontSize: "clamp(1.5rem, 3vw, 1.875rem)",   lineHeight: 1.2,  fontWeight: 600, letterSpacing: "-0.01em" },
  h5: { fontSize: "1.5rem",   lineHeight: 1.25, fontWeight: 600 },
  h6: { fontSize: "1.25rem",  lineHeight: 1.3,  fontWeight: 600 },
  subtitle1: { fontSize: "1.125rem", lineHeight: 1.6 },
  subtitle2: { fontSize: "1rem",     lineHeight: 1.6 },
  body1: { fontSize: "1.125rem", lineHeight: 1.6 },
  body2: { fontSize: "1rem",     lineHeight: 1.6 },
  caption: { fontSize: "0.875rem", lineHeight: 1.5 },
};

const defaultTag: Record<TypographyVariant, keyof JSX.IntrinsicElements> = {
  h1: "h1",
  h2: "h2",
  h3: "h3",
  h4: "h4",
  h5: "h5",
  h6: "h6",
  subtitle1: "p",
  subtitle2: "p",
  body1: "p",
  body2: "p",
  caption: "p",
};

type Props<C extends keyof JSX.IntrinsicElements = "p"> = {
  variant: TypographyVariant;
  as?: C;
  className?: string;
  style?: React.CSSProperties;
  children?: React.ReactNode;
} & Omit<React.ComponentPropsWithoutRef<C>, "className" | "children" | "style">;

export function Typography<C extends keyof JSX.IntrinsicElements = "p">({
  variant,
  as,
  className,
  style,
  children,
  ...rest
}: Props<C>) {
  const Tag = (as ?? defaultTag[variant]) as keyof JSX.IntrinsicElements;
  const isHeading = variant.startsWith("h");
  const fontClass = isHeading ? "font-heading" : "font-body";

  return React.createElement(
    Tag,
    {
      className: cn(fontClass, sizeClasses[variant], className),
      style: { ...sizeStyles[variant], ...style },
      ...rest,
    },
    children,
  );
}

export default Typography;
