import React from "react"
import { Modal, Button, Row, Col, Space, Select, Input, Form, Tooltip, Typography, Spin, Checkbox } from 'antd'
import { SettingFilled } from '@ant-design/icons';

import { dispatch } from '../../../../model'
import { formatVersionDate } from "../../../../util"
import download from "../../../../util/Component/download"

const ddlFilterInfo = {
  表: {
    tableDrop: 'DROP',
    tableCreate: 'CREATE',
    tableAlert: 'ALERT',
    tableSchema: '表物理位置',
    tableCnName: '表中文名',
    tableRemark: '表描述',
  },
  KEY: {
    primaryKey: '主键',
    primaryKeyConstraint: '主键约束',
  },
  字段: {
    columnCnName: '中文名',
    columnRemark: '字段描述',
  },
  索引: {
    index: '索引',
    indexRemark: '注释',
  }
}

const notAlertSpecialInfo = [
  { key: 'tableCreate', defaultValue: true },
  { key: 'tableAlert', defaultValue: false },
]

const alertSpecialInfo = [
  { key: 'tableCreate', defaultValue: false },
  { key: 'tableAlert', defaultValue: true },
  { key: 'tableDrop', defaultValue: false },
]

const FC = (props) => {
  const { ids, visible, onCancel } = props
  const [downloading, setDownloading] = React.useState(false)
  const basicRef = React.useRef()

  const close = () => {
    setDownloading(false)
    onCancel?.()
  }

  const onDownload = () => {
    setDownloading(true)
    dispatch({
      type: 'datamodel.downloadExportTableDDLListZip',
      payload: {
        data: basicRef.current.configs??[],
        headers: {
          'Content-Type': 'application/json',
        },
        responseType: 'blob',
      },
      callback: (data) => {
        setDownloading(false)
        download(data)
      },
      error: () => {
        setDownloading(false)
      }
    }) 
  }

  const footer = React.useMemo(() => {
    return [
      <Button key={'cancel'}
        onClick={() => close()}
      >取消</Button>,
      <Button key={'save'} type='primary'
        loading={downloading}
        disabled={downloading}
        onClick={() => onDownload()}
      >导出</Button>
    ]
  }, [close, onDownload, downloading])

  return (
    <Modal
      visible={visible}
      footer={footer}
      width='90%'
      bodyStyle={{ padding: '15px', height: '80vh', overflow: 'auto' }}
      title='DDL导出详情'
      centered destroyOnClose
      onCancel={() => { close() }}
    >
      <Basic ref={basicRef} ids={ids} />
    </Modal>
  )
}

export default FC

