import {
  CSSProperties,
  ReactNode,
  useEffect,
  useId,
  useRef,
  useState,
} from 'react'
import classNames from 'classnames'
import { Transition } from '../transition/Transition'
// import { Transition } from 'react-transition-group'
import { reflow, animate, AnimateStop } from '../../utils'
import { useCallbackState, useEvent, useSelectorId } from '../../use'
import { getBoundingClientRect } from '../../utils/dom'
import { CommonComponentProps } from '../../utils/types'
import './Collapse.scss'

interface TransitionHookWrap {
  (): void
}

const CLS_SHOW = 's-show'
const CLS_COLLAPSING = 's-collapsing'

export interface CollapseProps extends CommonComponentProps {
  className?: string
  style?: CSSProperties
  children?: ReactNode
  visible?: boolean
  duration?: number
  onEnter?: () => void
  onEntering?: () => void
  onEntered?: () => void
  onExit?: () => void
  onExiting?: () => void
  onExited?: () => void
}

export function Collapse(props: CollapseProps) {
  const {
    className,
    style,
    children,
    visible = false,
    duration = 300,
    onEnter,
    onEntering,
    onEntered,
    onExit,
    onExiting,
    onExited,
    ...restProps
  } = props

  const id = useSelectorId()

  const [classList, setClassList] = useCallbackState<string[]>([])
  const [height, setHeight] = useCallbackState<string | number>('')

  const handleEnter = useEvent(() => {
    setClassList([CLS_SHOW], () => {
      getBoundingClientRect('#' + id, (rect) => {
        setClassList([CLS_SHOW, CLS_COLLAPSING])
        setHeight(0, () => {
          setTimeout(() => {
            setHeight(rect.height)
          }, 10)
        })
      })
    })
    onEnter?.()
  })

  const handleEntering = useEvent(() => {
    onEntering?.()
  })

  const handleEntered = useEvent(() => {
    setClassList([CLS_SHOW])
    setHeight('')
    onEntered?.()
  })

  const handleExit = useEvent(() => {
    setClassList([CLS_SHOW, CLS_COLLAPSING])
    getBoundingClientRect('#' + id, (rect) => {
      setHeight(rect.height, () => {
        setTimeout(() => {
          setHeight(0)
        }, 10)
      })
    })
    onExit?.()
  })

  const handleExiting = useEvent(() => {
    onExiting?.()
  })

  const handleExited = useEvent(() => {
    setHeight('')
    setClassList([])
    onExited?.()
  })

  const collapseClass = classNames('s-collapse', classList, className)
  const collapseStyle = {
    height,
    transitionDuration: duration + 'ms',
    ...style,
  }

  return (
    <Transition
      {...restProps}
      timeout={{
        enter: duration,
        exit: duration,
        appear: 0,
      }}
      in={visible}
      appear
      onEnter={handleEnter}
      onEntering={handleEntering}
      onEntered={handleEntered}
      onExit={handleExit}
      onExiting={handleExiting}
      onExited={handleExited}
    >
      <div className={collapseClass} style={collapseStyle} id={id}>
        {children}
      </div>
    </Transition>
  )
}

export default Collapse
