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;
  /** 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<HTMLSpanElement>) => void;
};

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

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

  const handleKeyDown: KeyboardEventHandler = (event) => {
    if (event.key === ' ') {
      event.preventDefault();
      onClick();
    }
  };

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

  return (
    <span
      className={clsx(
        'np-switch',
        {
          'np-switch--unchecked': !checked,
          'np-switch--checked': checked,
          disabled,
        },
        className,
      )}
      tabIndex={0}
      role="switch"
      aria-checked={checked}
      aria-label={ariaLabel}
      {...inputAttributes}
      aria-labelledby={ariaLabelledby}
      id={id}
      aria-disabled={disabled}
      onClick={!disabled ? onClick : undefined}
      onKeyDown={!disabled ? handleKeyDown : undefined}
    >
      <span className="np-switch--thumb" />
      <input type="checkbox" checked={checked} readOnly />
    </span>
  );
};

export default Switch;