const Basic = React.forwardRef(function ({ ids }, ref) {
  const [loading, setLoading] = React.useState(false)
  const [data, setData] = React.useState()
  const [configs, setConfigs] = React.useState()
  const [currentConfig, setConfig] = React.useState()
  const [loadingDDLGenerators, setLoadingDDLGenerators] = React.useState(false)
  const [ddlGenerators, setDDLGenerators] = React.useState()

  React.useImperativeHandle(ref, () => ({
    configs,
  }), [configs])

  React.useEffect(() => {
    if ((ids??[]).length > 0) {
      exportTableDDLAbstractList()
    }
  }, [ids])

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

  React.useEffect(() => {
    let ddlFilter = {}
    for (const key in ddlFilterInfo) {
      for (const _key in ddlFilterInfo[key]) {
        ddlFilter[_key] = true
      
        const index = notAlertSpecialInfo.findIndex(item => item.key === _key)
        if (index !== -1) {
          ddlFilter[_key] = notAlertSpecialInfo[index].defaultValue
        }
      }
    }

    const newConfigs = (data??[]).map(item => ({ 
      alertDLL: false, //false全量 true增量
      ...item, 
      ddlFilter,
    }))
    setConfigs(newConfigs)
    if ((newConfigs??[]).length > 0) {
      setConfig(newConfigs[0])
    }
  }, [data])

  const exportTableDDLAbstractList = () => {
    setLoading(true)
    dispatch({
      type: 'datamodel.exportTableDDLAbstractList',
      payload: {
        data: ids,
      },
      callback: (data) => {
        setLoading(false)
        setData(data)
      },
      error: () => {
        setLoading(false)
      }
    }) 
  }

  const getDDLGenerators = (needDB = false) => {
    setLoadingDDLGenerators(true)
    dispatch({
      type: 'datamodel.ddlGenerators',
      callback: data => {
        setLoadingDDLGenerators(false)
        setDDLGenerators(data)
      }, 
      error: () => {
        setLoadingDDLGenerators(false)
      }
    })
  }

  return (
    <Spin spinning={loading}>
      <Row gutter={15}>
        <Col flex='350px' style={{ height: 'calc(80vh - 30px)', overflow: 'auto' }}>
        { data?.map((item, index) => (
          <Row gutter={10} key={index} className={index!==0?'mt-2':''} align='middle'>
            <Col flex='1' style={{ overflow: 'hidden' }}>
              <Tooltip title={item.modelEnName}>
                <Typography.Text ellipsis={true}>
                  <a style={{ color: (item.easyDataModelerDataModelId===currentConfig?.easyDataModelerDataModelId)?'#196AD2':'#262626' }}
                    onClick={() => {
                      const index = (configs??[]).findIndex(_item => item.easyDataModelerDataModelId === _item.easyDataModelerDataModelId)
                      if (index !== -1) {
                        setConfig(configs[index])
                      }
                    }}
                  >
                  {item.modelEnName}
                  </a>
                </Typography.Text>
              </Tooltip>
            </Col>
            <Col flex='none'>
              <Select defaultValue={item.dbType} 
                style={{ width: 120 }}
                loading={loadingDDLGenerators}
                onChange={(val) => {
                  const index = (configs??[]).findIndex(_item => item.easyDataModelerDataModelId === _item.easyDataModelerDataModelId)
                  if (index !== -1) {
                    const newConfig = { ...configs[index], dbType: val }
                    setConfigs((prev) => {
                      const newConfigs = [...prev??[]]
                      newConfigs.splice(index, 1, newConfig)
                      return newConfigs
                    })

                    if (configs[index].easyDataModelerDataModelId === currentConfig?.easyDataModelerDataModelId) {
                      setConfig(newConfig)
                    }
                  }
                }}
              >
              { 
                ddlGenerators?.map(item => (
                  <Select.Option key={item.name} value={item.name}>{item.name}</Select.Option>
                )) 
              }
              </Select>  
            </Col>
            <Col flex='none'>
              <Select defaultValue={false} 
                style={{ width: 80 }}
                onChange={(val) => {
                  const index = (configs??[]).findIndex(_item => item.easyDataModelerDataModelId === _item.easyDataModelerDataModelId)
                  if (index !== -1) {
                    const newConfig = { ...configs[index], alertDLL: val, leftVersionId: null, rightVersionId: null }
                    const info = val ? alertSpecialInfo : notAlertSpecialInfo
                    for (const item of info) {
                      newConfig.ddlFilter[item.key] = item.defaultValue
                    }

                    setConfigs((prev) => {
                      const newConfigs = [...prev??[]]
                      newConfigs.splice(index, 1, newConfig)
                      return newConfigs
                    })

                    if (configs[index].easyDataModelerDataModelId === currentConfig?.easyDataModelerDataModelId) {
                      setConfig(newConfig)
                    }
                  }
                }}
              >
                <Select.Option value={false}>全量</Select.Option>
                { item.supportAlertDLL && <Select.Option value={true}>增量</Select.Option> }
              </Select>
            </Col>
          </Row>
        )) }
        </Col>
        <Col flex='1' style={{ overflow: 'hidden' }}>
          <DDLDetail config={currentConfig} setConfig={(val) => {
            const index = (configs??[]).findIndex(item => item.easyDataModelerDataModelId === val?.easyDataModelerDataModelId)
            if (index !== -1) {
              setConfigs((prev) => {
                const newConfigs = [...prev??[]]
                newConfigs.splice(index, 1, val)
                return newConfigs
              })
              setConfig(val)
            }
          }} />
        </Col>
      </Row>
    </Spin>
  )
})

