import React, { useState, useEffect, useMemo, useRef } from 'react';
import { Form, Input, Row, Col, Select, AutoComplete, Button, Divider, Tooltip, Checkbox, Space, Typography } from 'antd';
import { DownOutlined, UpOutlined, ExclamationCircleFilled, WarningFilled, MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Subject } from 'rxjs';
import classnames from 'classnames';

import { highlightSearchContentByTerms, generateUUID, IsArr } from '../../../../util';
import { dispatch, dispatchLatest } from '../../../../model'; 
import Rule from '../../ModelConfig/Component/rule-readonly';
import DebounceInput from './DebounceInput';
import HivePartitionAddKey from './hive-partition-add-key';
import { Detail as KeysDetail } from './hive-partition-add-key';

import './ImportActionHeader.less';

const { TextArea } = Input;
const { Option } = Select;

const InputDebounce = DebounceInput(300)(Input);

const loadOptions = ['append', 'refresh', 'insert', 'update', 'full', 'chain', 'delete', '手工导入'];
const updateOptions = [
  '每个交易日早间交易前加载上一交易日数据,历史资料入历史表',
  '每个交易日早间交易前清空该表,交易期间实时加载,下午收市后入历史表',
  '每个交易日7:30加载',
  '每个交易日8:30加载',
  '每个交易日15:00加载',
  '每个交易日18:00加载',
  '每个交易日19:00加载',
  '每个交易日19:30加载',
  '每个交易日20:00加载',
  '每个交易日22:00加载',
  '每个交易日23:00加载',
  '每个交易日20:00加载T-2的数据',
  '每日中午12:00加载T-3日数据',
  '实时更新',
  '收盘后加载',
  '收市后加载',
  '下午收市后加载',
  '下午收市后入历史表',
  '下午收市后入实时和历史表',
  '晚间结算后加载',
  '实时从mysql同步',
  '手工维护',
  '用户提交',
  '作业提交',
  '脚本加载',
];
const dataTypeRemark = '描述ETL框架中目标表的数据类型';
const bindingLoadRemark = '描述ETL框架绑定加载列表，如chain、daily、current等';

const NameInput = ({ value, prefixName, onChange }) => {
  const customName = useMemo(() => {
    let _customName = (value??'')
    if (prefixName) {
      _customName = (value??'').slice(prefixName.length);
    }
    return _customName
  }, [value, prefixName])

  return (
    <Input className='prefix-input' value={customName} onChange={(e) => {
      onChange?.(`${prefixName??''}${e.target.value}`)
    }}
      addonBefore={prefixName&&<Tooltip title={`简称:${prefixName}`}>
        <Typography.Text ellipsis={true} style={{ maxWidth: 150 }}>{prefixName}</Typography.Text>
      </Tooltip>} 
    />
  )
}

