<template>
  <el-dialog :title="title" v-model="visible" width="90%"
             :close-on-click-modal="false" draggable>
    <el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="150px" v-loading="loading"
             :disabled="operType === 'view'">
      <el-row :gutter="24">
        <el-col :span="12" class="mb20">
          <el-form-item :label="t('createTable.tableName')" prop="tableName">
            <el-input v-model="form.tableName" :placeholder="t('createTable.inputTableNameTip')"/>
          </el-form-item>
        </el-col>

        <el-col :span="12" class="mb20">
          <el-form-item :label="t('createTable.comments')" prop="comments">
            <el-input v-model="form.comments" :placeholder="t('createTable.inputCommentsTip')"/>
          </el-form-item>
        </el-col>

        <el-col :span="24" class="mb20">
          <el-form-item :label="t('createTable.columnInfo')" prop="columns">
            <el-table :data="form.columns" border style="width: 100%" max-height="500">
              <el-table-column type="index" :label="t('createTable.index')" width="80">
                <template #header>
                  <el-button icon="Plus" size="small" type="primary" circle @click="onAddItem"></el-button>
                </template>
                <template #default="scope">
                  <el-button icon="Minus" size="small" type="danger" circle
                             @click="handleDelete(scope.$index, scope.row)"></el-button>
                </template>
              </el-table-column>
              <el-table-column prop="name" :label="t('createTable.name')" show-overflow-tooltip>
                <template #default="scope">
                  <el-input v-model="scope.row.name" :placeholder="t('createTable.name')"
                            @blur="suggestedFieldType(scope.row)"/>
                </template>
              </el-table-column>
              <el-table-column prop="comment" :label="t('createTable.comment')" show-overflow-tooltip>
                <template #default="scope">
                  <el-input v-model="scope.row.comment" :placeholder="t('createTable.comment')"/>
                </template>
              </el-table-column>
              <el-table-column prop="typeName" :label="t('createTable.typeName')" show-overflow-tooltip>
                <template #default="scope">
                  <el-select v-model="scope.row.typeName" :placeholder="t('createTable.typeName')" clearable filterable>
                    <el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value"/>
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column prop="precision" :label="t('createTable.precision')" show-overflow-tooltip>
                <template #default="scope">
                  <el-input-number :min="0" :max="10000" v-model="scope.row.precision"
                                   :placeholder="t('createTable.precision')"></el-input-number>
                </template>
              </el-table-column>
              <el-table-column prop="scale" :label="t('createTable.scale')" show-overflow-tooltip>
                <template #default="scope">
                  <el-input-number :min="0" :max="10000" v-model="scope.row.scale"
                                   :placeholder="t('createTable.scale')"></el-input-number>
                </template>
              </el-table-column>
              <el-table-column prop="defaultValue" :label="t('createTable.defaultValue')" show-overflow-tooltip>
                <template #default="scope">
                  <el-input v-model="scope.row.defaultValue" :placeholder="t('createTable.defaultValue')"/>
                </template>
              </el-table-column>
              <el-table-column prop="primary" :label="t('createTable.primary')" show-overflow-tooltip>
                <template #default="scope">
                  <el-radio-group v-model="scope.row.primary">
                    <el-radio v-for="(item, index) in tableDict" :key="index" :label="item.value" class="w-5">
                      {{ item.label }}
                    </el-radio>
                  </el-radio-group>
                </template>
              </el-table-column>
              <el-table-column prop="nullable" :label="t('createTable.nullable')" show-overflow-tooltip>
                <template #default="scope">
                  <el-radio-group v-model="scope.row.nullable">
                    <el-radio v-for="(item, index) in tableDict" :key="index" :label="item.value" class="w-5">
                      {{ item.label }}
                    </el-radio>
                  </el-radio-group>
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
        </el-col>

      </el-row>
    </el-form>
    <template #footer v-if="operType !== 'view'">
        <span class="dialog-footer">
          <el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
          <el-button type="primary" @click="onSubmit" :disabled="loading">{{
              $t('common.confirmButtonText')
            }}</el-button>
        </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts" name="CreateTableDialog">
import {useMessage, useMessageBox} from "/@/hooks/message";
import {getObj, addObj, putObj} from '/@/api/gen/create-table'
import {useI18n} from "vue-i18n"
import {rule, validateNull} from '/@/utils/validate';
import {useDict} from "/@/hooks/dict";
import {list} from "/@/api/gen/fieldtype";
import {fetchList} from '/@/api/gen/table';

const emit = defineEmits(['refresh']);

const {t} = useI18n();
const {yes_no_type} = useDict('yes_no_type');

const tableDict = [{value: -1, label: '否'}, {value: 1, label: '是'}]

// 定义变量内容
const dataFormRef = ref();
const visible = ref(false);
const loading = ref(false);
const operType = ref();
const title = ref('');
const typeList = ref([]) as any;

// 提交表单数据
const form = reactive({
  id: '',
  tableName: '',
  dsName: '',
  comments: '',
  databaseType: '',
  pkPolicy: '',
  primary: '',
  columnsInfo: '',
  columnInfo: '',
  columns: [] as any
});

/**
 * 校验数据源名
 * @param {校验数据源名} rule
 * @param {*} value
 * @param {*} callback
 */
let validateTableName = async (rule, value, callback) => {
  const {data} = await fetchList({tableName: value})
  if (data.total === 0) {
    callback()
  } else {
    callback(new Error('表名已存在'))
  }
}

