import {
  CSSProperties,
  ReactNode,
  ReactElement,
  Children,
  useState,
  useEffect,
  cloneElement,
} from 'react'
import classNames from 'classnames'
import { CommonComponentProps } from '../../utils/types'
import './Accordion.scss'

import { AccordionItem, AccordionItemProps } from './AccordionItem'

export * from './AccordionItem'

interface AccordionBaseProps extends CommonComponentProps {
  className?: string
  style?: CSSProperties
  children?: ReactNode
  duration?: number
  onChange?: (name: any) => void
}

interface AccordionSingleProps extends AccordionBaseProps {
  multiple?: false
  defaultActiveName?: any
  activeName?: any
}

interface AccordionMultipleProps extends AccordionBaseProps {
  multiple?: true
  defaultActiveName?: any[]
  activeName?: any[]
}

export type AccordionProps = AccordionSingleProps | AccordionMultipleProps

export function Accordion(props: AccordionProps) {
  const {
    className,
    style,
    children,
    defaultActiveName,
    activeName,
    multiple = false,
    duration,
    onChange,
    ...restProps
  } = props

  const [innerName, setInnerName] = useState(() => {
    return activeName ?? defaultActiveName ?? (multiple ? [] : '')
  })

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

  const handleItemClick = (name: any) => {
    if (multiple) {
      name = innerName.includes(name)
        ? innerName.filter((item: any) => item !== name)
        : [...innerName, name]
    } else {
      name = name !== innerName ? name : ''
    }
    // 非受控
    if (activeName == null) {
      setInnerName(name)
    }
    onChange?.(name)
  }

  const accordionClass = classNames('s-accordion', className)

  return (
    <div {...restProps} className={accordionClass}>
      {Children.map(
        children as ReactElement<AccordionItemProps>,
        (item: ReactElement<AccordionItemProps>, index: number) => {
          const name = item.props.name ?? index
          return cloneElement(item, {
            name,
            multiple,
            activeName: innerName,
            duration: item.props.duration ?? duration,
            onClick: () => handleItemClick(name),
          })
        }
      )}
    </div>
  )
}

Accordion.Item = AccordionItem

export default Accordion
