import React, { memo, useEffect, useRef, useState } from 'react'
import { CloseCircleFilled, DownOutlined } from '@ant-design/icons'
import { Dropdown, Menu, Tag, Button, Select, Badge } from 'antd'
import { Icon } from '../icons'
import { ClassNamesFn } from '../../theme'

interface FilterItem {
  name: string
  label: string
  value: string
}

interface IProps {
  filters?: FilterItem[]
  advancedFilters?: FilterItem[]
  globalFilters?: (FilterItem & { isNumber?: boolean })[]
  onFilterRemove?: (name: string) => void
  onAdvancedFilterRemove?: (name: string) => void
  onGlobalFilterChange?: (values: object) => void
  buttonGroup?: React.ReactNode
  cx: ClassNamesFn
}

const CrudFilter: React.FC<IProps> = (props) => {

  const { filters, advancedFilters, globalFilters, buttonGroup, cx, onFilterRemove, onAdvancedFilterRemove, onGlobalFilterChange } = props

  const [isOverflow, setIsOverflow] = useState(false)

  const [hoverId, setHoverId] = useState<string>()

  const menuRef = useRef<HTMLUListElement>(null)

  useEffect(() => {
    const resizeObserver = new ResizeObserver(entries => {
      for (const entry of entries) {
        if (entry.target == menuRef.current) {
          const element = menuRef.current
          setIsOverflow(element.scrollWidth > element.clientWidth)
          break
        }
      }
    })
    resizeObserver.observe(menuRef.current!)
    return () => {
      resizeObserver.disconnect()
    }
  }, [])

  useEffect(() => {
    const element = menuRef.current
    if (element) {
      setIsOverflow(element.scrollWidth > element.clientWidth)
    }
  }, [filters])

  const renderTags = (onPopover: boolean) => {
    const renderItem = (item: FilterItem, isAdvanced: boolean) => {
      const { name, label, value } = item
      return (
        <li className='filter-menu-item' key={name} style={{ marginBottom: onPopover ? 6 : undefined }}>
          <Tag
            className={isAdvanced ? 'is-advanced' : ''}
            style={{ fontSize: 12, marginRight: 0 }}
            closable
            closeIcon={<CloseCircleFilled style={{ fontSize: 12, lineHeight: 'normal', opacity: hoverId == onPopover + name ? 1 : 0 }} />}
            onMouseEnter={() => { setHoverId(onPopover + name) }}
            onMouseLeave={() => { setHoverId(undefined) }}
            onClose={(e) => {
              e.preventDefault();
              isAdvanced ? onAdvancedFilterRemove?.(name) : onFilterRemove?.(name)
            }}
          >
            <span className="text"> {label + ':' + value} </span>
          </Tag>
        </li>
      )
    }
    return (
      <>
        {filters?.map((item) => renderItem(item, false))}
        {advancedFilters?.map((item) => renderItem(item, true))}
      </>
    )
  }

  return (
    <div className={cx('Crud-head-filter')} >
      <span style={{ fontSize: 13, fontWeight: 500, whiteSpace: 'nowrap' }}>数据查询</span>
      <ul className='filter-menu' ref={menuRef} >
        {renderTags(false)}
      </ul>
      <Dropdown
        trigger={['click']}
        placement='bottomRight'
        overlay={(
          <Menu style={{ maxHeight: 400, overflow: 'auto', display: 'flex', flexDirection: 'column', padding: 6 }}>
            {renderTags(true)}
          </Menu>
        )}
      >
        <DownOutlined style={{ color: 'rgba(0,0,0,0.3)', margin: '0 8px', fontSize: 12, visibility: isOverflow ? undefined : 'hidden' }} />
      </Dropdown>
      <div className='filter-search-wrapper'>
        <div className="filter-search-items">
          {(globalFilters && onGlobalFilterChange) && <GlobalFilter globalFilters={globalFilters} onGlobalFilterChange={onGlobalFilterChange} />}
          {buttonGroup}
        </div>
      </div>
    </div>
  )
}

export default memo(CrudFilter)

const SPLIT_CHAR = '·'

