import React, { useCallback } from 'react';
import { clsx } from 'clsx';

import { buildClassNameObject } from '../utils/misc';
import { forwardRef } from '../utils/react';
import { ChipBody, ChipBodyProps } from './chip-body';
import { useChipGroupContext } from './chip-group.context';
import * as css from './chip-select.css';

export interface ChipSelectProps
  extends Omit<
    ChipBodyProps,
    'startIcon' | 'endIcon' | 'border' | 'className'
  > {
  selected?: boolean;
  onSelect?: (state: boolean) => void;
  disabled?: boolean;
  icon?: React.ReactNode;
  value?: string;
  inputRef?: React.Ref<HTMLInputElement>;
  borderless?: boolean;
  className?: string | { container?: string; body?: string };
}

export const ChipSelect = forwardRef<'label', ChipSelectProps>(
  function ChipSelect(
    {
      children,
      disabled,
      selected,
      onSelect: userOnSelect,
      className,
      icon,
      value,
      borderless,
      inputRef,
      ...rest
    },
    ref,
  ) {
    const {
      multiple,
      checkSelected,
      onSelect: contextOnSelect,
    } = useChipGroupContext(({ onSelect, checkSelected, multiple }) => ({
      onSelect,
      checkSelected,
      multiple,
    }));

    const isContextAvailable = !!(checkSelected && value);
    const isSelected = !!(
      selected ||
      (isContextAvailable && checkSelected(value))
    );
    const type = !isContextAvailable || multiple ? 'checkbox' : 'radio';

    const onSelect: React.ChangeEventHandler<HTMLInputElement> = useCallback(
      event => {
        const nextState = event.target.checked;

        userOnSelect && userOnSelect(nextState);
        isContextAvailable && contextOnSelect(value, nextState);
      },
      [userOnSelect, contextOnSelect, value, isContextAvailable],
    );

    const border = borderless ? 'none' : isSelected ? 'wide' : 'thin';

    const cn = buildClassNameObject(className, 'container');

    return (
      <label
        {...rest}
        ref={ref}
        data-selected={isSelected}
        className={clsx(cn.container, css.select)}
      >
        <input
          value={value}
          type={type}
          className={css.input}
          checked={isSelected}
          disabled={disabled}
          onChange={onSelect}
          ref={inputRef}
        />
        <ChipBody
          startIcon={icon}
          disabled={disabled}
          className={clsx(
            cn.body,
            css.body({ disabled, selected: isSelected }),
          )}
          customHover
          border={border}
        >
          {children}
        </ChipBody>
      </label>
    );
  },
);