const DDLDetail = ({ config, setConfig }) => {
  const [loadingVersions, setLoadingVersions] = React.useState(false)
  const [versions, setVersions] = React.useState()
  const [incVersions, setIncVersions] = React.useState()
  const [loadingDDL, setLoadingDDL] = React.useState(false)
  const [ddl, setDDL] = React.useState()
  const [ddlFilterParams, setDDLFilterParams] = React.useState({
    visible: false,
  })
  const prevModelIdRef = React.useRef()

  React.useEffect(() => {
    if (config?.easyDataModelerDataModelId && config?.easyDataModelerDataModelId!==prevModelIdRef.current) {
      prevModelIdRef.current = config?.easyDataModelerDataModelId
      getVersions()
    } else {
      initConfigVersionId()
    }
  }, [config?.alertDLL, config?.easyDataModelerDataModelId])

  React.useEffect(() => {
    if ((config?.alertDLL&&config?.leftVersionId&&config?.rightVersionId)
      || (!config?.alertDLL&&config?.leftVersionId)) {
      getDDL()
    }
  }, [config?.alertDLL, config?.dbType, config?.leftVersionId, config?.rightVersionId, config?.ddlFilter])

  const getVersions = () => {
    setLoadingVersions(true)
    setVersions()
    dispatch({
      type: 'datamodel.getVersions',
      payload: {
        params: {
          id: config?.easyDataModelerDataModelId,
        }
      },
      callback: data => {
        setLoadingVersions(false)
        const newData = []
        for (const [index, item] of (data??[]).entries()) {
          let name = item.name??''
          name = name + '_' + new Date(item.ts).toLocaleString()
          if ((index === 0&&item.id !== '-1') 
          || (index === 1&&data[0].id === '-1')) {
            name = name+'(当前版本)'
          }

          newData.push({ ...item, name })
        }
        setVersions(newData)
        initConfigVersionId()
      },
      error: () => {
        setLoadingVersions(false)
      }
    })
  }

  const initConfigVersionId = () => {
    setVersions(prevVersions => {
      if (config?.alertDLL) {
        //增量
        if ((prevVersions??[]).length > 1) {
          setIncVersions((prevVersions??[]).slice(0, 1))

          if (!config?.leftVersionId && !config?.rightVersionId) {
            setConfig?.({ 
              ...config, 
              leftVersionId: prevVersions[1].id, 
              rightVersionId: prevVersions[0].id,
            })
          }
        }
      } else {
        //全量
        if ((prevVersions??[]).length > 0) {
          if (!config?.leftVersionId) {
            setConfig?.({ 
              ...config, 
              leftVersionId: prevVersions[0].id, 
              rightVersionId: null,
            })
          }
        }
      }

      return prevVersions
    })
  }

  const getDDL = () => {
    setLoadingDDL(true)
    dispatch({
      type: 'datamodel.getExportTableDDL',
      payload: {
        data: config,
      },
      callback: data => {
        setLoadingDDL(false)
        setDDL(data)
      },
      error: () => {
        setLoadingDDL(false)
      }
    })
  }

  const onBasicChange = (val) => {
    setConfig({
      ...config,
      leftVersionId: val,
      rightVersionId: null,
    })
    
    const index = (versions??[]).findIndex(item => item.id === val)
    if (index !== -1) {
      setIncVersions((versions||[]).slice(0, index))
    }
  }

  const onIncChange = (val) => {
    setConfig({
      ...config,
      rightVersionId: val,
    })
  }

  return (
    <>
      <div className='flex' style={{ justifyContent: 'space-between' }}>
        <Form layout='inline'>
          <Form.Item label='基线版本'>
            <Select loading={loadingVersions} value={(versions??[]).length>0?config?.leftVersionId:undefined} style={{ width: 300 }} onChange={onBasicChange}  >
            {
              versions?.map((item, index) => (
                <Select.Option key={index} value={item.id} disabled={config?.alertDLL&&index===0}>
                  <Tooltip title={(config?.alertDLL&&index===0)?'最近版本只能在增量版本中被选中':''}>
                  {item.name}
                  </Tooltip>
                </Select.Option>
              ))
            }
            </Select>
          </Form.Item>
          {
            config?.alertDLL && <Form.Item label='增量版本' style={{ marginRight: 5 }}>
              <Select value={(incVersions??[]).length>0?config?.rightVersionId:undefined} style={{ width: 300 }} disabled={!config?.leftVersionId} onChange={onIncChange}>
              {
                (incVersions||[]).map((item, index) => (
                  <Select.Option key={index} value={item.id}>{item.name}</Select.Option>
                ))
              }
              </Select>
            </Form.Item>
          }
        </Form>
        {/* <Button icon={<SettingFilled />} onClick={() => { setDDLFilterParams({ visible: true }) }} /> */}
      </div>
      <div className='mt-2'>
        <Spin spinning={loadingDDL}>
          <Input.TextArea value={ddl??''} style={{ height: 'calc(80vh - 70px)', resize: 'none'  }} />
        </Spin>
      </div>
      <DDLFilter 
        {...ddlFilterParams}
        config={config}
        setConfig={setConfig}
        onCancel={() => {
          setDDLFilterParams({ visible: false })
        }}
      />
    </>
  )
}

