import * as React from 'react';
import * as ButtonBase from '@tesseract-design/web-base-button';

type LinkButtonElement = HTMLAnchorElement | HTMLSpanElement;

export type LinkButtonProps = Omit<React.HTMLProps<LinkButtonElement>, 'size' | 'style'> & {
  /**
   * Size of the component.
   */
  size?: ButtonBase.ButtonSize,
  /**
   * Variant of the component.
   */
  variant?: ButtonBase.ButtonVariant,
  /**
   * Should the component display a border?
   */
  border?: boolean,
  /**
   * Should the component occupy the whole width of its parent?
   */
  block?: boolean,
  /**
   * Does the component need to conserve space?
   */
  compact?: boolean,
  /**
   * Complementary content of the component.
   */
  subtext?: React.ReactNode,
  /**
   * Short complementary content displayed at the edge of the component.
   */
  badge?: React.ReactNode,
  /**
   * Is this component part of a menu?
   */
  menuItem?: boolean,
};

/**
 * Component for performing an action upon activation (e.g. when clicked).
 *
 * This component functions as a hyperlink.
 */
export const LinkButton = React.forwardRef<LinkButtonElement, LinkButtonProps>(
  (
    {
      size = ButtonBase.ButtonSize.MEDIUM,
      variant = ButtonBase.ButtonVariant.OUTLINE,
      border = false,
      children,
      block = false,
      disabled = false,
      onClick,
      href,
      target,
      rel,
      compact = false,
      subtext,
      badge,
      menuItem = false,
      className: _className,
      as: _as,
      ...etcProps
    }: LinkButtonProps,
    ref,
  ) => {
    const styleProps = React.useMemo<ButtonBase.ButtonBaseArgs>(() => ({
      size,
      block,
      variant,
      border,
      disabled,
      compact,
      menuItem,
    }), [size, block, variant, border, disabled, compact, menuItem]);

    const commonChildren = (
      <>
        <span
          className={ButtonBase.Border(styleProps)}
        />
        <span
          className={ButtonBase.Label(styleProps)}
        >
          <span
            className={ButtonBase.MainText()}
            data-testid="children"
          >
            <span
              className={ButtonBase.OverflowText()}
            >
              {children}
            </span>
          </span>
          {
            subtext
            && (
              <>
                {' '}
                <span
                  className={ButtonBase.Subtext()}
                  data-testid="subtext"
                >
                  <span
                    className={ButtonBase.OverflowText()}
                  >
                    {subtext}
                  </span>
                </span>
              </>
            )
          }
        </span>
        {
          badge
          && (
            <>
              {' '}
              <span
                className={ButtonBase.BadgeContainer(styleProps)}
                data-testid="badge"
              >
                {badge}
              </span>
            </>
          )
        }
        {
          menuItem
          && (
            <>
              {' '}
              <span
                className={ButtonBase.IndicatorWrapper(styleProps)}
                data-testid="menuItemIndicator"
              >
                <svg
                  className={ButtonBase.Indicator()}
                  viewBox="0 0 24 24"
                  role="presentation"
                >
                  <polyline points="9 18 15 12 9 6"/>
                </svg>
              </span>
            </>
          )
        }
      </>
    );

    if (disabled) {
      return (
        // eslint-disable-next-line jsx-a11y/click-events-have-key-events
        <span
          {...etcProps}
          className={ButtonBase.Button(styleProps)}
          ref={ref as React.ForwardedRef<HTMLSpanElement>}
          onClick={undefined}
        >
          {commonChildren}
        </span>
      );
    }

    return (
      <a
        {...etcProps}
        className={ButtonBase.Button(styleProps)}
        ref={ref as React.ForwardedRef<HTMLAnchorElement>}
        href={href}
        target={target}
        rel={rel}
        onClick={onClick}
      >
        {commonChildren}
      </a>
    );
  },
);

LinkButton.displayName = 'LinkButton';
