import React from "react";

import { Typography } from "antd";
import type { LinkProps } from "antd/lib/typography/Link";
import type { ParagraphProps } from "antd/lib/typography/Paragraph";
import type { TextProps } from "antd/lib/typography/Text";
import type { TitleProps } from "antd/lib/typography/Title";

import {
  tachTypographyMarkdownToHtml,
  tachTypographyClassName,
  type TypographyColor,
  type TypographyVariant,
  type TypographyWeight,
} from "../core";

interface AdditionalProps {
  color?: TypographyColor;
  weight?: TypographyWeight;
  onClick?: (event: React.MouseEvent<HTMLElement>) => void;
  className?: string | undefined;
  markdownEnabled?: boolean;
  children?: React.ReactNode;
}

const createTypographyVariant = <P extends object>(
  Component: React.ComponentType<P>,
  variant: TypographyVariant,
) => {
  const Variant = React.forwardRef<HTMLElement, P & AdditionalProps>(
    (
      {
        color = "primary",
        weight = "normal",
        className,
        onClick,
        markdownEnabled = false,
        children,
        ...rest
      },
      ref,
    ) => {
      const markdownHtml =
        markdownEnabled && typeof children === "string"
          ? tachTypographyMarkdownToHtml(children)
          : undefined;
      const renderedChildren = markdownHtml ? (
        <span dangerouslySetInnerHTML={{ __html: markdownHtml }} />
      ) : (
        children
      );
      const contentProps = { children: renderedChildren } as unknown as P;

      return (
        <Component
          ref={ref as never}
          className={tachTypographyClassName({
            variant,
            color,
            weight,
            className,
            clickable: Boolean(onClick),
          })}
          onClick={onClick}
          {...(rest as P)}
          {...contentProps}
        />
      );
    },
  );

  Variant.displayName = String(variant);

  return Variant;
};

const createTypographyComponent = <P extends object>(Component: React.ComponentType<P>) => ({
  LargeTitle: createTypographyVariant(Component, "LargeTitle"),
  Title1: createTypographyVariant(Component, "Title1"),
  Title2: createTypographyVariant(Component, "Title2"),
  Title3: createTypographyVariant(Component, "Title3"),
  Headline: createTypographyVariant(Component, "Headline"),
  Body: createTypographyVariant(Component, "Body"),
  Inputs: createTypographyVariant(Component, "Inputs"),
  Subheadline: createTypographyVariant(Component, "Subheadline"),
  FootnoteUnderline: createTypographyVariant(Component, "FootnoteUnderline"),
  Footnote: createTypographyVariant(Component, "Footnote"),
  Caption: createTypographyVariant(Component, "Caption"),
  Caption2: createTypographyVariant(Component, "Caption2"),

  AccentH1: createTypographyVariant(Component, "AccentH1"),
  AccentH2: createTypographyVariant(Component, "AccentH2"),
  AccentSubttl: createTypographyVariant(Component, "AccentSubttl"),
  AccentSubttl2: createTypographyVariant(Component, "AccentSubttl2"),
  AccentCaption: createTypographyVariant(Component, "AccentCaption"),
  AccentCaption2: createTypographyVariant(Component, "AccentCaption2"),
  AccentRegularM: createTypographyVariant(Component, "AccentRegularM"),
  AccentRegularS: createTypographyVariant(Component, "AccentRegularS"),
  AccentLargeTtl: createTypographyVariant(Component, "AccentLargeTtl"),
  AppMediumBody: createTypographyVariant(Component, "AppMediumBody"),
  AppMediumSubtext: createTypographyVariant(Component, "AppMediumSubtext"),
  AppMediumSubtextUnderline: createTypographyVariant(Component, "AppMediumSubtextUnderline"),
});

export const TachTypography = {
  Text: createTypographyComponent<TextProps & Pick<ParagraphProps, "ellipsis">>(Typography.Text),
  Paragraph: createTypographyComponent<ParagraphProps>(Typography.Paragraph),
  Link: createTypographyComponent<LinkProps>(Typography.Link),
  Title: createTypographyComponent<TitleProps>(Typography.Title),
};
