import cx from "classnames";
import React from "react";

export type ButtonSize = "small" | "large";
export type ButtonType = "primary" | "fill" | "ghost";

interface CommonProps {
  elemRef?: React.Ref<any>;
  htmlType?: "button" | "submit" | "reset";
  isActive?: boolean;
  isDefault?: boolean;
  isDisabled?: boolean;
  isSquare?: boolean;
  size?: ButtonSize;
  type?: ButtonType;
  className?: string;
  children?: React.ReactNode;
  preserveWidth?: boolean;
}

type AnchorProps = CommonProps &
  Omit<
    React.AnchorHTMLAttributes<HTMLAnchorElement>,
    keyof CommonProps | "type" | "ref"
  > & {
    href: string;
  };

type NativeButtonProps = CommonProps &
  Omit<
    React.ButtonHTMLAttributes<HTMLButtonElement>,
    keyof CommonProps | "href" | "ref"
  > & {
    href?: undefined;
  };

export type ButtonProps = AnchorProps | NativeButtonProps;

const CLASS_ROOT = "btn";

const Button = React.forwardRef<any, ButtonProps>((props, ref) => {
  const {
    className,
    children,
    htmlType = "button",
    href,
    isActive,
    isDisabled,
    size,
    isSquare,
    type,
    elemRef,
    ...other
  } = props;

  const classes = cx(
    CLASS_ROOT,
    {
      [`${CLASS_ROOT}--square`]: isSquare,
      [`${CLASS_ROOT}--${size}`]: size,
      [`${CLASS_ROOT}--${type}`]: type,
      [`${CLASS_ROOT}--preserve-width`]: props.preserveWidth,
      "is-active": isActive,
    },
    className,
  );

  if (href) {
    // Anchor element
    const anchorProps = other as React.AnchorHTMLAttributes<HTMLAnchorElement>;
    return (
      <a
        href={href}
        className={classes}
        aria-disabled={isDisabled ? "true" : undefined}
        ref={elemRef || ref}
        {...anchorProps}
      >
        {children}
      </a>
    );
  } else {
    // Button element
    const buttonProps = other as React.ButtonHTMLAttributes<HTMLButtonElement>;
    return (
      <button
        type={htmlType}
        className={classes}
        disabled={isDisabled ? true : undefined}
        aria-disabled={isDisabled ? "true" : undefined}
        ref={elemRef || ref}
        {...buttonProps}
      >
        {children}
      </button>
    );
  }
});

Button.displayName = "Button";

export { Button };
