// TODO: Update DropdownProps["value"] so the type matches SelectHTMLAttributes["value"]
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useCallback, useMemo, useState } from 'react'
import classNames from 'classnames'
import Each from '@komi-app/each'
import When from '@komi-app/when'
import styles from './dropdownMenu.module.scss'
import { DropdownMenuItem } from './item'
import selfless from '@komi-app/selfless'
import { MdSearch as Search } from 'react-icons/md'

import type { DropdownItem } from '../Dropdown'
import { TextInputField } from '@komi-app/creator-ui'
import { filterOptions } from './utils'

export enum DropdownItemType {
  LABEL = 'label',
  OBJECT = 'object'
}

export type DropdownMenuProps = Omit<
  React.HTMLAttributes<HTMLUListElement>,
  'onChange'
> & {
  current?: DropdownItem
  items: DropdownItem[]
  name: string
  value?: any
  multiple?: boolean
  emptyLabel?: string
  selectedItems: DropdownItem[]
  hasSearch?: boolean
  searchPlaceholder?: string
  onChange?: (value: DropdownItem, remove?: boolean) => void
}

export interface DropdownMenuViewProps
  extends Omit<DropdownMenuProps, 'onChange'> {
  containerClassName: string
  classify: (item: DropdownItem) => DropdownItemType
  change: (value: DropdownItem, remove?: boolean) => void
}

export const DEFAULT_EMPTY_LABEL = 'No data'

export const useDropdownMenu = ({
  onChange,
  items,
  ...props
}: DropdownMenuProps): DropdownMenuViewProps => ({
  containerClassName: classNames(styles.container, {
    [styles.container__empty]: !items.length
  }),
  classify: (item: DropdownItem) =>
    typeof item === 'string' ? DropdownItemType.LABEL : DropdownItemType.OBJECT,
  change: useCallback(
    (value: DropdownItem, remove?: boolean) => {
      onChange && onChange(value, remove)
    },
    [onChange]
  ),
  items,
  ...props
})

export const DropdownMenuView = ({
  name,
  current,
  containerClassName,
  selectedItems,
  items,
  multiple,
  emptyLabel = DEFAULT_EMPTY_LABEL,
  change,
  hasSearch,
  searchPlaceholder,
  ...props
}: DropdownMenuViewProps) => {
  const [searchValue, setSearchValue] = useState<string>('')
  const filteredOptions = useMemo(
    () => filterOptions(items, searchValue),
    [items, searchValue]
  )

  const searchHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    const searchedValue = e.target.value || ''
    setSearchValue(searchedValue)
  }

  return (
    <ul
      className={classNames(containerClassName, {
        [styles.container__empty]: !filteredOptions.length
      })}
      role="listbox"
      {...props}
    >
      <When
        value={hasSearch}
        then={
          <TextInputField
            prefixIcon={<Search size={24} />}
            placeholder={searchPlaceholder || 'Search'}
            onChange={searchHandler}
            value={searchValue}
          />
        }
      />

      <Each
        values={filteredOptions}
        layout={(item: DropdownItem) => (
          <DropdownMenuItem
            name={name}
            item={item}
            selectedItems={selectedItems}
            multiple={multiple}
            current={current}
            onChange={change}
          />
        )}
        otherwise={
          <DropdownMenuItem
            name={name}
            item={{
              value: emptyLabel,
              disabled: true
            }}
            onChange={change}
          />
        }
      />
    </ul>
  )
}

export const DropdownMenu = selfless(DropdownMenuView, useDropdownMenu)
export default DropdownMenu
