import React, { useEffect, useRef, useState } from 'react';
import { RendererProps } from '../../factory';
import { Icon } from '../../components/icons';
import Popover from 'antd/lib/popover';
import Select from 'antd/lib/select';
import Input, { InputRef } from 'antd/lib/input/Input';
import Button from 'antd/lib/button';
import Checkbox from 'antd/lib/checkbox/Checkbox';
import Radio from 'antd/lib/radio';
import DatePicker from 'antd/lib/date-picker';
import Dropdown from 'antd/lib/dropdown';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import { ColumnsFilterType, Condition, FilterValue, getOptions, dealInputValue } from '../../components/table/SecondFilter/types';
import { guid } from '../../utils/helper';
import { IColumn } from '../../store/table';
import { ClassNamesFn } from '../../theme';
import TextareaPop from '../../components/common/TextareaPop';
import { TranslateFn } from '../../locale';
import { flatMap } from 'lodash';

/**value1和value2是展示值, value3是value1的实际值 */
type RFilterValue = { key: string, condition?: Condition, value1?: string, value2?: string, relation?: 'and' | 'or', value3?: string }

export interface HeadCellFilterProps extends RendererProps {
  isActive: boolean
  isShow: boolean
  filterType: ColumnsFilterType
  defaultFilters: RFilterValue[]
  columnFileds: { label: string, name: string }[]
  column: IColumn
  onConfirm: (values: RFilterValue[], caseSensitive: boolean) => void
  onReset: () => void
  translate: TranslateFn<any>
}

export class HeadCellFilterDropDown extends React.Component<HeadCellFilterProps, { visible: boolean, map: object }> {

  constructor(props: HeadCellFilterProps) {
    super(props)
    this.state = { visible: false, map: {} }
  }

  componentDidMount() {
    this.getMapValue()
  }

  async getMapValue() {
    const { filterType, column, env } = this.props
    if (filterType == 'select') {
      if (column.map) {
        this.setState({ map: column.map })
      } else {
        const api = column.pristine.source
        const res = await env.fetcher(api, {})
        if (res.ok) {
          const data = res.data
          this.setState({ map: data })
          column.setMapValue?.(data)
        }
      }
    }
  }

  render() {
    const { isActive, isShow, column, classPrefix: ns, classnames: cx, onReset, onConfirm } = this.props;
    const { visible, map } = this.state

    return (
      <Popover
        trigger={'click'}
        visible={visible}
        onVisibleChange={visible => this.setState({ visible })}
        getPopupContainer={e => e.parentNode as any}
        content={(
          <SecondFilter
            {...this.props}
            map={map}
            columnFields={this.props.columnFileds}
            format={column.pristine.valueFormat}
            onReset={() => { onReset(); this.setState({ visible: false }) }}
            onConfirm={((values, caseSensitive) => { onConfirm(values, caseSensitive); this.setState({ visible: false }) })}
            onCancel={() => this.setState({ visible: false })}
          />
        )}
        placement='bottomRight'
        arrowPointAtCenter={true}
      // destroyTooltipOnHide={true}
      >
        <span style={{ visibility: isShow ? 'visible' : 'hidden', zIndex: 7 }} onClick={(e) => e.stopPropagation()} className={cx(`${ns}TableCell-filterBtn`, isActive ? 'is-active' : '')}>
          <Icon icon="column-filter" className="icon" />
        </span>
      </Popover>
    )
  }
}

