import { CSSProperties, ReactNode, useEffect, useRef, useState } from 'react'
import classNames from 'classnames'
import { CommonComponentProps } from '../../utils/types'
import { Popup } from '../popup/Popup'
import { DropdownOption } from './DropdownOption'
import { Icon } from '../icon/Icon'
import './Dropdown.scss'

import { DropdownOptionProps } from './DropdownOption'
import { useEvent } from '../../use'

export interface DropdownItemProps extends CommonComponentProps {
  className?: string
  style?: CSSProperties
  children?: ReactNode
  label?: ReactNode
  placeholder?: ReactNode
  options?: DropdownOptionProps[]
  disabled?: boolean
  value?: any
  defaultValue?: any
  onChange?: (value: any) => void
}

export function DropdownItem(props: DropdownItemProps) {
  const {
    className,
    style,
    children,
    placeholder,
    options = [],
    disabled,
    value,
    defaultValue,
    onChange,
    ...restProps
  } = props

  const [innerValue, setInnerValue] = useState(value ?? defaultValue ?? null)

  // 受控
  useEffect(() => {
    if (value != null) {
      setInnerValue(value)
    }
  }, [value])

  const [visible, setVisible] = useState(false)

  const optionsRef = useRef<HTMLDivElement>(null)
  const itemRef = useRef<HTMLDivElement>(null)

  const handleItemClick = () => {
    setVisible(!visible)
  }

  const handleDocumentClick = useEvent((event: MouseEvent) => {
    if (
      visible &&
      !optionsRef.current?.contains(event.target as Node) &&
      !itemRef.current?.contains(event.target as Node)
    ) {
      setVisible(false)
    }
  })

  useEffect(() => {
    document.addEventListener('click', handleDocumentClick)

    return () => {
      document.removeEventListener('click', handleDocumentClick)
    }
  }, [])

  const handleOptionClick = (option: DropdownOptionProps) => {
    if (option.value !== innerValue) {
      // 非受控
      if (value == null) {
        setInnerValue(option.value)
      }
      onChange?.(option.value)
    }

    setVisible(false)
  }

  const itemClass = classNames(
    's-dropdown-item',
    {
      's-dropdown-item-show': visible,
      's-dropdown-item-disabled': disabled,
    },
    className
  )

  return (
    <>
      <div
        {...restProps}
        className={itemClass}
        ref={itemRef}
        onClick={handleItemClick}
      >
        {children && <div className="s-dropdown-item-label">{children}</div>}
        {(innerValue && (
          <div className="s-dropdown-item-value">
            {options.find((option) => option.value === innerValue)?.label}
          </div>
        )) ||
          (placeholder && (
            <div className="s-dropdown-placeholder">{placeholder}</div>
          ))}

        <Icon
          prefix="si"
          name={visible ? 'caret-up-fill' : 'caret-down-fill'}
          className="s-dropdown-item-icon"
        ></Icon>
      </div>
      <Popup placement="bottom" visible={visible}>
        <div className="s-dropdown-options" ref={optionsRef}>
          {options.map((option, index) => (
            <DropdownOption
              {...option}
              key={index}
              active={option.value === innerValue}
              onClick={() => handleOptionClick(option)}
            ></DropdownOption>
          ))}
        </div>
      </Popup>
    </>
  )
}

export default DropdownItem
