import classNames from 'classnames'
import dayjs from 'dayjs'
import { useState, useEffect } from 'react'
import './index.less'

enum ModeType {
  LINE = 'line',
  CARD = 'card'
}

type TimeLineListProps<T> = {
  rowKey?: ((item: T) => React.Key) | keyof T
  dataSource: T[]
  renderItem?: (item: T, index: number) => React.ReactNode
  dataField: keyof T
  mode: 'line' | 'card'
}

function TimeLineList<T>({
  dataField = 'createTime',
  dataSource = [],
  mode = 'line',
  renderItem
}: TimeLineListProps<T>) {
  // 用二维数组去存数据
  const [dataMap, setDataMap] = useState<Nullable<T[][]>>(null)

  useEffect(() => {
    const formatTimeMap = () => {
      // 先去重，按日期进行分组
      const uniKeys = Array.from(new Set(dataSource.map(item => item?.[dataField])))
      const uniDataMap = []
      // 构建二维数组
      uniKeys.forEach(key => {
        uniDataMap.push(dataSource.filter(item => item?.[dataField] === key))
      })
      setDataMap(uniDataMap)
    }
    dataSource?.length && formatTimeMap(dataSource)
  }, [dataSource])

  if (!dataMap) return null

  // 渲染左侧日期
  const renderDate = (dataIndex: number, diffTime: number, renderTime: dayjs.Dayjs) => {
    let node = null
    if (dataIndex === 0) {
      switch (diffTime) {
        case 0:
          node = '今天'
          break
        case 1:
          node = '昨天'
          break
        case 2:
          node = renderTime.format('MM-DD')
          break
        default:
          node = (
            <div
              className={classNames('flex flex-col justify-center', {
                'items-center': mode === ModeType.LINE
              })}>
              <span className="year">{renderTime.get('year')}</span>
              <span className="date">{renderTime.format('MM-DD')}</span>
            </div>
          )
          break
      }
    }
    return node
  }

  // render mode timeline
  const renderTimelineItem = () => {
    return dataMap.map(t =>
      t.map((item, i) => {
        const itemTime = dayjs(item?.[dataField])
        const currentTime = dayjs()
        if (itemTime && currentTime) {
          const renderTime = currentTime.diff(itemTime, 'day')
          return (
            <div key={item.id} className="time-item-content time-item-has-line">
              <div className="time-item-label time-item-label-has-line">
                <div
                  className={classNames(i > 0 ? 'time-item-label-square' : 'time-item-label-base', {
                    'time-item-label-forward': renderTime <= 2
                  })}>
                  {renderDate(i, renderTime, itemTime)}
                </div>
              </div>
              <div className="time-item-render time-item-render-has-line">{renderItem?.(item, i)}</div>
            </div>
          )
        }
        return null
      })
    )
  }

  // render mode card
  const renderCardItem = () => {
    return dataMap.map(t =>
      t.map((item, i) => {
        const itemTime = dayjs(item?.[dataField])
        const currentTime = dayjs()
        if (itemTime && currentTime) {
          const renderTime = currentTime.diff(itemTime, 'day')
          return (
            <div
              key={item.id}
              className={classNames('time-item-content time-item-has-card', {
                'time-item-last': t.length - 1 === i
              })}>
              <div className="time-item-label time-item-label-has-card">
                <div
                  className={classNames('time-item-label-base', {
                    'time-item-label-forward': renderTime <= 2
                  })}>
                  {renderDate(i, renderTime, itemTime)}
                </div>
              </div>
              <div className="time-item-render time-item-render-has-card">{renderItem?.(item, i)}</div>
              <div className={classNames({ 'time-item-label-tail': t.length - 1 === i })} />
            </div>
          )
        }
        return null
      })
    )
  }

  return (
    <div className="w-full h-full time-list-container">
      {mode === ModeType.LINE ? renderTimelineItem() : renderCardItem()}
    </div>
  )
}
export default TimeLineList
