import React, { forwardRef, HTMLAttributes } from 'react'

import classNames from 'classnames'
import PropTypes from 'prop-types'

import type { Search, SelectedOption } from './types'

export interface CMultiSelectSelectionProps extends HTMLAttributes<HTMLSpanElement> {
  ariaTagDeleteLabel?: string
  disabled?: boolean
  multiple?: boolean
  onRemove?: (option: SelectedOption) => void
  placeholder?: string
  search?: Search
  selected?: SelectedOption[]
  selectionType?: 'counter' | 'tags' | 'text'
  selectionTypeCounterText?: string
}

export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSelectionProps>(
  (
    {
      ariaTagDeleteLabel = 'Remove',
      children,
      disabled,
      multiple,
      placeholder,
      onRemove,
      search,
      selected = [],
      selectionType,
      selectionTypeCounterText,
    },
    ref
  ) => {
    return (
      <span
        className={classNames('form-multi-select-selection', {
          'form-multi-select-selection-tags': multiple && selectionType === 'tags',
        })}
        aria-live="polite"
        ref={ref}
      >
        {multiple && selectionType === 'counter' && !search && selected.length === 0 && placeholder}
        {multiple &&
          selectionType === 'counter' &&
          !search &&
          selected.length > 0 &&
          `${selected.length} ${selectionTypeCounterText}`}
        {multiple &&
          selectionType === 'tags' &&
          selected.map((option: SelectedOption, index: number) => {
            if (selectionType === 'tags') {
              return (
                <span className="form-multi-select-tag" key={index}>
                  {option.label}
                  {!disabled && !option.disabled && (
                    <button
                      className="form-multi-select-tag-delete"
                      type="button"
                      aria-label={`${ariaTagDeleteLabel} ${option.label}`.trim()}
                      onClick={() => onRemove?.(option)}
                    />
                  )}
                </span>
              )
            }
            return
          })}
        {multiple &&
          selectionType === 'text' &&
          selected.map((option, index) => (
            <span key={index}>
              {option.label}
              {index === selected.length - 1 ? '' : ','}&nbsp;
            </span>
          ))}
        {!multiple && !search && selected.map((option) => option.label)[0]}
        {children}
      </span>
    )
  }
)

CMultiSelectSelection.propTypes = {
  ariaTagDeleteLabel: PropTypes.string,
  children: PropTypes.node,
  disabled: PropTypes.bool,
  multiple: PropTypes.bool,
  onRemove: PropTypes.func,
  placeholder: PropTypes.string,
  search: PropTypes.oneOfType([
    PropTypes.bool,
    PropTypes.oneOf<'external' | 'global'>(['external', 'global']),
    PropTypes.shape({
      external: PropTypes.bool.isRequired,
      global: PropTypes.bool.isRequired,
    }),
  ]),
  selected: PropTypes.array,
  selectionType: PropTypes.oneOf(['counter', 'tags', 'text']),
  selectionTypeCounterText: PropTypes.string,
}

CMultiSelectSelection.displayName = 'CMultiSelectSelection'
