import { useEffect, useState } from 'react'

import { omitThemingProps, styled, th, useStyleConfig, vui } from '../core'
import Icon from '../icon'
import T from '../t'
import { ChangeEvent, cs, filterUndefined } from '../utils'
import { CheckboxProps, CheckboxStyleProps } from './checkbox.types'
import { checkboxColors, disabled } from './consts'
import { useCheckboxGroupContext } from './context'

const CheckboxControl = styled.spanBox`
  border-radius: none;
  display: inline-flex;
  flex-shrink: 0;
  position: relative;
  transition-duration: fast;
`

const CheckboxInput = styled.input`
  cursor: inherit;
  height: 100%;
  left: 0;
  margin: 0;
  opacity: 0;
  padding: 0;
  position: absolute;
  top: 0;
  width: 100%;
  z-index: 1;
`

export const CheckboxBase = styled.labelBox<CheckboxStyleProps>`
  cursor: pointer;
  display: inline-flex;
  width: fit-content;

  &:not([aria-disabled='true']):hover .vui-checkboxControl {
    color: ${p => th.color(p.controlHoverColor)};
  }

  .vui-checkboxControl:focus-within {
    color: ${checkboxColors.focus};
  }

  &[aria-disabled='true'] {
    color: ${disabled.text};
    cursor: not-allowed;

    .vui-checkboxControl {
      color: ${disabled.icon};
    }
  }
`

/**
 * Allows selection of one or more choices from a set of items. Handles controlled and uncontrolled modes.
 * Uses icons to display itself in different states. Can be indeterminate when selecting some nested items.
 */
export const Checkbox = vui<'span', CheckboxProps>((props, ref) => {
  const { defaultValue: groupDefaultValue, ...checkboxGroupProps } = useCheckboxGroupContext() ?? {}

  const mergedProps = { ...checkboxGroupProps, ...props }
  const {
    checked,
    children,
    className,
    defaultChecked = groupDefaultValue !== undefined ? groupDefaultValue.includes(props.value) : undefined,
    disabled,
    icon: iconProp = 'cuiCheckboxUnselected',
    iconChecked = 'cuiCheckboxSelected',
    iconIndeterminate = 'cuiCheckboxIndeterminate',
    id,
    inputProps,
    inputRef,
    isIndeterminate,
    label,
    name,
    onChange: onChangeProp,
    required,
    value,
    ...rest
  } = omitThemingProps(mergedProps)
  const [isChecked, setIsChecked] = useState(defaultChecked)
  const styles = useStyleConfig('Checkbox', mergedProps)
  const { color: controlColor, hoverColor, ...controlStyles } = styles.control

  const icon = isIndeterminate ? iconIndeterminate : isChecked ? iconChecked : iconProp
  const controlMr = children || label ? 1 : 0
  const color = isChecked || isIndeterminate ? checkboxColors.checked : controlColor
  const controlHoverColor = hoverColor ? hoverColor : checkboxColors.hover
  const isLongLabel = label && label?.length >= 60

  useEffect(() => {
    checked !== undefined && setIsChecked(checked)
  }, [checked])

  const onChange = (e: ChangeEvent) => {
    if (checked === undefined) setIsChecked(e.target.checked)
    onChangeProp?.(e)
  }

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

  return (
    <CheckboxBase
      alignItems={isLongLabel ? 'flex-start' : 'center'}
      className={cs('vui-checkbox', className)}
      controlHoverColor={controlHoverColor}
      ref={ref}
      {...styles.container}
      {...aliasedProps}
      {...rest}
    >
      <CheckboxControl
        bg="white"
        className="vui-checkboxControl"
        color={color}
        focusWithinRing={3}
        mr={controlMr}
        role="none"
        {...controlStyles}
      >
        <CheckboxInput
          className="vui-checkboxInput"
          onChange={onChange}
          ref={inputRef}
          type="checkbox"
          {...{ checked, defaultChecked, disabled, id, name, required, value }}
          {...inputProps}
        />
        <Icon className="vui-checkboxIcon" h="100%" name={icon} w="100%" />
      </CheckboxControl>

      {children ??
        (label && (
          <T className="vui-checkboxLabel" lineHeight={isLongLabel ? '26px' : 'normal'} {...styles.label}>
            {label}
          </T>
        ))}
    </CheckboxBase>
  )
})

Checkbox.displayName = 'Checkbox'
export default Checkbox