const ImportActionHeader = (props) => {
  const { editable, form, modelerData, constraints, templates, onConstraintChange, onTemplateChange, validateReports, onChange, terms, supportedPartitionTypes, catalogId } = props;

  const [ options, setOptions ] = useState([]);

  const [ autoTranslate, setAutoTranslate ] = useState(false);
  const [loadingDbTypes, setLoadingDbTypes] = useState(false);
  const [dbTypes, setDbTypes] = useState();
  const [ dataTypeList, setDataTypeList ] = useState(null);
  const [loadingHiveStoredTypes, setLoadingHiveStoredTypes] = useState(false);
  const [hiveStoredTypes, setHiveStoredTypes] = useState();
  const [ bindingLoadRangeList, setBindingLoadRangeList ] = useState(null);
  const [loadingRangeList, setLoadingRangeList] = useState(false);
  const [rangeList, setRangeList] = useState();
  const [isCollapse, setCollapse] = useState(true)
  const [ruleParams, setRuleParams] = useState({
    visible: false
  })

  useEffect(() => {
    getDataTypeList();
    getDbTypes();
    getHiveStoredTypes();
  }, [])

  useEffect(() => {
    if (catalogId) {
      getRangeList();
    }
  }, [catalogId])

  useEffect(() => {
    if (modelerData?.dataType) {
      getBindingLoadRangeList(modelerData?.dataType);
    } else {
      setBindingLoadRangeList([]);
    }
  }, [modelerData?.dataType])

  useEffect(() => {
    setAutoTranslate((modelerData.name||'')==='');
    if (modelerData) {
      form?.setFieldsValue(modelerData);
    }
    
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [modelerData])

  const _pratitionTypes = React.useMemo(() => {
    return (supportedPartitionTypes||[]).filter(item => (item.supportedDBTypes??[]).indexOf(modelerData?.dbType)!==-1)
  }, [supportedPartitionTypes, modelerData?.dbType])

  //分布键
  const distributionDescription = useMemo(() => {
    if (modelerData && modelerData.distributionKey) {
      return (modelerData.distributionKey.keys??[]).map(item => item.name).toString()
    }
    return '';
  }, [modelerData])

  //分桶字段
  const distributionBucketDescription = useMemo(() => {
    if (modelerData && modelerData.distributionKey && modelerData.distributionKey.bucketCount) {
      const keyNamesString = (modelerData.distributionKey.keys??[]).map(item => item.name).toString()
      return `${keyNamesString} 分桶数${modelerData.distributionKey.bucketCount}`
    }

    return '';
  }, [modelerData])

  //主键
  const primaryDescription = useMemo(() => {
    let newPrimaryDescription = ''
    if (modelerData?.easyDataModelerPrimaryKey) {
      (modelerData?.easyDataModelerPrimaryKey||[]).forEach((item, index) => {
        if (index > 0) {
          newPrimaryDescription += ',';
        }

        newPrimaryDescription += item.name||'';
      })
    }
    return newPrimaryDescription;
    //eslint-disable-next-line react-hooks/exhaustive-deps    
  }, [editable, modelerData])

  //分区
  const partitionsDescription = useMemo(() => {
    let newPartitionsDescription = ''
    if (modelerData?.partition?.keys) {

      (modelerData?.partition?.keys||[]).forEach((item, index) => {
        if (index > 0) {
          newPartitionsDescription += ',';
        }

        newPartitionsDescription += item.name||'';
      })
    }
    if (modelerData?.partition?.partitionType?.cnName) {
      newPartitionsDescription += '/' + modelerData?.partition?.partitionType?.cnName||'';
    }
    return newPartitionsDescription;
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [editable, modelerData])

  //类主键
  const semiPrimaryDescription = useMemo(() => {
    let newSemiPrimaryDescription = ''
    if (modelerData?.easyDataModelerSemiPrimaryKey) {
      (modelerData?.easyDataModelerSemiPrimaryKey||[]).forEach((item, index) => {
        if (index > 0) {
          newSemiPrimaryDescription += ',';
        }

        newSemiPrimaryDescription += item.name||'';
      })
    }
    return newSemiPrimaryDescription;
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [editable, modelerData])

  const hiveTableConfigPropertiesDescription = useMemo(() => {
    let tmp = []
    for (const item of modelerData?.hiveTableConfigProperties??[]) {
      if (item && item.key && item.value) {
        tmp.push(`${item.key}:${item.value}`)
      }
    }

    return tmp.toString()
  }, [modelerData])

  const marginBottom = useMemo(() => {
    return  editable ? 15 : 10
  }, [editable])

  const formItemLayout = {
    labelCol: {
      xs: { span: 24 },
      sm: { span: 6 },
    },
    wrapperCol: {
      xs: { span: 24 },
      sm: { span: 18 },
    },
  };

  const getDataTypeList = () => {
    dispatch({
      type: 'datamodel.dataTypeList',
      callback: data => {
        setDataTypeList(data);
      }
    })
  }

  const getDbTypes = () => {
    setLoadingDbTypes(true)
    dispatch({
      type: 'datamodel.getDbTypes',
      callback: data => {
        setLoadingDbTypes(false)
        setDbTypes(data)
      },
      error: () => {
        setLoadingDbTypes(false)
      }
    })
  }

  const getHiveStoredTypes = () => {
    setLoadingHiveStoredTypes(true)
    dispatch({
      type: 'datamodel.getHiveStoredTypes',
      callback: data => {
        setLoadingHiveStoredTypes(false)
        setHiveStoredTypes(data)
      },
      error: () => {
        setLoadingHiveStoredTypes(false)
      }
    })
  }

  const getBindingLoadRangeList = (dataTypeName) => {
    dispatch({
      type: 'datamodel.bindingLoadRangeList',
      payload: {
        dataTypeName
      },
      callback: data => {
        setBindingLoadRangeList(data);
      }
    })
  }

  const getRangeList = () => {
    setLoadingRangeList(true)
    dispatch({
      type: 'datamodel.getRangeList',
      payload: {
        easyDataModelCatalogId: catalogId,
      },
      callback: data => {
        setLoadingRangeList(false)
        setRangeList(data)
      },
      error: () => {
        setLoadingRangeList(false)
      }
    })
  }

  const onSearch = (searchText) => {

    const _searchText = searchText.replace(/ /g,'');
    if (_searchText !== '') {
      dispatchLatest({
        type: 'datamodel.autocomplete',
        payload: {
          params: {
            word: _searchText,
            isEasyDataModelerDataModelAttribute: false,
          }
        },
        callback: data => {
          const _options = [];
          (data||[]).forEach(item => {
            _options.push({ value: item });
          })

          setOptions(_options);
        }
      })
    } else {
      dispatchLatest({
        type: 'datamodel.recommandEnglishWords',
        payload: {
          params: {
            chineseWord: modelerData.cnName,
          }
        },
        callback: data => {
          const _options = [];
          (data||[]).forEach(item => {
            _options.push({ value: item });
          })

          setOptions(_options);
        }
      })
    }
  }

  const genericTechnicalInfoComponent = () => {
    return (
      <>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="分布键"
            name="distributionKey"
            style={{ marginBottom }}
          >
            {
              editable ? <DistributionItem modelerData={modelerData} /> : <span className='word-wrap'>{highlightSearchContentByTerms(distributionDescription, terms)}</span>
            }
          </Form.Item>
        </Col>
        {
          (_pratitionTypes??[]).length>0 && <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label="分区键"
              name="partition"
              style={{ marginBottom }}
            >
              {
                editable ? <PartitionSelect modelerData={modelerData} partitionTypes={_pratitionTypes} /> : <span className='word-wrap'>{highlightSearchContentByTerms(partitionsDescription, terms)}</span>
              }
            </Form.Item>
          </Col>
        }
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="类主键"
            name="easyDataModelerSemiPrimaryKey"
            style={{ marginBottom }}
          >
            {
              editable ? <AttributesSelect modelerData={modelerData} mode='tags' /> : <span className='word-wrap'>{highlightSearchContentByTerms(semiPrimaryDescription, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="数据情况"
            name="dataCircumstances"
            style={{ marginBottom }}
          >
            {
              editable ? <Input placeholder='描述数据表中数据的更新频率、每日增量情况、数据量级和历史数据' /> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.dataCircumstances, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="更新时间"
            name="dataUpdatingTiming"
            style={{ marginBottom }}
          >
            {
              editable ? <UpdateSelect placeholder='描述数据表的更新时间点'/> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.dataUpdatingTiming, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="数据类型"
            name="dataType"
            tooltip={dataTypeRemark}
            style={{ marginBottom }}
          >
            {
              editable ? <Select allowClear placeholder='请选择数据类型'>
              {
                dataTypeList?.map((item, index) => <Option key={index} value={item}>
                  {item}
                </Option>)
              }
              </Select> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.dataType, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="绑定加载范围"
            name="bindingLoadRange"
            tooltip={bindingLoadRemark}
            style={{ marginBottom }}
          >
            {
              editable ? <Select allowClear placeholder='请选择绑定加载范围'>
              {
                bindingLoadRangeList?.map((item, index) => <Option key={index} value={item}>
                  {item}
                </Option>)
              }
              </Select> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.bindingLoadRang, terms)}</span>
            }
          </Form.Item>
        </Col>
      </>
    )
  }

  const hiveTechnicalInfoComponent = () => {
    return (
      <>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="数据表类型"
            name="externalTable"
            style={{ marginBottom }}
          >
            {
              (editable&&!modelerData?.deployed) ? <Select allowClear>
              <Select.Option value={false}>内部表</Select.Option>
              <Select.Option value={true}>外部表</Select.Option>
            </Select> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.externalTable?'外部表':'内部表', terms)}</span>
            }
          </Form.Item>
        </Col>
        {
          (_pratitionTypes??[]).length>0 && <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label="分区键"
              name="partition"
              style={{ marginBottom }}
            >
              {
                (editable&&!modelerData?.deployed) ? <HivePartitionSelect modelerData={modelerData} partitionTypes={_pratitionTypes} /> : <Tooltip       
                overlayClassName='tooltip-common'
                title={<KeysDetail value={modelerData?.partition?.keys} />}>
                  <span className='word-wrap'>{highlightSearchContentByTerms(partitionsDescription, terms)}</span>
                </Tooltip>
              }
            </Form.Item>
          </Col>
        }
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="分桶字段"
            name="distributionKey"
            style={{ marginBottom }}
            rules={[
              {
                validator: (_, value) => {
                  if ((value?.keys??[]).length >0) {
                    if (value?.bucketCount === 0) {
                      return Promise.reject(new Error('分桶数不能为0!'));  
                    } else if (!value?.bucketCount) {
                      return Promise.reject(new Error('请输入分桶数!'));
                    }
                  }
                  if (value?.bucketCount && (value?.keys??[]).length===0) {
                    return Promise.reject(new Error('请选择字段名称!'));
                  }
                  return Promise.resolve();
                }
              },
            ]}
          >
            {
              (editable&&!modelerData?.deployed) ? <DistributionBucketItem modelerData={modelerData} /> : <span className='word-wrap'>{highlightSearchContentByTerms(distributionBucketDescription, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="生命周期"
            name="hiveLifeCycle"
            style={{ marginBottom }}
          >
            {
              (editable&&!modelerData?.deployed) ? <Input placeholder='默认永久保存' /> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.hiveLifeCycle, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="存储类型"
            name="hiveStoredType"
            style={{ marginBottom }}
          >
            {
              (editable&&!modelerData?.deployed) ? <Select allowClear loading={loadingHiveStoredTypes}>
              { hiveStoredTypes?.map(item => <Select.Option key={item} value={item}>{item}</Select.Option>) }
            </Select> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.hiveStoredType, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="存储地址"
            name="hiveStoredLocation"
            style={{ marginBottom }}
          >
            {
              (editable&&!modelerData?.deployed) ? <Input placeholder='请填写存储地址' /> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.hiveStoredLocation, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item
            label="字段分隔符"
            name="hiveFieldsTerminated"
            style={{ marginBottom }}
          >
            {
              (editable&&!modelerData?.deployed) ? <Input placeholder='请填写字段分隔符' /> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.hiveFieldsTerminated, terms)}</span>
            }
          </Form.Item>
        </Col>
        <Col xs={24} sm={24} lg={12} xl={8}>
          <Form.Item label='自定义参数' style={{ marginBottom }}>
            {
              (editable&&!modelerData?.deployed) ? <Form.List name="hiveTableConfigProperties">
                {(fields, { add, remove }) => (
                  <>
                    {fields.map(({ key, name, ...restField }) => (
                      <Space
                        key={key}
                        style={{
                          display: 'flex',
                          marginBottom: 0,
                        }}
                        align="baseline"
                      >
                        <Form.Item
                          {...restField}
                          name={[name, 'key']}
                          style={{ marginBottom }}
                          rules={[
                            {
                              required: true,
                              message: '请输入key值',
                            },
                          ]}
                        >
                          <Input placeholder="请输入key值" />
                        </Form.Item>
                        <Form.Item
                          {...restField}
                          name={[name, 'value']}
                          style={{ marginBottom }}
                          rules={[
                            {
                              required: true,
                              message: '请输入value值',
                            },
                          ]}
                        >
                          <Input placeholder="请输入value值" />
                        </Form.Item>
                        <MinusCircleOutlined onClick={() => remove(name)} />
                      </Space>
                    ))}
                    <Form.Item style={{ marginBottom }}>
                      <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
                        新增参数
                      </Button>
                    </Form.Item>
                  </>
                )}
              </Form.List> : <span className='word-wrap'>{highlightSearchContentByTerms(hiveTableConfigPropertiesDescription, terms)}</span>
            }
          </Form.Item>
        </Col>
      </>
    )
  }

  const onValuesChange = (changedValues, allValues) => {
    if (changedValues.hasOwnProperty('tableType')) return;

    onChange && onChange(changedValues, allValues);

    // //有手动编辑过英文名称并且有内容的情况下, 不能通过编辑中文名称自动翻译
    // if (changedValues.hasOwnProperty('name')) {
    //   setAutoTranslate(changedValues.name==='');
    // } else if (changedValues.hasOwnProperty('cnName')) {
    //   if (autoTranslate) {
    //     dispatchLatest({
    //       type: 'datamodel.translatePhase',
    //       payload: {
    //         params: {
    //           phaseInChinese: changedValues.cnName,
    //         }
    //       },
    //       callback: data => {
    //         if ((data?.translated||'') !== '') {
    //           form?.setFieldsValue({ name: data?.translated||'' });
    //           onChange && onChange({...changedValues, ...{name: data?.translated||''}}, {...allValues, ...{name: data?.translated||''}});
    //         }
    //       }
    //     })
    //   }
    // }
    if (changedValues.hasOwnProperty('dataType')) {
      if (changedValues.dataType) {
        onChange?.({...changedValues, bindingLoadRange: ''}, {...allValues, bindingLoadRange: ''});
      } else {
        onChange?.({...changedValues, bindingLoadRange: ''}, {...allValues, bindingLoadRange: ''});
      }
    } else if (changedValues.hasOwnProperty('dbType')) {
      onChange?.({...changedValues, partition: null}, {...allValues, partition: null});
    }
  }

  return (
    <div className={classnames('model-import-action-header', editable?'':'model-import-action-header-readolny')}>
      <div className='model-import-action-basic mb-3'>
        <h3 className='mr-3' style={{ marginBottom: 0 }}>基本信息</h3>
      </div>
      <Form form={form} {...formItemLayout}
        onValuesChange={onValuesChange}
      >
        <Row gutter={10}>
          <Col xs={24} sm={24} lg={12} xl={8}>                
            <Form.Item
              label='数据库类型'
              name="dbType"
              rules={[{ required: true, message: '请选择数据库类型!' }]}
              style={{ marginBottom }}
            >
              {
                !modelerData?.id ? <Select loading={loadingDbTypes}>
                  { dbTypes?.map(item => <Select.Option key={item} value={item}>{item}</Select.Option>) }
                </Select> : <span className='word-wrap'>
                  {highlightSearchContentByTerms(modelerData?.dbType, terms)}
                </span>
              }
            </Form.Item>
          </Col>
          <Col xs={24} sm={24} lg={12} xl={8}>                
            <Form.Item
              label={<ItemTitle name='cnName' cnName='中文名称' validateReports={validateReports} />}
              name="cnName"
              rules={[{ required: true, message: '请输入中文名称!' }]}
              style={{ marginBottom }}
            >
              {
                editable ? <InputDebounce /> : <span className='word-wrap'>
                  {highlightSearchContentByTerms(modelerData?.cnName, terms)}
                </span>
              }
            </Form.Item>
          </Col>
          <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label={<ItemTitle name='name' cnName='英文名称' validateReports={validateReports} />}
              name="name"
              rules={[
                {
                  required: true,
                  message: '',
                },
                ({ getFieldValue }) => ({
                  validator(_, value) {
                    if ((modelerData?.prefixName&&modelerData?.prefixName===value) || !value) {
                      return Promise.reject(new Error('请输入英文名称!')); 
                    }
                
                    return Promise.resolve();
                  },
                }),
              ]}
              style={{ marginBottom }}
            >
              {
                (editable&&(modelerData?.dbType!=='Hive'||!modelerData?.deployed)) ? <NameInput 
                  prefixName={modelerData?.prefixName} 
                /> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.name, terms)}</span>
              } 
            </Form.Item>
          </Col>
          <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label={<ItemTitle name='remark' cnName='数据内容' validateReports={validateReports} />}
              name="remark"
              // rules={[{ required: true, message: '请输入数据内容!' }]}
              style={{ marginBottom }}
            >
              {
                editable ? <TextArea rows={1} placeholder='描述数据表包含的业务数据，包括数据内容业务描述、表的适用范围、数据粒度、数据统计口径、数据来源等。对于原始数据表，可以说明加载的源接口信息。' /> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.remark, terms)}</span>
              }
            </Form.Item>
          </Col>
          <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label="技术主键"
              name="easyDataModelerPrimaryKey"
              style={{ marginBottom }}
            >
              {
                (editable&&(modelerData?.dbType!=='Hive'||!modelerData?.deployed)) ? <AttributesSelect modelerData={modelerData} mode='tags' /> : <span className='word-wrap'>{highlightSearchContentByTerms(primaryDescription, terms)}</span>
              }
            </Form.Item>
          </Col>
          <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label="Schema"
              name="dataResidence"
              style={{ marginBottom }}
              // rules={[{ required: true, message: '请输入数据库Schema!' }]}
            >
              {
                (editable&&(modelerData?.dbType!=='Hive'||!modelerData?.deployed)) ? <Select allowClear loading={loadingRangeList} placeholder='描述数据表落地的数据库Schema'>
                  { rangeList?.map(item => <Select.Option key={item} value={item}>{item}</Select.Option>) }
                </Select> : <span className='word-wrap'>{highlightSearchContentByTerms(modelerData?.dataResidence, terms)}</span>
              }
            </Form.Item>
          </Col>
          <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label="规范"
              name="easyDataModelerModelingConstraint"
              rules={[{ required: true, message: '请选择规范!' }]}
              style={{ marginBottom }}
            >
              {
                editable ? <ConstraintSelect 
                  constraints={constraints} 
                  onChange={onConstraintChange}
                  onDetail={() => {
                    setRuleParams({ visible: true })
                  }} 
                /> : <div className='flex' style={{ alignItems: 'flex-start' }}>
                  <div className='word-wrap mr-2'>
                    {modelerData?.easyDataModelerModelingConstraint?.cnName}
                  </div>
                  <div style={{ flex: 1, minWidth: 30 }}>
                    <a onClick={() => {
                      setRuleParams({ visible: true })
                    }}>查看</a>
                  </div>
                </div>
              }
            </Form.Item>
          </Col>
          <Col xs={24} sm={24} lg={12} xl={8}>
            <Form.Item
              label="模板类型"
              name="tableType"
              rules={[{ required: true, message: '请选择模板类型!' }]}
              style={{ marginBottom }}
            >
              {
                editable ? <TemplateSelect 
                  modelerData={modelerData}
                  templates={(templates??[]).filter(item=>item.dbType===modelerData?.dbType)} 
                  onChange={onTemplateChange} 
                /> : <span className='word-wrap'>{modelerData?.tableType}</span>
              }
            </Form.Item>
          </Col> 
        </Row> 
      </Form> 
      <div className='model-import-action-technical mb-3' style={{ 
          display: 'flex',
          alignItems: 'center',
        }}
      >
        <h3 className='mr-3' style={{ marginBottom: 0 }}>技术信息</h3>
        {
          isCollapse ? <Button type='primary' size='small' onClick={() => {
            setCollapse(!isCollapse)
          }}>展开<DownOutlined /></Button> : <Button type='primary' size='small' onClick={() => {
            setCollapse(!isCollapse)
          }}>收起<UpOutlined /></Button>
        }
      </div>
      {
        !isCollapse && <Form
          form={form}
          {...formItemLayout}
          onValuesChange={onValuesChange}
        >
          <Row gutter={10}>
           { modelerData?.dbType==='Hive' ? hiveTechnicalInfoComponent()  : genericTechnicalInfoComponent() }
          </Row> 
        </Form>
      }
      <Rule
        {...ruleParams}
        onCancel={() => {
          setRuleParams({ visible: false })
        }}
      />
    </div>
  )
}

export default ImportActionHeader;

const ConstraintSelect = ({ value = {}, constraints = [], onChange, onDetail, ...restProps }) => {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
      <Select 
        onChange={(val) => { onChange?.(val) }} 
        value={value?.id} 
        placeholder='请选择规范'
        style={{ flex: 1 }}
        {...restProps}
      >
      {
        (constraints||[]) && constraints.map((constraint, index) => {
          return (
            <Option key={index} value={constraint.id} >{constraint.cnName||''}</Option>
          );
        })
      }
      </Select>
      <a className='ml-3' onClick={() => { onDetail?.() }}>查看</a>
    </div>
  )
}

const TemplateSelect = ({ value = '', modelerData = undefined, templates = [], onChange, ...restProps }) => {
  const mountRef = useRef(true);
  const [isCustom, setIsCustom] = useState(false);

  useEffect(() => {
    if (mountRef.current && modelerData && Object.keys(modelerData).length > 0) {
      if (modelerData?.tableType && !modelerData?.easyDataModelerModelingTemplate?.name) {
        setIsCustom(true);
      } else {
        setIsCustom(false);
      }

      mountRef.current = false;
    } 
  }, [modelerData])

  useEffect(() => {
    if (modelerData?.dbType && modelerData?.easyDataModelerModelingTemplate?.dbType && modelerData?.dbType !== modelerData?.easyDataModelerModelingTemplate?.dbType) {
      onChange?.('');
    }
  }, [modelerData])

  return (
    <span style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
      {
        isCustom ? <InputDebounce 
          placeholder='请输入模板类型' 
          allowClear 
          value={modelerData?.tableType}
          onChange={(val) => {
            onChange?.(val, true);
          }} 
          style={{ flex: 1 }}
        /> : <Select   
          onChange={(val) => {
            onChange?.(val);
          }} 
          value={value || undefined} 
          placeholder='请选择模板类型'
          allowClear
          style={{ flex: 1 }}
          {...restProps}
        >
        {
          (templates||[]) && templates.map((template, index) => {
            return (
              <Option key={index} value={template.cnName||''} >
                <Tooltip title={template.remark}>
                {template.cnName}
                </Tooltip>
              </Option>
            );
          })
        }
        </Select>
      }
      <Checkbox className='ml-3' checked={isCustom} onChange={(e) => { 
        setIsCustom(e.target.checked); 
        onChange?.('');
      }}>自定义</Checkbox>
    </span>
  )
}

const AttributesSelect = ({ value = [], modelerData, onChange, mode = 'multiple', ...restProps }) => {

  const onAttributeChange = (value) => {
    let currentAttributes = [];
    if (mode === 'multiple') {
      currentAttributes = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(attribute => (value||[]).indexOf(attribute.iid)!==-1);
    } else {
      (value||[]).forEach(item => {

        const filterAttributes = (newAttributes||[]).filter(attribute => item ===attribute.iid);

        if (filterAttributes.length !== 0) {
          currentAttributes = [...currentAttributes, ...filterAttributes];
        } else {
          currentAttributes = [...currentAttributes, { name: item, iid: generateUUID() }];
        }
      })
    }

    triggerChange(currentAttributes);
  }

  const triggerChange = (changedValue) => {
    onChange?.(changedValue);
  };

    //value有可能为空
    value = value ? value: [];
  
    let attributeIds = [];
    let newAttributes = [...(modelerData?.easyDataModelerDataModelAttributes||[])];
  
    value.forEach(attribute => {
      attributeIds.push(attribute.iid);
  
      if (mode === 'tags') {
        const filterAttributes = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(_attribute => attribute.iid ===_attribute.iid);
  
        if (filterAttributes.length === 0) {
          newAttributes = [...newAttributes, attribute];
        } 
      }
    })

  return (
    <Select 
      onChange={(value) => { onAttributeChange && onAttributeChange(value) }} 
      value={attributeIds} 
      placeholder='请选择字段名称'
      mode={mode}
      allowClear={true}
    >
    {
      (newAttributes||[]).map((attribute, index) => {
        return (
          <Option key={index} value={attribute.iid?attribute.iid:(attribute.name||'')}>{attribute.name||''}</Option>
        );
      })
    }
    </Select>
  );
}

const DistributionItem = ({ value, modelerData, onChange, ...restProps }) => {
  const onAttributeChange = (value) => {
    const newKeys = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(attribute => (value||[]).indexOf(attribute.iid)!==-1);

    triggerChange({ keys: newKeys });
  }

  const triggerChange = (changedValue) => {
    onChange?.({...value, ...changedValue});
  }

  return (
    <Select 
      onChange={(val) => { 
        onAttributeChange(val) 
      }} 
      value={(value?.keys??[]).map(item => item.iid)} 
      placeholder='请选择字段名称'
      mode='multiple'
      allowClear={true}
    >
    {
      modelerData?.easyDataModelerDataModelAttributes?.map((attribute, index) => <Option key={index} value={attribute.iid}>{attribute.name}</Option>
      )
    }
    </Select>
  );
}

const DistributionBucketItem = ({ value, modelerData, onChange, ...restProps }) => {
  const onAttributeChange = (value) => {
    const newKeys = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(attribute => (value||[]).indexOf(attribute.iid)!==-1);

    if ((newKeys??[]).length === 0) {
      triggerChange({ keys: newKeys, bucketCount: null });
    } else {
      triggerChange({ keys: newKeys });
    }
  }

  const onBucketChange = (e) => {
    const val = e.target.value;
    //只允许输入数字
    const reg = /^\d+$/;
    if (reg.test(val) || val === '') {
      triggerChange({ bucketCount: val });
    }
  }

  const triggerChange = (changedValue) => {
    onChange?.({...value, ...changedValue, type: 'Hive'});
  }

  return (
    <Row gutter={10}>
      <Col span={(value?.keys??[]).length>0?12:24}>
        <Select 
          onChange={(val) => { 
            onAttributeChange(val) 
          }} 
          value={(value?.keys??[]).map(item => item.iid)} 
          placeholder='请选择字段名称'
          mode='multiple'
          allowClear={true}
        >
        {
          modelerData?.easyDataModelerDataModelAttributes?.map((attribute, index) => <Option key={index} value={attribute.iid}>{attribute.name}</Option>
          )
        }
        </Select>
      </Col>
      {
        (value?.keys??[]).length>0 && <Col span={12}>
          <Input        
            onChange={onBucketChange}  
            value={value.bucketCount} 
            style={{ width: '100%' }}
            placeholder='分桶数'
          />
        </Col>
      }
    </Row>
  );
}

const PartitionSelect = ({ value = {}, modelerData, partitionTypes = [], onChange, ...restProps }) => {

  const onPartitionTypeChange = (value) => {

    let currentPartitionType = {}; 
    (partitionTypes||[]).forEach((partitionType, index) => {
      if (value === partitionType.name) {
        currentPartitionType = partitionType;
      }
    })

    triggerChange({ partitionType: currentPartitionType });
  }

  const onAttributeChange = (value) => {
    const currentAttributes = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(attribute => (value||[]).indexOf(attribute.iid)!==-1);

    triggerChange({ keys: currentAttributes });
  }

  const triggerChange = (changedValue) => {
    onChange?.({
      ...value,
      ...changedValue,
    });
  };

  //value有可能为空
  value = value ? value: {};
  
  let attributeIds = [];
  (value?.keys||[]).forEach(attribute => {
    attributeIds.push(attribute.iid);
  })

  return (
    <Row gutter={10}>
      <Col span={10}>
      <Select 
        onChange={onPartitionTypeChange} 
        value={value?.partitionType?.name} 
        placeholder='请选择分区类型'
        allowClear={true}
      >
      {
        partitionTypes?.map((partitionType, index) => {
          return (
            <Option key={partitionType.name} value={partitionType.name}>{partitionType.cnName}</Option>
          );
        })
      }
      </Select>
      </Col>
      <Col span={14}>
        <Select 
          onChange={(value) => { onAttributeChange && onAttributeChange(value) }} 
          value={attributeIds} 
          placeholder='请维护分区字段'
          mode='multiple'
          allowClear={true}
        >
        {
          (modelerData?.easyDataModelerDataModelAttributes||[]).map((attribute, index) => {
            return (
              <Option key={index} value={attribute.iid||''}>{attribute.name||''}</Option>
            );
          })
        }
        </Select>
      </Col>
    </Row>
  );
}

const HivePartitionSelect = ({ value, onChange, partitionTypes, modelerData }) => {
  const [popupParams, setPopupParams] = useState({
    visible: false,
    value: undefined,
  })
  const onPartitionTypeChange = (value) => {
    let currentPartitionType = {}; 
    (partitionTypes||[]).forEach((partitionType, index) => {
      if (value === partitionType.name) {
        currentPartitionType = partitionType;
      }
    })

    triggerChange({ partitionType: currentPartitionType });
  }

  const triggerChange = (changedValue) => {
    onChange?.({
      ...value,
      ...changedValue,
    })
  }

  return (
    <>
    <Row gutter={10}>
      <Col span={10}>
        <Select 
          onChange={onPartitionTypeChange} 
          value={value?.partitionType?.name} 
          placeholder='请选择分区类型'
          allowClear={true}
        >
        {
          partitionTypes?.map((partitionType, index) => {
            return (
              <Option key={partitionType.name} value={partitionType.name}>{partitionType.cnName}</Option>
            );
          })
        }
        </Select>
      </Col>
      <Col span={14}>
      <Select
        mode='multiple'
        placeholder='请维护分区字段'
        onDropdownVisibleChange={(open) => {
          if (open) {
            setPopupParams({
              visible: true,
              value: value?.keys??[],
            })
          }
        }}
        open={false}
        value={(value?.keys??[]).map(item => item.iid)}
        options={(value?.keys??[]).map(item => ({ label: item.name, value: item.iid }))}
        allowClear
        onChange={(newValue) => {
          let newKeys = [...value?.keys??[]]
          newKeys = newKeys.filter(item => newValue.indexOf(item.iid)!==-1)
          triggerChange({ keys: newKeys })
        }}
        maxTagCount='responsive'
      />
      </Col>
    </Row>
    <HivePartitionAddKey 
      {...popupParams} 
      modelerData={modelerData}
      onChange={(data) => {
        setPopupParams({
          visible: false,
          value: undefined,
        })

        if (data) {
          triggerChange({ keys: data })
        }
      }}
    />
    </>
  )
}

const LoadSelect = ({ value = '', onChange, ...restProps }) => {

  const onLoadChange = (value) => {

    triggerChange(value.join('/'));
  }

  const triggerChange = (changedValue) => {
    onChange?.(changedValue);
  };

  //value有可能为空
  value = value ? value: '';
  
  let loadNames = [];

  if (value !== '') {
    value.split('/').forEach(item => {
      loadNames.push(item);
    })
  }

  return (
    <Select 
      mode="tags" 
      tokenSeparators={['/', ' ']}
      onChange={(value) => { onLoadChange && onLoadChange(value) }} 
      value={loadNames} 
      placeholder='请选择或者手动输入加载方式'
      allowClear={true}
    >
    {
      loadOptions.map((item, index) => {
        return (
          <Option key={index} value={item}>{item}</Option>
        );
      })
    }
    </Select>
  );
}

const UpdateSelect = ({ value = '', onChange, ...restProps }) => {

  const onUpdateChange = (value) => {

    triggerChange(value.join('/'));
  }

  const triggerChange = (changedValue) => {
    onChange?.(changedValue);
  };

  //value有可能为空
  value = value ? value: '';
  
  let updateNames = [];
  if (value !== '') {
    value.split('/').forEach(item => {
      updateNames.push(item);
    })
  }

  return (
    <Select 
      mode="tags" 
      tokenSeparators={['/', ' ']}
      onChange={(value) => { onUpdateChange && onUpdateChange(value) }} 
      value={updateNames} 
      allowClear={true}
      {...restProps}
    >
    {
      updateOptions.map((item, index) => {
        return (
          <Option key={index} value={item}>{item}</Option>
        );
      })
    }
    </Select>
  );
}

const ItemTitle = ({ name, cnName, validateReports }) => {
  return (
    <Space size={2}>
      {cnName}
      <ValidateTip validateReports={validateReports} type='DataModel' propertyName={name} />
    </Space>
  )
}

export const ValidateTip = ({ validateReports, type, propertyName, iid }) => {
  const reports = useMemo(() => {
    const index = (validateReports??[]).findIndex(item => (
      (item.type === type) && (!iid || item.iid === iid)
    ))
    if (index !== -1) {
      return (validateReports[index].reportItems??[]).filter(item => item.checkRule?.ruleTemplate?.checkProperty?.originalPropertyEnName === propertyName)
    }

    return []
  }, [validateReports, type, propertyName])

  return (
    <React.Fragment>
    {
      (reports??[]).length === 0 ? null : <Tooltip title={
        <div>
        {
          (reports??[]).map((item, index) => (
            <Row key={index}>
              <Space>
                { (item.checkRule?.alertTypeId === 'enforced') ? <WarningFilled style={{ color: '#E94848' }} /> : <ExclamationCircleFilled style={{ color: '#F7AB00' }} /> }
                <span>{item.checkRule?.alertContent}</span>
              </Space>
            </Row>
          ))
        }
        </div>
      }>
        {
          (reports??[]).findIndex(item => item.checkRule?.alertTypeId === 'enforced') !== -1 ? <WarningFilled style={{ color: '#E94848' }} /> : <ExclamationCircleFilled style={{ color: '#F7AB00' }} />
        }  
      </Tooltip>
    }
    </React.Fragment>
  )
}