import * as React from 'react';
import clsx from 'clsx';
import plugin from 'tailwindcss/plugin';
import { useFallbackId } from '@modal-sh/react-utils';

/**
 * Derived HTML element of the {@link RadioTickBox} component.
 */
export type RadioTickBoxDerivedElement = HTMLInputElement;

/**
 * Props of the {@link RadioTickBox} component.
 */
export interface RadioTickBoxProps extends Omit<React.InputHTMLAttributes<RadioTickBoxDerivedElement>, 'type' | 'size'> {
  /**
   * Should the component occupy the whole width of its parent?
   */
  block?: boolean;
  /**
   * Complementary content of the component.
   */
  subtext?: React.ReactNode;
}

export const radioTickBoxPlugin = plugin(({ addComponents }) => {
  addComponents({
    '.radio-tick-box': {
      '& + label + label > :first-child > :first-child': {
        'display': 'none',
      },
      '&:checked + label + 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 tick box, i.e. a typical radio button.
 */
export const RadioTickBox = React.forwardRef<RadioTickBoxDerivedElement, RadioTickBoxProps>((
  {
    children,
    block = false as const,
    id: idProp,
    className,
    subtext,
    style,
    ...etcProps
  },
  forwardedRef,
) => {
  const id = useFallbackId(idProp);

  return (
    <div
      className={clsx(
        'gap-x-4 flex-wrap',
        block && 'flex',
        !block && 'inline-flex align-center',
        className,
      )}
      style={style}
      data-testid="base"
    >
      <input
        {...etcProps}
        ref={forwardedRef}
        type="radio"
        id={id}
        className="sr-only peer/radio radio-tick-box"
      />
      <label
        htmlFor={id}
        className="peer/children order-2 cursor-pointer peer-disabled/radio:cursor-not-allowed"
      >
        <span
          data-testid="children"
        >
          {children}
        </span>
      </label>
      <label
        htmlFor={id}
        className={clsx(
          'order-1 block rounded-full ring-secondary/50 overflow-hidden gap-4 leading-none select-none cursor-pointer',
          'peer-focus/radio:outline-0 peer-focus/radio:ring-4 peer-focus/radio:ring-secondary/50',
          'active:ring-tertiary/50 active:ring-4',
          'peer-active/children:ring-tertiary/50 peer-active/children:ring-4 peer-active/children:text-tertiary',
          'peer-disabled/radio:opacity-50 peer-disabled/radio:cursor-not-allowed peer-disabled/radio:ring-0',
          'text-primary peer-disabled/radio:text-primary peer-focus/radio:text-secondary peer-checked/radio:text-tertiary active:text-tertiary',
        )}
      >
        <span
          className={clsx(
            'w-6 h-6 block rounded-full border-2 p-0.5 box-border border-current',
          )}
        >
          <span
            className={clsx(
              'w-full h-full rounded-full bg-current text-current',
            )}
          />
        </span>
      </label>
      {subtext && (
        <div
          className="block w-full text-xs pl-10 order-3"
          data-testid="subtext"
        >
          {subtext}
        </div>
      )}
    </div>
  );
});

RadioTickBox.displayName = 'RadioTickBox' as const;

RadioTickBox.defaultProps = {
  block: false as const,
  subtext: undefined,
};
