import React, { useMemo, useEffect, useImperativeHandle } from 'react'
import { Button, Checkbox, Col, Dropdown, InputNumber, Row, Select } from 'antd'
import { Icon } from '../../../../components/icons'
import { ADVANCED_FILTER_NAME, TagTypeEnum, ConditionFilterData, RangeOptionsEnum } from './types'
import Rule from './rule'
import { Schema } from '../../../../types'
import { isNil, uniqWith } from 'lodash'
import { CRUDProps } from '../../types'
import { uuidv4 } from '../../../../utils/helper'

// 处理数字类型介于的常量
const BETWEEN_VALUE_A = 'number_a', BETWEEN_VALUE_B = 'number_b', SPLIT_CHAR = ';'
// 去除字段名前缀的正则
const REG_EXP = new RegExp(`^(${ADVANCED_FILTER_NAME.FILTER}|${ADVANCED_FILTER_NAME.FILTER_SUB})\\.`)

interface IProps {
  visible: boolean
  advancedFilter: Schema
  advancedQueryFields?: string
  advancedFilterDatas: ConditionFilterData[]
  caseSensitive: boolean
  limitStatus: boolean
  topN: number
  setAdvancedFilterDatas: React.Dispatch<React.SetStateAction<ConditionFilterData[]>>
  setCaseSensitive: React.Dispatch<React.SetStateAction<boolean>>
  setLimitStatus: React.Dispatch<React.SetStateAction<boolean>>
  setTopN: React.Dispatch<React.SetStateAction<number>>
}

export type ConditionQueryRef = { getDefaultAdvancedFilterDatas: () => ConditionFilterData[] }

