import * as React from 'react';
import clsx from 'clsx';
import { Button } from '@tesseract-design/web-base';

/**
 * Derived HTML element of the {@link ActionButton} component.
 */
export type ActionButtonDerivedElement = HTMLButtonElement;

/**
 * Props of the {@link ActionButton} component.
 */
export interface ActionButtonProps extends Omit<React.HTMLProps<ActionButtonDerivedElement>, 'type' | 'size'> {
  /**
   * Type of the component.
   */
  type?: Button.Type;
  /**
   * Variant of the component.
   */
  variant?: Button.Variant;
  /**
   * Should the component occupy the whole width of its parent?
   */
  block?: 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;
  /**
   * Size of the component.
   */
  size?: Button.Size;
  /**
   * Should the component's content use minimal space?
   */
  compact?: boolean;
}

/**
 * Component for performing an action upon activation (e.g. when clicked).
 *
 * This component functions as a regular button.
 */
export const ActionButton = React.forwardRef<ActionButtonDerivedElement, ActionButtonProps>((
  {
    type = 'button' as const,
    variant = 'bare' as const,
    subtext,
    badge,
    menuItem = false as const,
    children,
    size = 'medium' as const,
    compact = false as const,
    className,
    block = false as const,
    ...etcProps
  },
  forwardedRef,
) => (
  <button
    {...etcProps}
    data-testid="button"
    type={type}
    ref={forwardedRef}
    className={clsx(
      'items-center justify-center rounded overflow-hidden ring-secondary/50 leading-none select-none',
      'focus:outline-0 focus:ring-4',
      'active:ring-tertiary/50',
      'disabled:opacity-50 disabled:cursor-not-allowed',
      {
        'flex w-full': block,
        'inline-flex max-w-full align-middle': !block,
      },
      {
        'pl-2 gap-2': compact,
        'pl-4 gap-4': !compact,
        'pr-4': !(compact || menuItem),
        'pr-2': compact || menuItem,
      },
      {
        'border-2 border-primary focus:border-secondary active:border-tertiary disabled:border-primary': variant !== 'bare',
        'bg-negative text-primary focus:text-secondary active:text-tertiary disabled:text-primary': variant !== 'filled',
        'bg-primary text-negative focus:bg-secondary active:bg-tertiary focus:text-negative active:text-negative disabled:bg-primary': variant === 'filled',
      },
      {
        'h-10': size === 'small',
        'h-12': size === 'medium',
        'h-16': size === 'large',
      },
      className,
    )}
  >
    <span
      className={clsx(
        'flex-auto min-w-0',
        {
          'text-left': compact || menuItem,
          'text-center': !(compact || menuItem),
        },
      )}
    >
      <span
        className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded"
        data-testid="children"
      >
        {children}
      </span>
      {subtext && (
        <>
          <span className="sr-only">
            {' - '}
          </span>
          <span
            className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
            data-testid="subtext"
          >
            {subtext}
          </span>
        </>
      )}
    </span>
    {badge && (
      <>
        <span className="sr-only">
          {' - '}
        </span>
        <span
          data-testid="badge"
        >
          {badge}
        </span>
      </>
    )}
    {menuItem && (
      <span
        data-testid="menuItemIndicator"
      >
        <svg
          className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round"
          viewBox="0 0 24 24"
          role="presentation"
        >
          <polyline points="9 18 15 12 9 6" />
        </svg>
      </span>
    )}
  </button>
));

ActionButton.displayName = 'ActionButton' as const;

ActionButton.defaultProps = {
  type: 'button' as const,
  variant: 'bare' as const,
  block: false as const,
  subtext: undefined,
  badge: undefined,
  menuItem: false as const,
  size: 'medium' as const,
  compact: false as const,
};
