import React from "react"
import { Modal, Button, Spin, Form, Input, Select, Space, InputNumber, Row, Col } from "antd"

import { dispatch } from '../../../../model'
import { IsArr } from "../../../../util"

const FC = (props) => {
  const { visible, type, item, onCancel } = props
  const [loading, setLoading] = React.useState(false)
  const [waiting, setWaiting] = React.useState(false)
  const [data, setData] = React.useState()

  const basicRef = React.useRef()

  React.useEffect(() => {
    if (item?.id) {
      getDetail()
    }
  }, [item])

  const title = React.useMemo(() => {
    if (type === 'add') return '新增检查规则'
    if (type === 'edit') return '修改检查规则'
    if (type === 'detail') return '检查规则详情'

    return ''
  }, [type])

  const getDetail = () => {
    setLoading(true)
    dispatch({
      type: 'datamodel.getRuleTemplateDetail',
      payload: {
        ruleTemplateId: item?.id
      },
      callback: data => {
        setLoading(false)
        setData(data)
      },
      error: () => {
        setLoading(false)
      }
    })
  }

  const close = (refresh = false) => {
    setLoading(false)
    setWaiting(false)
    setData()
    onCancel?.(refresh)
  }

  const save = async() => {
    try {
      const rows = await basicRef.current?.validate()
      setWaiting(true)
      if (type === 'add') {
        dispatch({
          type: 'datamodel.addRuleTemplate',
          payload: {
            data: rows
          },
          callback: data => {
            close(true)
          },
          error: () => {
            setWaiting(false)
          }
        })
      } else {
        dispatch({
          type: 'datamodel.updateRuleTemplate',
          payload: {
            data: {...item, preCheckProperty: null, ...rows}
          },
          callback: data => {
            close(true)
          },
          error: () => {
            setWaiting(false)
          }
        })
      }
       
    } catch (e) {
      
    }
  }

  const footer = React.useMemo(() => {
    return [
      <Button key='cancel'
        onClick={() => close()}
      >取消</Button>,
      <Button key='save' type='primary'
        onClick={() => save()}
      >确定</Button>
    ]
  }, [close, save])

  return (
    <Modal
      visible={visible}
      footer={type!=='detail'?footer:null}
      width='80%'
      bodyStyle={{ padding: '15px', overflowX: 'auto', maxHeight: '80vh' }}
      title={title}
      centered destroyOnClose
      onCancel={() => { close() }}
    >
      <Spin spinning={waiting||loading}>
        <Basic ref={basicRef} type={type} item={data} />
      </Spin>
    </Modal>
  )
}

export default FC