const ConditionQuery: React.ForwardRefRenderFunction<ConditionQueryRef, IProps & Pick<CRUDProps, 'render' | 'env' | 'classnames'>> = (props, ref) => {

  const { visible, render, classnames: cx, env, advancedFilter, advancedQueryFields, advancedFilterDatas, caseSensitive, limitStatus, topN,
    setAdvancedFilterDatas, setCaseSensitive, setLimitStatus, setTopN } = props

  useEffect(() => {
    setAdvancedFilterDatas(getDefaultAdvancedFilterDatas())
  }, [])

  useImperativeHandle(ref, () => ({ getDefaultAdvancedFilterDatas }))

  const advancedBody: any[] = useMemo(() => {
    const body = advancedFilter.body.find((item: any) => item.name === ADVANCED_FILTER_NAME.FILTER)?.body ?? []
    if (advancedQueryFields) {
      return body.filter((item: any) => advancedQueryFields.split(',').includes(item.name.replace(REG_EXP, '')))
    }
    return body
  }, [advancedFilter, advancedQueryFields])

  // 筛选出body日期项
  const advancedBodyInDate = useMemo(() => {
    const tags = [TagTypeEnum.InputDate, TagTypeEnum.InputDatetime, TagTypeEnum.InputTime, TagTypeEnum.InputMonth, TagTypeEnum.InputQuarter, TagTypeEnum.InputYear]
    return advancedBody.filter(item => item.type && tags.includes(item.type))
  }, [advancedBody])

  // 字段select选项集合
  const fieldOptions = useMemo(() => {
    const uniqArr = uniqWith(advancedBody, (a, b) => a.name === b.name)
    return uniqArr.map(item => ({
      label: (item.groupName ? `${item.groupName} · ` : '') + (item.label || item.placeholder),
      value: item.name as string,
      type: item.type,
      isNumber: item.isNumber || null,
      defaultValue: item.value
    }))
  }, [advancedBody])

  // 日期类型select选项集合
  const dateFieldOptions = useMemo<{ label: string, value: string, type: TagTypeEnum, isNumber: boolean, defaultValue?: any }[]>(() => {
    return [{ label: '无', value: ADVANCED_FILTER_NAME.NONE, type: TagTypeEnum.InputText, isNumber: false }]
    .concat(fieldOptions.filter(option => advancedBodyInDate.some(body => body.name === option.value)))
  }, [fieldOptions])

  // 文本数字类型dropdown选项集合
  const textOrNumberFieldOptions = useMemo(() => {
    const tags = [TagTypeEnum.InputNumber, TagTypeEnum.InputText, TagTypeEnum.InputDate, TagTypeEnum.InputDatetime]
    return fieldOptions.filter(option => (option.type && tags.includes(option.type)) || option.isNumber)
  }, [fieldOptions])

  // 设置默认查项项
  const getDefaultAdvancedFilterDatas = () => {
    const option = dateFieldOptions[1] ?? fieldOptions[0]
    const itemOne: ConditionFilterData = {
      key: uuidv4(),
      field: option.value,
      condition: 1,
      not: false,
      op: Rule.getRangeOption(option.type),
      dateLine: dateFieldOptions.length > 1 ? true : undefined,
      values: option.defaultValue
    }
    const itemTwo: ConditionFilterData = {
      key: uuidv4(),
      field: fieldOptions[0].value,
      condition: 1,
      not: false,
      op: Rule.getRangeOption(fieldOptions[0].type),
      values: fieldOptions[0].defaultValue
    }
    return dateFieldOptions[1] ? [itemOne, itemTwo] : [itemOne]
  }

  const handleAddFilter = () => {
    setAdvancedFilterDatas(datas => {
      const lastField = datas[datas.length - 1].field
      const taretIndex = fieldOptions.findIndex(option => option.value === lastField)
      const nextField = fieldOptions[taretIndex + 1] ?? fieldOptions[taretIndex]
      const item: ConditionFilterData = {
        key: uuidv4(),
        field: nextField.value,
        condition: 1,
        not: false,
        op: Rule.getRangeOption(nextField.type)
      }
      return datas.concat(item)
    })
  }

  const handleMenuClick = (menuKey: string, key: string) => {
    const targetOption = textOrNumberFieldOptions.find(option => option.value === menuKey)
    if (targetOption) {
      setAdvancedFilterDatas(datas => datas.map(data => {
        if (data.key === key) {
          return { ...data, key: uuidv4(), values: `${data.values}[${targetOption.label}]` }
        }
        return data
      }))
    }
  }

  const handleChange = (type: 'condition' | 'field' | 'not' | 'op', key: string, value: any, schema?: Schema) => {
    switch (type) {
      case 'condition':
        setAdvancedFilterDatas(datas => datas.map(data => {
          if (data.key === key) {
            return { ...data, condition: value }
          }
          return data
        }))
        break
      case 'field':
        setAdvancedFilterDatas(datas => datas.map(data => {
          if (data.key == key) {
            // 字段选择无，把条件和值置空
            if (value === ADVANCED_FILTER_NAME.NONE) {
              return { ...data, field: value, op: RangeOptionsEnum.Equal, values: undefined }
            }
            switch (schema?.type) {
              case TagTypeEnum.Switch:
                return { ...data, field: value, op: RangeOptionsEnum.Equal, values: schema.falseValue }
              case TagTypeEnum.File:
                return { ...data, field: value, op: RangeOptionsEnum.IsEmpty, values: undefined }
              case TagTypeEnum.InputDate:
              case TagTypeEnum.InputMonth:
              case TagTypeEnum.InputDatetime:
                return { ...data, field: value, op: RangeOptionsEnum.Between, values: undefined }
              default:
                return { ...data, field: value, op: RangeOptionsEnum.Equal, values: undefined }
            }
          }
          return data
        }))
        break
      case 'not':
        setAdvancedFilterDatas(datas => datas.map(data => {
          if (data.key == key) {
            return { ...data, not: value }
          }
          return data
        }))
        break
      case 'op':
        setAdvancedFilterDatas(datas => datas.map(data => {
          if (data.key == key) {
            // 把选项从介于选成其它时，把值清空
            if (value !== RangeOptionsEnum.Between && data.op === RangeOptionsEnum.Between) {
              return { ...data, op: value, values: undefined }
            }
            return { ...data, op: value }
          }
          return data
        }))
        break
      default:
        break
    }
  }

  const handleValueChange = (value: any, name: string, ...args: any[]) => {
    const advancedQueryKey = args[args.length - 1]
    // console.log(value, name, advancedQueryKey)
    if (typeof advancedQueryKey !== 'string') return

    setAdvancedFilterDatas(datas => datas.map(data => {
      if (advancedQueryKey.includes(BETWEEN_VALUE_A) || advancedQueryKey.includes(BETWEEN_VALUE_B)) {
        const [key, tag] = advancedQueryKey.split(SPLIT_CHAR)
        if (data.key === key) {
          const oldValues = data.values ? `${data.values}` : ','
          const [a, b] = oldValues.split(',')
          let values = ''
          if (tag === BETWEEN_VALUE_A) {
            values = `${value},${b}`
          } else if (tag === BETWEEN_VALUE_B) {
            values = `${a},${value}`
          }
          return { ...data, values }
        }
      } else {
        if (data.key === advancedQueryKey) {
          return { ...data, values: value }
        }
      }
      return data
    }))
  }

  const renderChild = (control: Schema, key: string, otherProps?: any, region: string = '') => {
    const props = {
      formMode: 'horizontal',
      key: `${control.name}-${control.type}-${key}`,
      advancedQueryKey: key,
      onChange: handleValueChange,
      ...otherProps
    };
    return render(`${region ? `${region}/` : ''}${key}`, control, props)
  }

  return visible ? (
    <>
      {advancedFilterDatas.map((item, index) => {
        const bodySchema = item.field === ADVANCED_FILTER_NAME.NONE ? { type: TagTypeEnum.InputDate, name: ADVANCED_FILTER_NAME.NONE } : advancedBody.find(body => body.name === item.field)
        if (isNil(bodySchema)) return null
        //是否时间类型
        const isTimeType = [TagTypeEnum.InputDate, TagTypeEnum.InputTime, TagTypeEnum.InputDatetime,].includes(bodySchema.type)
        const isDisableRange = [TagTypeEnum.TreeSelect, TagTypeEnum.TabsTransferPicker, TagTypeEnum.InputDateRange, TagTypeEnum.InputDatetimeRange, TagTypeEnum.InputMonthRange,
        TagTypeEnum.InputYearRange, TagTypeEnum.InputQuarterRange, TagTypeEnum.InputTimeRange, TagTypeEnum.InputTag, TagTypeEnum.NestedSelect, TagTypeEnum.Switch
        ].includes(bodySchema.type)
        const isDateSelectedNone = item.dateLine && item.field === ADVANCED_FILTER_NAME.NONE

        return (
          <Row className='advanced-filter-row' gutter={24} key={item.key} >
            <Col span={1} style={{ paddingRight: 0 }} >
              {!item.dateLine ? (
                <div
                  className={cx('condition', { 'or': item.condition === (advancedBodyInDate.length ? 1 : 0), 'not': index === (advancedBodyInDate.length ? 1 : 0) })}
                  onClick={() => {
                    if (index === (advancedBodyInDate.length ? 1 : 0)) return
                    handleChange('condition', item.key, item.condition ^ 1)
                  }}>
                  {item.condition === 0 ? '或' : '且'}
                </div>
              ) : <div style={{ width: 20 }} />
              }
            </Col>
            <Col span={5} className='advanced-filter-row-select' style={{ paddingLeft: 0 }}>
              <Select
                value={item.field}
                showSearch
                dropdownClassName={`dropdown-select-style`}
                allowClear={false}
                filterOption={(input: string, option?: { label: string; value: string }) => (option?.label ?? '').includes(input.toLowerCase()) || (option?.value ?? '').toLowerCase().includes(input.toLowerCase())}
                options={item.dateLine ? dateFieldOptions : fieldOptions}
                getPopupContainer={env.getModalContainer}
                onChange={(value) => { handleChange('field', item.key, value, advancedBody.find(body => body.name === value)) }}
                suffixIcon={<Icon symbol icon={'#icon-tooltool_down'} className="icon" />}
              />
            </Col>
            <Col span={1} className='condition-not' style={{ padding: 0 }}>
              <Checkbox
                disabled={isDateSelectedNone}
                checked={item.not}
                onChange={(e) => { handleChange('not', item.key, e.target.checked) }}>
                不
              </Checkbox>
            </Col>
            <Col span={4} className='advanced-filter-row-select' style={{ paddingLeft: 0 }}>
              <Select
                dropdownClassName={`dropdown-select-style`}
                disabled={isDisableRange || isDateSelectedNone}
                value={item.op}
                allowClear={false}
                getPopupContainer={env.getModalContainer}
                options={Rule.getRangeOptions(bodySchema, false)}
                onChange={(val) => { handleChange('op', item.key, val) }}
                suffixIcon={<Icon symbol icon={'#icon-tooltool_down'} className="icon" />}
              />
            </Col>
            {Rule.showInputItem(item.op, bodySchema.type, true) ? <>
              <Dropdown
                menu={{
                  items: textOrNumberFieldOptions.map((val,) => ({ key: val.value, label: val.label, })),
                  onClick: (info) => handleMenuClick(info.key, item.key)
                }}
                trigger={['contextMenu']}
                overlayStyle={{ overflow: 'hidden' }}
                disabled={!(['input-number', 'input-text', 'input-date', 'input-datetime', 'input-time'].includes(bodySchema.type) || bodySchema.isNumber) || item.op == 7}
                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: 'hidden', display: 'flex', flexDirection: 'column'
                  }}>
                    <div style={{ flex: 1, overflow: 'auto' }}>
                      {React.cloneElement(menu as React.ReactElement, { style: { boxShadow: 'none' } })}
                    </div>
                  </div>
                )}
              >
                <Col span={12} style={{ paddingRight: 0, paddingLeft: 0 }}>
                  {item.op === RangeOptionsEnum.DataTag ?
                    renderChild({ ...bodySchema.dataTag, name: item.field, value: item.values }, item.key)
                    : item.op === RangeOptionsEnum.Between && (bodySchema.type === TagTypeEnum.InputNumber || bodySchema.isNumber)
                      ?
                      <div className="double">
                        {renderChild({
                          ...bodySchema,
                          name: bodySchema.name + '-a8',
                          isMultipleValues: false,
                          label: undefined,
                          value: item.values?.toString().split(',')[0]
                        },`${item.key}${SPLIT_CHAR}${BETWEEN_VALUE_A}`)}
                        <span style={{ margin: '0 4px' }}></span>
                        {renderChild({
                          ...bodySchema,
                          name: bodySchema.name + '-b8',
                          isMultipleValues: false,
                          label: undefined,
                          value: item.values?.toString().split(',')[1]
                        },`${item.key}${SPLIT_CHAR}${BETWEEN_VALUE_B}`)}
                      </div>
                      :
                      item.op !== RangeOptionsEnum.IsEmpty && item.op === RangeOptionsEnum.Between && [TagTypeEnum.InputDate, TagTypeEnum.InputMonth, TagTypeEnum.InputDatetime].includes(bodySchema.type) ?
                        renderChild({
                          ...bodySchema,
                          ranges: bodySchema.ranges ?? bodySchema.shortcuts,
                          type: bodySchema.type + "-range",
                          label: undefined,
                          value: item.values
                        }, item.key) :
                        renderChild({
                          ...bodySchema,
                          validations: (() => {
                            if (bodySchema.isNumber) return { "isExprOrNumeric": true }
                            if (isTimeType) return { "isExprOrDate": true }
                            return null
                          })(),
                          value: bodySchema.value?.includes(',') && isTimeType ? bodySchema.value.split(',')[0] : item.values || bodySchema.value,
                          label: undefined,
                          isNumber: bodySchema.isNumber,
                          disabled: isDateSelectedNone
                        }, item.key, { inputFocusShowPicker: false, inputBlurCheckValue: false })
                  }
                </Col>
              </Dropdown>
            </>
              : <Col span={12} />}
            {!item.dateLine && (
              <Col span={1} className='del-icon' >
                <Icon role="delete" icon="#icon-tooltool_minus-o" onClick={() => { setAdvancedFilterDatas(datas => datas.filter(data => data.key !== item.key)) }} />
              </Col>
            )}
          </Row>
        )
      })
      }
      <div className={'Modal-advanced-body-but'} >
        <Button block onClick={handleAddFilter}>新增+</Button>
      </div>
      <Row className={'Modal-advanced-body-caseSensitive'} >
        <Col span={4}>
          <Checkbox className='condition-case-sensitive' checked={caseSensitive} onChange={e => setCaseSensitive(e.target.checked)}>区分大小写</Checkbox>
        </Col>
        <Col span={20} className='condition-topN-box'>
          <Checkbox className='condition-topN' checked={limitStatus} onChange={e => setLimitStatus(e.target.checked)}>仅查前</Checkbox>
          <InputNumber
            size='small'
            min={1}
            precision={0}
            onChange={(value) => setTopN(value ?? 0)}
            style={{ margin: '0 8px', width: '110px', fontSize: 12 }}
            value={topN}
          />
          项
        </Col>
      </Row>
    </>
  ) : null

}

export default React.forwardRef(ConditionQuery)