const DDLFilter = (props) => {
  const { visible, onCancel, config, setConfig } = props
  const [form] = Form.useForm()

  React.useEffect(() => {
    if (visible) {
      form.setFieldsValue(config?.ddlFilter)
    }
  }, [config, visible])

  const close = () => {
    onCancel?.()
  }

  const save = () => {
    setConfig?.({ ...config, ddlFilter: form?.getFieldsValue() })
    close()
  }

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

  const onValuesChange = (changedValues, allValues) => {
    if (changedValues.hasOwnProperty('primaryKeyConstraint')) {
      if (changedValues['primaryKeyConstraint']) {
        form?.setFieldsValue({ primaryKey: true })
      }
    } 
    if (changedValues.hasOwnProperty('primaryKey')) {
      if (!changedValues['primaryKey']) {
        form?.setFieldsValue({ primaryKeyConstraint: false })
      }
    }

    if (changedValues.hasOwnProperty('indexRemark')) {
      if (changedValues['indexRemark']) {
        form?.setFieldsValue({ index: true })
      }
    }
    if (changedValues.hasOwnProperty('index')) {
      if (!changedValues['index']) {
        form?.setFieldsValue({ indexRemark: false })
      }
    }
  }

  return (
    <Modal
      visible={visible}
      footer={footer}
      bodyStyle={{ padding: '15px 15px 0px', overflowX: 'auto', maxHeight: '80vh' }}
      title=''
      width={600}
      closable={false}
      centered destroyOnClose
      onCancel={() => { close() }}
    >
      <Form
        form={form}
        labelCol={{ span: 4 }}
        wrapperCol={{ span: 20 }}
        autoComplete="off"
        onValuesChange={onValuesChange}
      >
        {
          Object.keys(ddlFilterInfo).map((key, index) => {
            const item = ddlFilterInfo[key]
            return (
              <Form.Item
                key={key}
                label={`对于${key}`}
                style={{ marginBottom: 15 }}
              >
                <Row>
                {
                  Object.keys(item).map((_key, index) => {
                    let disabled = false
                    const info = (config?.alertDLL) ? alertSpecialInfo : notAlertSpecialInfo
                    const _index = info.findIndex(item => item.key === _key)
                    disabled = (_index !== -1)

                    return (
                      <Col span={6} key={index}>
                        <Form.Item name={_key}
                          style={{ marginBottom: 0 }}
                          valuePropName="checked"
                        >
                          <Checkbox disabled={disabled}>
                          {item[_key]}
                          </Checkbox>
                        </Form.Item>
                      </Col>
                    )
                  })
                }
                </Row>
              </Form.Item>
            )
          })
        }
      </Form>
    </Modal>
  )
}