export const Basic = React.forwardRef(function ({ type, item }, ref) {
  const [loadingCheckTypes, setLoadingCheckTypes] = React.useState(false)
  const [checkTypes, setCheckTypes] = React.useState()
  const [checkTypeValue, setCheckTypeValue] = React.useState()
  const [preCatalog, setPreCatalog] = React.useState()

  const [form] = Form.useForm()

  React.useImperativeHandle(ref, () => ({
    validate: async () => {
      return await form?.validateFields()
    },
  }), [form])

  React.useEffect(() => {
    getCheckTypes()
  }, [])

  React.useEffect(() => {
    if (item) {
      form?.setFieldsValue(item)
      setCheckTypeValue(item.checkType)
      setPreCatalog(item.preCheckProperty?.propertyCatalog)
    }
  }, [item])

  const [checkPropertyDescription, preCheckPropertyDescription] = React.useMemo(() => {
    if (item) {
      let newCheckPropertyDescription = `${item?.checkProperty?.propertyCnName??''} ${item?.checkProperty?.expressionTypeCnName??''} ${item?.checkProperty?.verifyExpression?.cnName??''}`
      if (IsArr(item?.checkProperty?.verifyExpression?.value)) {
        newCheckPropertyDescription = `${newCheckPropertyDescription} ${item?.checkProperty?.verifyExpression?.value.join(';')}`
      } else {
        newCheckPropertyDescription = `${newCheckPropertyDescription} ${item?.checkProperty?.verifyExpression?.value}`
      }

      let newPreCheckPropertyDescription = `${item?.preCheckProperty?.propertyCnName??''} ${item?.preCheckProperty?.expressionTypeCnName??''} ${item?.preCheckProperty?.verifyExpression?.cnName??''}`
      if (IsArr(item?.preCheckProperty?.verifyExpression?.value)) {
        newPreCheckPropertyDescription = `${newPreCheckPropertyDescription} ${item?.preCheckProperty?.verifyExpression?.value.join(';')}`
      } else {
        newPreCheckPropertyDescription = `${newPreCheckPropertyDescription} ${item?.preCheckProperty?.verifyExpression?.value}`
      }

      return [newCheckPropertyDescription, newPreCheckPropertyDescription]
    }

    return ['', '']
  }, [item])

  const marginBottom = React.useMemo(() => {
    return type === 'detail' ? 5 : 15
  }, [type])

  const getCheckTypes = () => {
    setLoadingCheckTypes(true)
    dispatch({
      type: 'datamodel.getRuleTemplateCheckTypes',
      callback: (data) => {
        setLoadingCheckTypes(false)
        setCheckTypes(data)        
      },
      error: () => {
        setLoadingCheckTypes(false)
      }
    })
  }

  const onValuesChange = (changedValues, allValues) => {
    if (changedValues.hasOwnProperty('checkType')) {
      setCheckTypeValue(changedValues.checkType)
    } else if (changedValues.hasOwnProperty('preCheckProperty')) {
      setPreCatalog(changedValues?.preCheckProperty?.propertyCatalog)
    }
  }

  const validatorCheckProperty = (_, value) => {
    if (!value?.propertyEnName) {
      return Promise.reject(new Error('请选择检查对象!'));
    }
    if (!value?.expressionTypeEnName) {
      return Promise.reject(new Error('请选择检查属性!'));
    }
    if (!value?.verifyExpression?.enName) {
      return Promise.reject(new Error('请选择表达式!'));
    }

    if ((value?.verifyExpression?.valueType==='string' || value?.verifyExpression?.valueType === 'int') && !value?.verifyExpression?.value) {
      return Promise.reject(new Error('请输入表达式的值!'));
    }

    if (value?.verifyExpression?.valueType === 'List<String>' && (value?.verifyExpression?.value??[]).length === 0) {
      return Promise.reject(new Error('请输入表达式的值!'));
    }

    return Promise.resolve();
  };
  
  return (
    <Form
      form={form}
      labelCol={{ span: 3 }}
      wrapperCol={{ span: 21 }}
      autoComplete="off"
      onValuesChange={onValuesChange}
    >
      {
        type !== 'add' && <Form.Item label='规则编号' style={{ marginBottom }}>
          <span>{item?.number}</span>
        </Form.Item>
      }
      <Form.Item name='name' label='规则中文名称'
        style={{ marginBottom }}
        rules={[{ required: true, message: '请输入规则中文名称!' }]}
      >
        {
          type === 'detail' ? <span>{item?.name}</span> : <Input placeholder='请输入规则中文名称' allowClear />
        }
      </Form.Item>
      <Form.Item name='remark' label='规则描述'
        style={{ marginBottom }}
      >
        {
          type === 'detail' ? <span>{item?.remark}</span> : <Input placeholder='请输入规则描述' allowClear />
        }
      </Form.Item>
      <Form.Item name='alertContent' label='规则提示'
        style={{ marginBottom }}
        rules={[{ required: true, message: '请输入规则提示!' }]}
      >
        {
          type === 'detail' ? <span>{item?.alertContent}</span> : <Input placeholder='请输入规则提示' allowClear />
        }
      </Form.Item>
      <Form.Item name='checkType' label='检查类型'
        style={{ marginBottom }}
        rules={[{ required: true, message: '请选择检查类型!' }]}
      >
        {
          type === 'detail' ? <span>{item?.checkTypeName}</span> : <Select allowClear loading={loadingCheckTypes}
            placeholder='请选择检查类型'
          >
            { (checkTypes??[]).map((item, index) => (
              <Select.Option key={item.type} value={item.type}>{item.name}</Select.Option>
            )) }
          </Select>
        }
      </Form.Item>
      {
        checkTypeValue === 'single' && <Form.Item name='checkProperty' label='检查规则'
          style={{ marginBottom }}
          rules={[
            {
              required: true,
              validator: validatorCheckProperty,
            },
          ]}
        >
          {
            type === 'detail' ? <span>{checkPropertyDescription}</span> : <CheckItem />
          }
        </Form.Item>
      }
      {
        checkTypeValue === 'preCheck' && <Form.Item label='检查规则'>
          <Form.Item name='preCheckProperty' label='满足条件'
            style={{ marginBottom }}
            rules={[
              {
                required: true,
                validator: validatorCheckProperty,
              },
            ]}
          >
            {
              type === 'detail' ? <span>{preCheckPropertyDescription}</span> : <CheckItem />
            }
          </Form.Item>
          <Form.Item name='checkProperty' label='检查内容'
            style={{ marginBottom }}
            rules={[
              {
                required: true,
                validator: validatorCheckProperty,
              },
            ]}
          >
            {
              type === 'detail' ? <span>{checkPropertyDescription}</span> : <CheckItem preCatalog={preCatalog} />
            }
          </Form.Item>
        </Form.Item>
      }
     
    </Form>
  )
})

