import React from "react";
import typographyTokens from "../../styles/tokens/typography";
import { HeadingProps, TypographyWeight } from "../../types/Typography";

type HeadingTokenKey =
  | "headingXl"
  | "headingLg"
  | "headingMd"
  | "headingSm"
  | "headingXs";

export const Heading: React.FC<HeadingProps> = ({
  size = "xl",
  element = "h2",
  align = "left",
  weight,
  color,
  truncate = false,
  lineClamp,
  children,
  className = "",
  style = {},
  onClick,
  testID,
  ...rest
}) => {
  const getStyles = (): React.CSSProperties => {
    const tokenKeyMap: Record<string, HeadingTokenKey> = {
      xl: "headingXl",
      lg: "headingLg",
      md: "headingMd",
      sm: "headingSm",
      xs: "headingXs",
    };

    const tokenSet = typographyTokens[tokenKeyMap[size]];

    const fontWeightValue = weight
      ? parseInt(typographyTokens.weights[weight])
      : parseInt(tokenSet.fontWeight);

    const baseStyles: React.CSSProperties = {
      fontFamily: tokenSet.fontFamily,
      fontSize: `${tokenSet.fontSize}px`,
      lineHeight: `${tokenSet.lineHeight}px`,
      fontWeight: fontWeightValue,
      color: color || tokenSet.color,
      textAlign: align,
      letterSpacing: tokenSet.letterSpacing,
      textDecoration: tokenSet.textDecoration || "none",
    };

    const truncationStyles: React.CSSProperties = truncate
      ? {
          whiteSpace: "nowrap",
          overflow: "hidden",
          textOverflow: "ellipsis",
          display: "block",
        }
      : {};

    const lineClampStyles: React.CSSProperties =
      lineClamp && lineClamp > 0
        ? {
            display: "-webkit-box",
            WebkitLineClamp: lineClamp,
            WebkitBoxOrient: "vertical",
            overflow: "hidden",
            textOverflow: "ellipsis",
          }
        : {};

    return {
      ...baseStyles,
      ...truncationStyles,
      ...lineClampStyles,
    };
  };

  const combinedStyles = {
    ...getStyles(),
    ...style,
  };

  const linkProps = element === "a" ? rest : {};

  const headingElementMap: Record<string, React.ElementType> = {
    xl: "h1",
    lg: "h2",
    md: "h3",
    sm: "h4",
    xs: "h5",
  };

  const defaultElement = element === "h2" ? headingElementMap[size] : element;

  const Component = defaultElement as React.ElementType;

  return (
    <Component
      style={combinedStyles}
      className={className}
      data-testid={testID}
      onClick={onClick}
      {...linkProps}
    >
      {children}
    </Component>
  );
};
