import React, { forwardRef } from "react";
import { default as MuiButton } from "@mui/material/Button";

import { Icon } from "../icon/Icon";
import { Tooltip } from "../tooltip/Tooltip";
import { twMerge } from "../../../tailwind.config";
import { ButtonProps, MUIButtonPropWithLink } from "./types";
import { useVariant } from "./useVariant";
import { useButtonStyles } from "./Button.styles";

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  (
    {
      children,
      onClick,
      type = "button",
      disabled = false,
      variant = "primary",
      size = "default",
      to,
      fullWidth,
      icon,
      iconPosition = "start",
      iconWeight = "semibold",
      linkComponent,
      tooltip,
      tooltipProps = {},
      ESCAPE_className,
      ...restProps
    },
    ref
  ) => {
    const { muiVariant, muiColor } = useVariant(variant);

    const { textMargin, ...classes } = useButtonStyles({
      variant,
      size,
      hasLabel: !!children,
    });

    const props = {
      classes: { ...classes, root: twMerge(classes.root, ESCAPE_className) },
      type,
      color: muiColor,
      variant: muiVariant,
      onClick,
      disabled,
      size: "medium",
      fullWidth,
      disableRipple: true,
      ...(to && { to, component: linkComponent }),
      ...restProps,
    } as MUIButtonPropWithLink;

    const iconComponent = icon ? (
      <Icon name={icon} weight={iconWeight} size="20" />
    ) : null;

    const iconProps = {
      [iconPosition === "end" ? "endIcon" : "startIcon"]: iconComponent,
    };

    const buttonComponent = (
      <MuiButton ref={ref} {...props} {...iconProps}>
        {children ? <span className={textMargin}>{children}</span> : null}
      </MuiButton>
    );

    if (tooltip) {
      return (
        <Tooltip tooltip={tooltip} {...tooltipProps}>
          {/* Disabled buttons don't fire events that the tooltip listens to. */}
          {disabled ? (
            <span style={{ display: "inline-flex" }}>{buttonComponent}</span>
          ) : (
            buttonComponent
          )}
        </Tooltip>
      );
    }

    return buttonComponent;
  }
);

Button.displayName = "Button";