const CheckItem = ({ value, onChange, preCatalog }) => {
  const [loadingCheckPropertyTypes, setLoadingCheckPrpertyTypes] = React.useState(false)
  const [checkPropertyTypes, setCheckPropertyTypes] = React.useState()
  const [loadingExpressionTypes, setLoadingExpressionTypes] = React.useState(false)
  const [expressionTypes, setExpressionTypes] = React.useState()
  const [loadingExpressionMapping, setLoadingExpressionMapping] = React.useState(false)
  const [expressionMapping, setExpressionMapping] = React.useState()

  const [currentCheckPropertyType, setCurrentCheckPropertyType] = React.useState()
  const [currentExpressionType, setCurrentExpressionType] = React.useState()
  const [currentExpression, setCurrentExpression] = React.useState()
  const [currentExpressionValue, setCurrentExpressionValue] = React.useState()

  const mountRef = React.useRef(true)

  React.useEffect(() => {
    getCheckPropertyTypes()
    getExpressionTypes()
    getExpressions()
  }, [])

  React.useEffect(() => {
    if (mountRef.current && value) {
      setCurrentCheckPropertyType({
        propertyCatalog: value?.propertyCatalog,
        propertyCnName: value?.propertyCnName,
        propertyEnName: value?.propertyEnName,
      })
      setCurrentExpressionType({
        expressionTypeCnName: value?.expressionTypeCnName,
        expressionTypeEnName: value?.expressionTypeEnName,
      })
      setCurrentExpression(value.verifyExpression)
      if (IsArr(value.verifyExpression?.value)) {
        setCurrentExpressionValue(value.verifyExpression?.value.join(';'))
      } else {
        setCurrentExpressionValue(value.verifyExpression?.value)
      }
    }

    mountRef.current = false
  }, [])

  React.useEffect(() => {
    onChange?.({...currentCheckPropertyType||{}, ...currentExpressionType||{}, verifyExpression: currentExpression})
  }, [currentCheckPropertyType, currentExpressionType, currentExpression])

  const visibleExpressions = React.useMemo(() => {
    if (currentExpressionType?.expressionTypeEnName) {
      return expressionMapping?.[currentExpressionType?.expressionTypeEnName]
    }

    return []
  }, [expressionMapping, currentExpressionType])

  const _checkPropertyTypes = React.useMemo(() => {
    if (preCatalog) {
      return (checkPropertyTypes??[]).filter(item => item.propertyCatalog === preCatalog)
    }

    return checkPropertyTypes
  }, [checkPropertyTypes, preCatalog])

  React.useEffect(() => {
    if (preCatalog) {
      if (currentCheckPropertyType?.propertyCatalog && currentCheckPropertyType?.propertyCatalog !== preCatalog) {
        setCurrentCheckPropertyType()
      }
    }
  }, [preCatalog, currentCheckPropertyType])

  const getCheckPropertyTypes = () => {
    setLoadingCheckPrpertyTypes(true)
    dispatch({
      type: 'datamodel.getRuleTemplateAllCheckPropertyTypes',
      callback: (data) => {
        setLoadingCheckPrpertyTypes(false)
        setCheckPropertyTypes(data)        
      },
      error: () => {
        setLoadingCheckPrpertyTypes(false)
      }
    })
  }

  const getExpressionTypes = () => {
    setLoadingExpressionTypes(true)
    dispatch({
      type: 'datamodel.getRuleTemplateAllVerifyExpressionTypes',
      callback: (data) => {
        setLoadingExpressionTypes(false)
        setExpressionTypes(data)
      },
      error: () => {
        setLoadingExpressionTypes(false)
      }
    })
  }

  const getExpressions = () => {
    setLoadingExpressionMapping(true)
    dispatch({
      type: 'datamodel.getRuleTemplateAllVertifyExpressions',
      callback: (data) => {
        setLoadingExpressionMapping(false)
        setExpressionMapping(data)
      },
      error: () => {
        setLoadingExpressionMapping(false)
      }
    })
  }

  return (
    <Row gutter={10}>
      <Col span={6}>
        <Select allowClear loading={loadingCheckPropertyTypes}
          value={currentCheckPropertyType?.propertyEnName}
          onChange={(val) => {
            if (val) {
              const index = (checkPropertyTypes??[]).findIndex(item => item.propertyEnName === val)
              if (index !== -1) {
                setCurrentCheckPropertyType(checkPropertyTypes[index])
              }
            } else {
              setCurrentCheckPropertyType()
            }
          }}
          placeholder='请选择检查对象'
        >
          { (_checkPropertyTypes??[]).map((item, index) => (
            <Select.Option key={item.propertyEnName} value={item.propertyEnName}>{item.propertyCnName}</Select.Option>
          )) }
        </Select>
      </Col>
      <Col span={6}>
        <Select allowClear loading={loadingExpressionTypes}
          value={currentExpressionType?.expressionTypeEnName}
          onChange={(val) => {
            if (val) {
              const index = (expressionTypes??[]).findIndex(item => item.expressionTypeEnName === val)
              if (index !== -1) {
                setCurrentExpressionType(expressionTypes[index])
              }
            } else {
              setCurrentExpressionType()
            }

            setCurrentExpression()
            setCurrentExpressionValue()
          }}
          placeholder='请选择检查属性'
        >
          { (expressionTypes??[]).map((item, index) => (
            <Select.Option key={item.expressionTypeEnName} value={item.expressionTypeEnName}>{item.expressionTypeCnName}</Select.Option>
          )) }
        </Select>
      </Col>
      <Col span={6}>
        <Select allowClear loading={loadingExpressionMapping}
          value={currentExpression?.enName}
          onChange={(val) => {
            if (val) {
              const index = (visibleExpressions??[]).findIndex(item => item.enName === val)
              if (index !== -1) {
                setCurrentExpression(visibleExpressions[index])
              }
            } else {
              setCurrentExpression()
            }

            setCurrentExpressionValue()
          }}
          placeholder='请选择表达式'
        >
          { (visibleExpressions??[]).map((item, index) => (
            <Select.Option key={item.enName} value={item.enName}>{item.cnName}</Select.Option>
          )) }
        </Select>
      </Col>
      <Col span={6}>
        { (currentExpression?.valueType === 'string') && <Input value={currentExpressionValue} 
          onChange={(e) => {
            setCurrentExpressionValue(e.target.value)
            setCurrentExpression({
              ...currentExpression, value: e.target.value
            })
          }}/> }
        { (currentExpression?.valueType === 'int') && <InputNumber min={1} value={currentExpressionValue} 
          onChange={(val) => {
            setCurrentExpressionValue(val)
            setCurrentExpression({
              ...currentExpression, value: val
            })
          }}/> }
        { (currentExpression?.valueType === 'List<String>') && <Input placeholder='枚举值用;隔开 如高;中;低' value={currentExpressionValue} onChange={(e) => {
          setCurrentExpressionValue(e.target.value)
          setCurrentExpression({
            ...currentExpression, value: e.target.value?e.target.value.split(';'):[]
          })
        }} />  }
      </Col>
    </Row>
  )
}