import * as React from 'react';
import { Button, tailwind } from '@tesseract-design/web-base';
import { useFallbackId } from '@modal-sh/react-utils';
import { PluginCreator } from 'tailwindcss/types/config';

const { tw } = tailwind;

const RadioButtonDerivedElementComponent = 'input' as const;

/**
 * Derived HTML element of the {@link RadioButton} component.
 */
export type RadioButtonDerivedElement = HTMLElementTagNameMap[
  typeof RadioButtonDerivedElementComponent
];

/**
 * Props of the {@link RadioButton} component.
 */
export interface RadioButtonProps extends Omit<React.InputHTMLAttributes<RadioButtonDerivedElement>, 'type' | 'size'> {
  /**
   * Should the component occupy the whole width of its parent?
   */
  block?: boolean;
  /**
   * Should the component's content use minimal space?
   */
  compact?: boolean;
  /**
   * Size of the component.
   */
  size?: Button.Size;
  /**
   * Complementary content of the component.
   */
  subtext?: React.ReactNode;
  /**
   * Short complementary content displayed at the edge of the component.
   */
  badge?: React.ReactNode;
  /**
   * Variant of the component.
   */
  variant?: Button.Variant;
}

export const radioButtonPlugin: PluginCreator = ({ addComponents }) => {
  addComponents({
    '.radio-button': {
      '& + label > :first-child > :first-child': {
        'display': 'none',
      },
      '&:checked + label > :first-child > :first-child': {
        'display': 'block',
      },
    },
  });
};

/**
 * Component for selecting a single value from an array of choices grouped by name.
 *
 * This component is displayed as a regular button.
 */
export const RadioButton = React.forwardRef<RadioButtonDerivedElement, RadioButtonProps>((
  {
    children,
    block = false as const,
    compact = false as const,
    size = 'medium' as const,
    id: idProp,
    className,
    subtext,
    badge,
    variant = 'bare' as const,
    style,
    ...etcProps
  },
  forwardedRef,
) => {
  const id = useFallbackId(idProp);

  return (
    <span
      className="contents"
    >
      <RadioButtonDerivedElementComponent
        {...etcProps}
        ref={forwardedRef}
        type="radio"
        id={id}
        className="sr-only peer radio-button"
      />
      <label
        style={style}
        htmlFor={id}
        data-testid="button"
        className={tw(
          'items-center justify-start rounded overflow-hidden ring-secondary/50 leading-none select-none cursor-pointer relative',
          'peer-focus:outline-0 peer-focus:ring-4 peer-focus:ring-secondary/50',
          'active:ring-tertiary/50 active:ring-4',
          'peer-disabled:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:ring-0',
					'text-primary focus:text-secondary active:text-tertiary',
          {
            'flex w-full': block,
            'inline-flex max-w-full align-middle': !block,
          },
          {
            'pl-2 gap-2 pr-2': compact,
            'pl-4 gap-4 pr-4': !compact,
          },
					{
						'bg-current': variant === 'filled',
					},
          {
            'text-primary peer-disabled:text-primary peer-focus:text-secondary peer-checked:text-tertiary active:text-tertiary': variant !== 'filled',
            'bg-primary text-negative peer-disabled:bg-primary peer-focus:bg-secondary peer-checked:bg-tertiary active:bg-tertiary': variant === 'filled',
          },
          {
            'h-10': size === 'small',
            'h-12': size === 'medium',
            'h-16': size === 'large',
          },
          className,
        )}
      >
        <span
          className={tw(
            'w-6 h-6 block rounded-full border-2 p-0.5 box-border',
            {
              'border-current': variant !== 'filled',
              'border-negative': variant === 'filled',
            },
          )}
        >
          <span
            className={tw(
              'w-full h-full rounded-full bg-current',
              {
                'text-current': variant !== 'filled',
                'text-negative': variant === 'filled',
              },
            )}
          />
        </span>
        <span
          className={tw(
            'contents',
            {
              'text-current': variant !== 'filled',
              'text-negative': variant === 'filled',
            },
          )}
        >
          <span
            className={tw(
              'flex-auto min-w-0',
            )}
          >
            <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>
            </>
          )}
        </span>
				{
					variant !== 'bare'
					&& (
						<span
							className="border-current border-2 rounded-inherit absolute w-full h-full top-0 left-0"
						/>
					)
				}
      </label>
    </span>
  );
});

RadioButton.displayName = 'RadioButton' as const;

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