const GlobalFilter: React.FC<{ globalFilters: (FilterItem & { isNumber?: boolean })[], onGlobalFilterChange: (values: object) => void }> = ({ globalFilters, onGlobalFilterChange }) => {

  const [globalValue, setGlobalValue] = useState<{ name: string, label: string, value: string }[]>([])

  const [options, setOptions] = useState<{ name: string, label: string, value: string }[]>([])

  const [gHoverId, setGHoverId] = useState<string | number>()

  return (
    <div className='filter-select-wrap'>
      <Icon symbol icon='#icon-tooltool_search' />
      <Select
        className='filter-select'
        size='small'
        placeholder={`搜索${globalFilters.filter(item => !item.name.includes('globalFilterAll')).map(item => item.label).join('/')}`}
        mode={'multiple'}
        notFoundContent={<span style={{ fontSize: 12 }}>'空格代表“或”，回车代表“且”'</span>}
        maxTagCount='responsive'
        autoClearSearchValue={true}
        bordered={false}
        showArrow={false}
        value={globalValue}
        labelInValue={true}
        onSearch={value => {
          if (value.length == 0) {
            setOptions([])
          } else {
            const isNum = !Number.isNaN(+(value.replaceAll(' ', '')))
            setOptions(globalFilters.filter(item => isNum ? true : !item.isNumber).map(item => {
              return { label: item.label + ':' + value, value: item.name + SPLIT_CHAR + value, name: item.name }
            }))
          }
        }}
        onBlur={() => setOptions([])}
        onChange={(values, options) => {
          setGlobalValue(values)
          if (Array.isArray(options)) {
            const obj = {}
            options.forEach((item) => {
              if (typeof item.value == 'string') {
                const [a, b] = item.value.split(SPLIT_CHAR)
                const key = a.substring(a.indexOf('.') + 1)
                const value = b.replaceAll(' ', ',')
                obj[key] = value
              }
            })
            onGlobalFilterChange(obj)
            setOptions([])
          }
        }}
        tagRender={props => {
          const { label, onClose } = props
          const [title, value] = typeof label == 'string' ? label.split(':') : ''
          return (
            <div className='filter-select-tag'>
              <span className='filter-select-tag-label'>{title}</span>
              <Badge offset={[0, -4]} count={<CloseCircleFilled onClick={() => { onClose() }} style={{ fontSize: 12, color: 'red' }} />}>
                <span className='filter-select-tag-value'>{value.replaceAll(' ', '或')}</span>
              </Badge>
            </div>
          )
        }}
        maxTagPlaceholder={values => (
          <Dropdown
            overlay={(
              <Menu style={{ maxHeight: 400, overflow: 'auto', display: values.length > 0 ? 'flex' : 'none', flexDirection: 'column', padding: 12 }}>
                {values.map(({ label, value }, index, arr) => {
                  const [title, _value] = typeof label == 'string' ? label.split(':') : ''
                  return (
                    <li key={value} style={{ marginBottom: index != arr.length - 1 ? 10 : undefined }} onMouseEnter={() => { setGHoverId(value) }} onMouseLeave={() => { setGHoverId(undefined) }}>
                      <span style={{ fontSize: 12, color: '#3574ee', border: '1px solid #dcdcdc', padding: 4, backgroundColor: '#f7f9fc' }}>{title}</span>
                      <Badge offset={[0, -4]} count={<CloseCircleFilled onClick={() => { setGlobalValue(values => values.filter(item => item.value != value)) }} style={{ fontSize: 12, color: 'red', opacity: value == gHoverId ? 1 : 0 }} />}>
                        <span style={{ fontSize: 12, color: '#00000090', border: '1px solid #dcdcdc', padding: 4, borderLeft: 'none' }}>{_value}</span>
                      </Badge>
                    </li>
                  )
                })}
              </Menu>
            )}>
            <DownOutlined style={{ fontSize: 12, color: 'rgba(0,0,0,0.3)' }} />
          </Dropdown>
        )}
        filterOption={() => true}
      >
        {options.map(item => <Select.Option style={{ fontSize: 12 }} key={item.value} value={item.value}>{item.label}</Select.Option>)}
      </Select>
    </div>
  )
}
