import './Button.scss';

import { AnchorHTMLAttributes, ButtonHTMLAttributes, forwardRef, FunctionComponent, SVGProps } from 'react';

const sparkClassNames = {
  button: 'spark-button spark-focus-visible spark-focus-visible-self spark-focus-visible-snap',
  buttonSizePrefix: 'spark-button-size-',
  buttonVariantPrefix: 'spark-button-',
  disabledButton: 'spark-button-disabled',
  buttonStartSlot: 'spark-button-start-slot',
  buttonContent: 'spark-button-content',
  buttonOnly: 'spark-button-icon-only',
};

type ButtonVariant = 'action' | 'primary' | 'secondary' | 'ghost';

type ButtonSize = 'l' | 'm' | 's';

type AsElementProps =
  | (ButtonHTMLAttributes<HTMLButtonElement> & { as?: 'button' })
  | (AnchorHTMLAttributes<HTMLAnchorElement> & { as?: 'link' });

type ButtonProps = {
  text?: string;
  variant?: ButtonVariant;
  size?: ButtonSize;
  disabled?: boolean;
  value?: string;
  onClick?: () => void;
  icon?: FunctionComponent<SVGProps<SVGSVGElement>>;
  className?: string;
} & AsElementProps;

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
  { text, as = 'button', variant = 'primary', size = 'm', disabled = false, onClick, icon, className, ...props },
  ref
): JSX.Element {
  const sizeClassName = `${sparkClassNames.buttonSizePrefix}${size}`;
  const variantClassName = `${sparkClassNames.buttonVariantPrefix}${variant}`;
  const classNames = [sparkClassNames.button, sizeClassName, variantClassName];

  if (disabled) {
    classNames.push(sparkClassNames.disabledButton);
  }

  if (!text && icon) {
    classNames.push(sparkClassNames.buttonOnly);
  }

  if (className) {
    classNames.push(className);
  }

  const buttonContent = (
    <>
      {icon && <span className={sparkClassNames.buttonStartSlot}>{icon({ className: 'button-icon' })}</span>}
      <span className={sparkClassNames.buttonContent}>{text}</span>
    </>
  );

  if (as === 'link') {
    return (
      <a
        className={classNames.join(' ')}
        href={(props as AnchorHTMLAttributes<HTMLAnchorElement>).href}
        target="_blank"
        rel="noreferrer"
        aria-label={text}
      >
        {buttonContent}
      </a>
    );
  }

  return (
    <button
      className={classNames.join(' ')}
      type="button"
      role="radio"
      onClick={(e) => onClick?.(e)}
      aria-label={text}
      ref={ref}
    >
      {buttonContent}
    </button>
  );
});