// 定义校验规则
const dataRules = ref({
  tableName: [
    {required: true, message: '表名称不能为空', trigger: 'blur'},
    {max: 32, message: '长度在 32 个字符', trigger: 'blur'},
    {validator: rule.validatorLowercase, trigger: 'blur'},
    {validator: validateTableName, trigger: 'blur'}
  ],
  comments: [{validator: rule.overLength, trigger: 'blur'}, {
    required: true,
    message: '表注释不能为空',
    trigger: 'blur'
  }],
  databaseType: [{required: true, message: '数据库类型不能为空', trigger: 'blur'}],
  pkPolicy: [{required: true, message: '主键策略不能为空', trigger: 'blur'}],
  columns: [{required: true, message: '字段信息不能为空', trigger: 'blur'}],
})

// 打开弹窗
const openDialog = (type: string, id: string, dsName: string) => {
  visible.value = true
  operType.value = type;
  form.id = ''
  form.dsName = dsName
  index = 1
  if (type === 'add') {
    title.value = t('common.addBtn');
  } else if (type === 'edit') {
    title.value = t('common.editBtn');
  } else if (type === 'view') {
    title.value = t('common.viewBtn');
  }
  // 获取字典值
  getFieldTypeList()
  // 重置表单数据
  nextTick(() => {
    dataFormRef.value?.resetFields();
    if (!id) onAddItem()
  });

  // 获取CreateTable信息
  if (id) {
    form.id = id
    getCreateTableData(id)
  }
};

// 提交
const onSubmit = async () => {
  const valid = await dataFormRef.value.validate().catch(() => {
  });
  if (!valid) return false;

  try {
    if (form.id) {
      await useMessageBox().confirm("注意：目前修改会重新建表" + form.tableName);
    }
  } catch {
    return;
  }

  try {
    loading.value = true;
    form.columnInfo = JSON.stringify(form.columns)
    let columns = {} as any
    form.columns.forEach(each => {
      if (validateNull(each.defaultValue)) each.defaultValue = null
      columns[each.name] = each
    })
    form.columnsInfo = JSON.stringify(columns)
    await addObj(form);
    useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText'));
    visible.value = false;
    emit('refresh');
  } catch (err: any) {
    useMessage().error(err.msg);
  } finally {
    loading.value = false;
  }
};

// 初始化表单数据
const getCreateTableData = (id: string) => {
  // 获取数据
  loading.value = true
  getObj(id).then((res: any) => {
    let columnInfo = res.data.columnInfo;
    res.data.columns = validateNull(columnInfo) ? [] : JSON.parse(columnInfo);
    Object.assign(form, res.data)
  }).finally(() => {
    loading.value = false
  })
};

let index = 1;
const onAddItem = () => {
  let find = form.columns.find(f => f.name === 'id');
  if (find) {
    let obj = {
      name: '',
      comment: '',
      typeName: 'varchar',
      precision: 255,
      scale: 0,
      defaultValue: null,
      primary: -1,
      nullable: 1
    };

    // 从 index为 1 的位置开始添加, 并且新增的字段要依次向后
    form.columns.splice(index++, 0, obj)
    return
  }
  let id = {
    name: 'id',
    comment: '主键',
    typeName: 'bigint',
    precision: 20,
    scale: 0,
    defaultValue: null,
    primary: 1,
    nullable: -1
  };
  let create_user = {
    name: 'create_by',
    comment: '创建人',
    typeName: 'varchar',
    precision: 64,
    scale: 0,
    defaultValue: null,
    primary: -1,
    nullable: 1
  };
  let create_time = {
    name: 'create_time',
    comment: '创建时间',
    typeName: 'datetime',
    precision: 0,
    scale: 0,
    defaultValue: null,
    primary: -1,
    nullable: 1
  };

  let update_user = {
    name: 'update_by',
    comment: '修改人',
    typeName: 'varchar',
    precision: 64,
    scale: 0,
    defaultValue: null,
    primary: -1,
    nullable: 1
  };

  let update_time = {
    name: 'update_time',
    comment: '修改时间',
    typeName: 'datetime',
    precision: 0,
    scale: 0,
    defaultValue: null,
    primary: -1,
    nullable: 1
  };

  let del_flag = {
    name: 'del_flag',
    comment: '删除标记',
    typeName: 'char',
    precision: 1,
    scale: 0,
    defaultValue: '0',
    primary: -1,
    nullable: -1
  };

  let tenant_id = {
    name: 'tenant_id',
    comment: '租户ID',
    typeName: 'bigint',
    precision: 0,
    scale: 0,
    primary: -1,
    nullable: -1
  };

  form.columns.push(id);
  form.columns.push(create_user);
  form.columns.push(create_time);
  form.columns.push(update_user);
  form.columns.push(update_time);
  form.columns.push(del_flag);
  form.columns.push(tenant_id);
}

const getFieldTypeList = async () => {
  typeList.value = [];
  // 获取数据
  const {data} = await list();
  // 设置属性类型值
  const typeMap = new Map();
  data.forEach((item: any) => {
    const {attrType, columnType} = item;
    if (!typeMap.has(attrType)) {
      typeMap.set(columnType, attrType);
      typeList.value.push({label: columnType, value: columnType});
    }
  });
};

const handleDelete = (index: number, row: any) => {
  form.columns.splice(index, 1)
}

// 字段建议
const suggestedFieldType = (row: { name: string, typeName: string, precision: number }) => {
  // 如果fieldName 包含 time,date  ，则默认为时间类型， 如果包含id ，则默认是 bigint
  if (row.name.includes('time') || row.name.includes('date')) {
    row.typeName = 'datetime'
    row.precision = 0
  } else if (row.name.includes('id')) {
    row.typeName = 'bigint'
    row.precision = 20
  } else if(row.name.includes('flag') || row.name.includes('status')){
    row.typeName = 'char'
    row.precision = 1
  } else {
    row.typeName = 'varchar'
    row.precision = 255
  }
}

// 暴露变量
defineExpose({
  openDialog
});
</script>
