import type { ReactNode, RefAttributes } from "react";
import classNames from "classnames/dedupe";
import type { DOMProps } from "../../types/dom";
import "./Text.css";

export type TextElementType = HTMLHeadingElement | HTMLParagraphElement;
export type TextVariantType =
  | "h1"
  | "h2"
  | "h3"
  | "h4"
  | "body"
  | "small"
  | "legal"
  | "title";
export type ElementType = "h1" | "h2" | "h3" | "h4" | "p" | "span";
export interface TextProps extends DOMProps, RefAttributes<TextElementType> {
  /** HTML element for the text */
  elementType?: ElementType;
  /** Specify font size override */
  variant?: TextVariantType;
  /** Specify compact line height override */
  spacing?: "loose" | "tight";
  /** Custom class name for setting specific CSS */
  className?: string;
  children: ReactNode;
  style?: React.CSSProperties;
}

export const getElementType = (
  variant: TextVariantType | undefined,
  elementType: ElementType | undefined,
): ElementType => {
  // Explicit elementType always wins
  if (elementType) {
    return elementType;
  }
  // Infer element from variant
  if (variant && ["h1", "h2", "h3", "h4"].includes(variant)) {
    return variant as ElementType;
  }
  return "p";
};

const Text = ({ ref, elementType, ...props }: TextProps) => {
  // Remove non-DOM props from element
  const { variant, className, spacing, ...otherProps } = props;

  // If a variant is supplied, set the class name and element type
  const Element: ElementType = getElementType(variant, elementType);
  const variantType = variant || Element;
  const classes = classNames(
    "mobius",
    "mobius-text",
    { [`--is-${variantType}`]: variantType },
    { [`--has-line-height-${spacing}`]: spacing },
    className,
  );

  return <Element ref={ref} {...otherProps} className={classes} />;
};

Text.displayName = "Text";
export { Text };
