import { clsx } from 'clsx';
import type { KeyboardEventHandler, MouseEvent } from 'react';

import type { CommonProps } from '../common';
import { useInputAttributes } from '../inputs/contexts';

export type SwitchProps = CommonProps & {
  /**
   * Used to describe the purpose of the switch. To be used if there is no external label (i.e. aria-labelledby is null)
   * @deprecated Use `Field` wrapper or the `aria-labelledby` attribute instead.
   */
  'aria-label'?: string;
  /** A reference to a label that describes the purpose of the switch. Ignored if aria-label is provided */
  'aria-labelledby'?: string;
  /** Identifies the element(s) that describes the element on which the attribute is set */
  'aria-describedby'?: string;
  /** Whether the switch is checked or not */
  checked?: boolean;
  disabled?: boolean;
  /** ID to apply to the switch container */
  id?: string;
  /** Function called when the switch is toggled */
  onClick: (event?: MouseEvent<HTMLButtonElement>) => void;
};

const Switch = (props: SwitchProps) => {
  const inputAttributes = useInputAttributes({ nonLabelable: true });

  const {
    checked,
    className,
    id = inputAttributes.id,
    'aria-label': ariaLabel,
    'aria-labelledby': ariaLabelledbyProp,
    'aria-describedby': ariaDescribedbyProp,
    onClick,
    disabled,
  } = props;

  const ariaLabelledby =
    (ariaLabel ? undefined : ariaLabelledbyProp) ?? inputAttributes['aria-labelledby'];

  return (
    <button
      className={clsx(
        'np-switch',
        {
          'np-switch--unchecked': !checked,
          'np-switch--checked': checked,
          disabled,
        },
        className,
      )}
      type="button"
      role="switch"
      {...inputAttributes}
      id={id}
      aria-checked={Boolean(checked)}
      aria-label={ariaLabel}
      aria-labelledby={ariaLabelledby}
      aria-describedby={ariaDescribedbyProp}
      disabled={disabled}
      onClick={!disabled ? onClick : undefined}
    >
      <span className="np-switch--thumb" />
    </button>
  );
};

export default Switch;
