import React, { useMemo } from 'react'

import { styled, useStyleConfig, vui, VuiComponent } from '../core'
import { cs, filterUndefined, isReactText } from '../utils'
import { SwitchProvider } from './context'
import { SwitchProps } from './switch.types'
import { SwitchButton } from './switchButton'
import { SwitchLabel } from './switchLabel'

export const SwitchBase = styled.labelBox`
  align-items: center;
  cursor: pointer;
  display: inline-flex;
  line-height: normal;
  width: fit-content;

  &[aria-disabled='true'] {
    cursor: not-allowed;

    .vui-switchLabel {
      color: disabled.color;
    }
  }
`

/**
 * Displays a toggle button with supporting text. Allows passing custom elements as side labels and inner labels.
 * Forwards many relevant props to the innner input element. Exposes some props to the children via context.
 */
export const Switch = vui<'label', SwitchProps>((props, ref) => {
  const {
    button,
    checked,
    children,
    className,
    defaultChecked,
    disabled,
    id,
    innerLabelOff,
    innerLabelOn,
    inputProps,
    inputRef,
    labelLeft,
    labelRight,
    name,
    onBlur,
    onChange,
    onFocus,
    required,
    size,
    value,
    variant,
    ...rest
  } = props
  const styles = useStyleConfig('Switch', props)

  const context = useMemo(
    () =>
      filterUndefined({
        checked,
        defaultChecked,
        disabled,
        name,
        onBlur,
        onChange,
        onFocus,
        required,
        size,
        value,
        variant,
      }),
    [checked, defaultChecked, disabled, name, onBlur, onChange, onFocus, required, size, value, variant],
  )

  const aliasedProps = filterUndefined({
    'aria-disabled': disabled,
  })

  return (
    <SwitchProvider value={context}>
      <SwitchBase className={cs('vui-switch', className)} ref={ref} {...styles.container} {...aliasedProps} {...rest}>
        {isReactText(labelLeft) ? <SwitchLabel mr={1} text={labelLeft} /> : labelLeft}

        {children ?? button ?? <SwitchButton {...{ id, innerLabelOff, innerLabelOn, inputProps, inputRef }} />}

        {isReactText(labelRight) ? <SwitchLabel ml={1} text={labelRight} /> : labelRight}
      </SwitchBase>
    </SwitchProvider>
  )
}) as VuiComponent<'label', SwitchProps> & {
  Button: typeof SwitchButton
  Label: typeof SwitchLabel
}

Switch.Button = SwitchButton
Switch.Label = SwitchLabel
Switch.displayName = 'Switch'

export default Switch
