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

const { tw } = tailwind;

const ActionButtonDerivedElementComponent = 'button' as const;

/**
 * Derived HTML element of the {@link ActionButton} component.
 */
export type ActionButtonDerivedElement = HTMLElementTagNameMap[
	typeof ActionButtonDerivedElementComponent
];

/**
 * 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;
	/**
	 * Graphical representation of the component.
	 */
	icon?: React.ReactNode;
	/**
	 * Should the graphical representation of the component be placed after the children?
	 */
	iconAfterChildren?: 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,
		icon,
		iconAfterChildren = false as const,
    ...etcProps
  },
  forwardedRef,
) => (
  <ActionButtonDerivedElementComponent
    {...etcProps}
    data-testid="button"
    type={type}
    ref={forwardedRef}
    className={tw(
      '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
			data-testid="childrenParent"
      className={tw(
				'flex-auto min-w-0 flex items-center gap-2',
				iconAfterChildren ? 'flex-row-reverse' : 'flex-row',
			)}
    >
			{icon && (
				<span
					data-testid="icon"
				>
					{icon}
				</span>
			)}
			{(children || subtext) && (
				<span
					className={tw(
						'min-w-0 flex-auto',
						{
							'text-left': compact || menuItem,
							'text-center': !(compact || menuItem),
						},
					)}
				>
					{children && (
						<span
							className={tw(
								'block uppercase font-bold w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded h-[1.1em]',
							)}
							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>
			)}
    </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>
    )}
  </ActionButtonDerivedElementComponent>
));

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,
	icon: undefined,
	iconAfterChildren: false as const,
};