interface IProps {
  filterType: ColumnsFilterType
  defaultFilters?: RFilterValue[]
  columnFields: { label: string, name: string }[]
  map: object
  format: string
  onConfirm: (values: RFilterValue[], caseSensitive: boolean) => void
  onReset: () => void
  onCancel: () => void
  classnames: ClassNamesFn
  render: any,
  classPrefix: string
  translate: TranslateFn<any>
}

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

  const { filterType, map = {}, format = 'YYYY-MM-DD HH:mm:ss', columnFields, onConfirm, onReset, onCancel, classnames: cx, render, classPrefix, translate } = props

  const [filters, setFilters] = useState<FilterValue[]>(props.defaultFilters ?? [{ key: guid(), condition: Condition.Equal, relation: 'and' }])

  const [caseSensitive, setCaseSensitive] = useState(true)

  const inputRef = useRef<InputRef>(null)

  const options = getOptions(filterType)

  useEffect(() => {
    setFilters(props.defaultFilters ?? [{ key: guid(), condition: Condition.Equal, relation: 'and' }])
  }, [props.defaultFilters])

  const handleOk = () => {
    const rValue = flatMap(filters ?? [], filter => {
      const { condition, value1, value2, relation, key } = filter
      if (condition != undefined) {
        if (condition == Condition.Null || condition == Condition.NotNull) {
          return { key, condition, value1: Array.isArray(value1) ? value1.join(',') : typeof value1 == 'object' ? value1.format(format) : value1, value2: typeof value2 == 'object' ? value2.format(format) : value2, relation }
        } else if (condition == Condition.Between) {
          if (value1 != undefined && value2 != undefined) {
            return { key, condition, value1: Array.isArray(value1) ? value1.join(',') : typeof value1 == 'object' ? value1.format(format) : value1, value2: typeof value2 == 'object' ? value2.format(format) : value2, relation }
          }
        } else {
          if (value1 != undefined && value1 != '') {
            return {
              key,
              condition,
              relation,
              value1: Array.isArray(value1) ? value1.join(',') : typeof value1 == 'object' ? value1.format(format) : value1,
              value2: typeof value2 == 'object' ? value2.format(format) : value2,
              value3: dealInputValue(value1, columnFields)
            }
          }
        }
      }
      return []
    })
    onConfirm(rValue, caseSensitive)
  }

  const handleReset = () => {
    setFilters([{ key: guid(), condition: Condition.Equal }])
    onReset()
  }

  const handleChange = (value: FilterValue) => {
    setFilters(filters => filters.map(filter => value.key === filter.key ? { ...filter, ...value } : filter))
  }

  const handleAdd = () => {
    const filter: FilterValue = { key: guid(), condition: Condition.Equal, relation: 'and' }
    setFilters(filters => filters.concat(filter))
  }

  return (
    <div onContextMenu={e => e.preventDefault()} className={cx('TableCell-filterPopOver')} onClick={e => e.stopPropagation()} style={{ padding: '12px 16px', maxHeight: '30rem', overflowY: 'auto' }}>
      {filters.map((filter, index, arr) => {
        const { key, condition, value1, value2, relation } = filter
        const isNull = condition == Condition.Null || condition == Condition.NotNull
        const isBetween = condition == Condition.Between
        return (
          <div key={key} >
            <Select className='filter-option' placeholder='请选择条件' value={condition} onChange={value => handleChange({ key: key, condition: value })} >
              {options.map(option => <Select.Option key={option.value} value={option.value}>{option.label}</Select.Option>)}
            </Select>
            {filterType == 'select' ?
              <Select
                className='filter-option'
                placeholder='请选择'
                value={typeof value1 == 'string' ? value1.split(',').filter(v => v != '') : value1}
                mode='multiple'
                maxTagCount='responsive'
                onChange={value => handleChange({ key, value1: value })}
                style={{ visibility: isNull ? 'hidden' : 'visible', height: isNull ? 0 : undefined, marginTop: isNull ? 0 : undefined }}
              >
                {Object.keys(map).map(key => (
                  <Select.Option key={key} value={key}>{render('tpl', { type: 'tpl', tpl: map[key] })}</Select.Option>
                ))}
              </Select>
              :
              <Dropdown
                trigger={['contextMenu']}
                overlayStyle={{ display: isBetween ? 'none' : undefined }}
                menu={{
                  items: columnFields.map(item => (
                    {
                      ...item,
                      key: item.name,
                      onClick: () => { handleChange({ key, value1: `${value1 ?? ''}[${item.label}]` }) }
                    }
                  ))
                }}
                dropdownRender={menu => (
                  <div style={{
                    backgroundColor: '#fff',
                    boxShadow: 'rgba(0, 0, 0, 0.08) 0px 6px 16px 0px, rgba(0, 0, 0, 0.12) 0px 3px 6px -4px, rgba(0, 0, 0, 0.05) 0px 9px 28px 8px',
                    maxHeight: 300, overflow: 'auto',
                  }}>
                    {menu}
                  </div>
                )}
              >
                <Input
                  ref={inputRef}
                  autoFocus={true}
                  className='filter-option'
                  type={'text'}
                  addonAfter={filterType == 'date' ?
                    // @ts-ignore
                    <DatePicker
                      className='filter-option-date'
                      locale={locale}
                      format={format}
                      showTime={true}
                      dropdownAlign={{ offset: [-143, 2] }}
                      allowClear={false}
                      onChange={date => date && handleChange({ key, value1: date })}
                      style={{ height: 30 }}
                    />
                    :
                    <TextareaPop
                      visible={false}
                      values={value1 as string | undefined}
                      classPrefix={classPrefix}
                      classnames={cx}
                      translate={translate}
                      onReset={() => handleChange({ key, value1: undefined })}
                      handleText={(val: string) => handleChange({ key, value1: val })}
                      icon='tablet'
                      placement='right'
                    />}
                  placeholder={'请输入'}
                  style={{ visibility: isNull ? 'hidden' : 'visible', height: isNull ? 0 : undefined, marginTop: isNull ? 0 : undefined }}
                  value={typeof value1 == 'object' ? Array.isArray(value1) ? value1.join(',') : value1.format(format) : value1}
                  onDoubleClick={() => inputRef.current?.select()}
                  onPressEnter={() => handleOk()}
                  onChange={e => handleChange({ key, value1: e.target.value })}
                  onPaste={e => {
                    e.preventDefault()
                    const input = e.target as HTMLInputElement
                    const start = input.selectionStart ?? 0
                    const end = input.selectionEnd ?? 0
                    const copy = e.clipboardData.getData('text/plain').trim().replaceAll('\r', '').replaceAll('\n', ',')
                    const prefix = input.value.slice(0, start)
                    const suffix = input.value.slice(end - start > 0 ? end : start)
                    const value = prefix + copy + suffix
                    handleChange({ key, value1: value })
                  }}
                />
              </Dropdown>
            }
            <Input
              className='filter-option'
              type={'text'}
              placeholder={'请输入'}
              style={{ visibility: isBetween ? 'visible' : 'hidden', height: isBetween ? undefined : 0, marginTop: isBetween ? undefined : 0 }}
              value={typeof value2 == 'object' ? Array.isArray(value2) ? value2.join(',') : value2.format(format) : value2}
              addonAfter={filterType == 'date' && (
                //@ts-ignore
                <DatePicker
                  className='filter-option-date'
                  locale={locale}
                  format={format}
                  showTime={true}
                  dropdownAlign={{ offset: [-143, 2] }}
                  allowClear={false}
                  onChange={date => date && handleChange({ key, value2: date })}
                  style={{ height: 30 }}
                />
              )}
              onPressEnter={() => handleOk()}
              onChange={e => handleChange({ key, value2: e.target.value })}
            />
            {index != arr.length - 1 && (
              <Radio.Group style={{ marginTop: 10 }} size='small' value={relation} onChange={e => handleChange({ key, relation: e.target.value })}>
                <Radio value='and'>且</Radio>
                <Radio value='or'>或</Radio>
              </Radio.Group>
            )}
          </div>
        )
      })
      }
      <div style={{ display: 'flex', marginTop: 10, justifyContent: 'space-between' }}>
        {filterType == 'text' && <Checkbox style={{ fontSize: 12 }} checked={caseSensitive} onChange={e => setCaseSensitive(e.target.checked)}>区分大小写</Checkbox>}
        <Button onClick={() => handleAdd()} size='small' type='link' style={{ fontSize: 12 }}>{translate('Condition.add_cond')}</Button>
      </div>
      <div className='filter-footer'>
        <Button onClick={() => handleReset()} size='small' type='link' style={{ fontSize: 12 }}>{translate('clear')}</Button>
        <div className='filter-footer-btn'>
          <Button onClick={() => onCancel()} style={{ borderRadius: 4, fontSize: 12 }} size='small' >{translate('cancel')}</Button>
          <Button onClick={() => handleOk()} style={{ borderRadius: 4, marginLeft: 6, fontSize: 12 }} size='small' type='primary'>{translate('Flow.determine')}</Button>
        </div>
      </div>
    </div>
  )

}
