<template>
  <span class="dg-tab-select">
    <el-button type="primary" @click="show"><slot>选择数据库表</slot></el-button>
    <dg-dialog
      :visible.sync="visible"
      append-to-body
      top="60px"
      title="数据库表选择"
      @confirm="handleConfirm"
      @close="handleClose"
    >
      <dg-form ref="form" :form-data.sync="form" :form-items="items" label-width="180px" class="select-form">
        <el-form-item :label="tableItem.label" prop="tableSelected">
          <el-select
            v-model="form.tableSelected"
            :multiple="multiple"
            filterable
            remote
            reserve-keyword
            placeholder="请输入表名称关键词查询"
            :remote-method="handleTableSearch"
            :loading="tableItem.loading"
            :disabled="tableItem.disabled"
          >
            <el-option
              v-for="item in tableItem.selectOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="已选择数据库表">
          <span v-if="!layoutSelected.length" class="empty-tip">暂未选择数据库表</span>
          <el-tag
            v-for="tag in layoutSelected"
            :key="tag"
            closable
            style="margin-right: 6px"
            @close="handleDeleteSelected(tag)"
          >
            {{ tag.split('|').pop() }}
          </el-tag>
        </el-form-item>
      </dg-form>
    </dg-dialog>
  </span>
</template>

<script>
export default {
  name: 'DgTabSelect',

  props: {
    multiple: {
      type: Boolean,
      default: false,
    },
    value: {
      type: [String, Array],
      default: '',
    },
  },

  data() {
    return {
      visible: false,
      form: {
        dbSelected: '',
        schemaSelected: '',
        tableSelected: null,
      },
      items: [
        {
          editer: 'select',
          label: '数据库',
          apiCode: 'DBListSelect',
          value: 'dbSelected',
          handleChange: this.handleDBChange,
        },
        {
          editer: 'select',
          label: '模式名',
          value: 'schemaSelected',
          disabled: true,
          selectOptions: [],
          handleChange: this.handleSchemaChange,
        },
      ],
      tableItem: {
        label: '表名称',
        value: 'tableSelected',
        disabled: true,
        loading: false,
        selectOptions: [],
      },
    }
  },

  computed: {
    layoutSelected() {
      const value = this.form.tableSelected || this.value
      return this.multiple ? [...new Set([...this.value, ...(this.form.tableSelected || [])])] : value ? [value] : []
    },
  },

  methods: {
    show() {
      this.visible = true
    },
    handleConfirm() {
      this.$emit('input', this.multiple ? this.layoutSelected : this.layoutSelected[0])
      this.visible = false
    },
    handleClose() {
      this.form.dbSelected = ''
      this.form.schemaSelected = ''
      this.form.tableSelected = null
      this.setItemProps('table', [], true)
      this.setItemProps('schema', [], true)
    },
    async handleDBChange() {
      const { dbSelected } = this.form
      if (dbSelected) {
        const options = await this.getScheme(dbSelected)
        this.setItemProps('schema', options, false)
      } else {
        this.setItemProps('schema', [], true)
      }
      this.form.schemaSelected = ''
      this.form.tableSelected = this.multiple ? [] : ''
      this.setItemProps('table', [], true)
    },
    handleSchemaChange() {
      const { schemaSelected } = this.form
      if (schemaSelected) {
        this.setItemProps('table', [], false)
      } else {
        this.setItemProps('table', [], true)
      }
      this.form.tableSelected = this.multiple ? [] : ''
    },
    async handleTableSearch(tableName) {
      if (!tableName) {
        this.setItemProps('table', [], false)
        return
      }
      const { dbSelected, schemaSelected } = this.form
      if (dbSelected && schemaSelected) {
        this.tableItem.loading = true
        const options = await this.getTable({ dbName: dbSelected, schemaName: schemaSelected, tableName })
        this.tableItem.loading = false
        this.setItemProps('table', options, false)
      }
    },
    handleDeleteSelected(tag) {
      this.form.tableSelected = this.multiple ? this.form.tableSelected.filter((v) => v !== tag) : ''
    },

    /**
     * @param type {'schema' | 'table'}
     * @param selectOptions any[]
     * @param disabled boolean
     */
    setItemProps(type, selectOptions = [], disabled = true) {
      const item = type === 'schema' ? this.items[1] : this.tableItem
      item['selectOptions'] = selectOptions
      item['disabled'] = disabled
    },

    async getScheme(dbName) {
      try {
        const { root } = await this.$api.DgJsonStore({
          apiCode: 'schemaListSelect',
          params: `command=init&dbName=${dbName}`,
        })

        const schemas = root.reduce((res = [], { CLT_SCHEMA_NAME = '' }) => {
          return res.concat(CLT_SCHEMA_NAME.split(',').filter((i) => i && i.trim()))
        }, [])

        return [...new Set(schemas)].map((v) => ({ id: v, name: v }))
      } catch (e) {
        return []
      }
    },
    async getTable({ dbName, schemaName, tableName }) {
      try {
        const { root } = await this.$api.DgJsonStore({
          apiCode: 'queryMetaTable',
          params: `command=init&dbName=${dbName}&schemaName=${schemaName}&TAB_LIKE=${tableName}`,
        })

        return [...new Set(root.map(({ TAB_NAME }) => TAB_NAME))].map((v) => ({
          value: [dbName, schemaName, v.trim()].join('|'),
          label: v.trim(),
        }))
      } catch (e) {
        return []
      }
    },
  },
}
</script>
