import * as stylex from "@stylexjs/stylex";
import { type PropsWithChildren, createElement, memo } from "react";
import { fontSize, headingMargin, headingWeight } from "./tokens.stylex";

export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;

//#region Styles

const styles = stylex.create({
	heading: {
		textWrap: "balance",
	},
	truncate: {
		overflow: "hidden",
		textOverflow: "ellipsis",
		whiteSpace: "nowrap",
	},
	centered: {
		textAlign: "center",
	},
	upperCased: {
		textTransform: "uppercase",
	},
	"1": {
		fontSize: fontSize.h1,
		marginTop: headingMargin.h1Top,
		marginBottom: headingMargin.h1Bottom,
		fontWeight: headingWeight.h1,
	},
	"2": {
		fontSize: fontSize.h2,
		marginTop: headingMargin.h2Top,
		marginBottom: headingMargin.h2Bottom,
		fontWeight: headingWeight.h2,
	},
	"3": {
		fontSize: fontSize.h3,
		marginTop: headingMargin.h3Top,
		marginBottom: headingMargin.h3Bottom,
		fontWeight: headingWeight.h3,
	},
	"4": {
		fontSize: fontSize.h4,
		marginTop: headingMargin.h4Top,
		marginBottom: headingMargin.h4Bottom,
		fontWeight: headingWeight.h4,
	},
	"5": {
		fontSize: fontSize.h5,
		marginTop: headingMargin.h5Top,
		marginBottom: headingMargin.h5Bottom,
		fontWeight: headingWeight.h5,
	},
	"6": {
		fontSize: fontSize.h6,
		marginTop: headingMargin.h6Top,
		marginBottom: headingMargin.h6Bottom,
		fontWeight: headingWeight.h6,
	},
	noTopMargin: {
		marginTop: 0,
	},
	noBottomMargin: {
		marginBottom: 0,
	},
});

//#endregion

/**
 * Based on this heading component:
 * https://react.docs.search.io/components/heading
 * https://mui.com/material-ui/react-typography/
 */
export interface HeadingProps extends PropsWithChildren {
	level: HeadingLevel;
	/** Use this to make the level smaller/larger than it would be according to the HTML tag. Used for a11y to not break the document outline. */
	styleLike?: HeadingLevel;

	/**
	 * If true, the heading will be upper-cased (using CSS for a11y reasons).
	 */
	upperCased?: boolean;

	noTopMargin?: boolean;
	noBottomMargin?: boolean;

	centered?: boolean;

	/**
	 * If true, the heading will be truncated with an ellipsis if it overflows.
	 */
	truncate?: boolean;
}
export default memo(function Heading(props: HeadingProps) {
	const elementProps = stylex.props(
		styles.heading,
		styles[props.styleLike ?? props.level],
		props.centered && styles.centered,
		props.upperCased && styles.upperCased,
		props.truncate && styles.truncate,
		props.noTopMargin && styles.noTopMargin,
		props.noBottomMargin && styles.noBottomMargin,
	);

	// We used to have a switch-case here. But we can call createElement directly to avoid the code duplication
	// biome-ignore lint/style/useTemplate: nope
	return createElement("h" + props.level, elementProps, props.children);
});
