import React, { FC } from 'react';
import tw, { styled } from 'twin.macro';

import {
  buttonColorVariantStyle,
  buttonLinkColorStyle,
  buttonLinkSizeStyle,
  buttonRingStyle,
  buttonSizeStyle,
  buttonVariantStyle,
} from './styles';
import { AnchorSpecificProps, ButtonProps, ButtonSpecificProps } from './types';

const Button = styled.button<Omit<ButtonProps, 'as'> & ButtonSpecificProps>(
  ({
    variant = 'secondary',
    color = 'brand',
    size = 'md',
    disabled,
    block,
  }) => [
    // Base styles
    tw`
    rounded font-bold font-sans transform-gpu transition duration-200 active:scale-95 leading-5
    focus:outline-none`,

    buttonVariantStyle[variant],
    buttonColorVariantStyle[color]?.[variant],
    buttonRingStyle[color],
    buttonSizeStyle[size],

    disabled && tw`opacity-disabled`,

    block && tw`w-full`,
  ],
);

const ButtonLink = styled.a<
  Omit<ButtonProps, 'variant' | 'as'> & AnchorSpecificProps
>(({ size = 'md', color = 'brand', disabled }) => [
  tw`font-semibold underline cursor-pointer`,

  buttonLinkSizeStyle[size],
  buttonLinkColorStyle[color],

  disabled && tw`pointer-events-none text-gray-500`,
]);

const ButtonComponent: FC<
  ButtonProps & (ButtonSpecificProps | AnchorSpecificProps)
> = ({
  as = 'button',
  variant = 'secondary',
  color = 'brand',
  size = 'md',
  disabled,
  ...props
}) => {
  const defaultComponent = (
    <Button
      variant={variant}
      color={color}
      size={size}
      disabled={disabled}
      {...(props as ButtonSpecificProps)}
    />
  );

  switch (as) {
    case 'button':
      return defaultComponent;
    case 'a':
      return (
        <ButtonLink
          color={color}
          size={size}
          disabled={disabled}
          {...(props as AnchorSpecificProps)}
        />
      );
    default:
      return defaultComponent;
  }
};

export default Button;
