<template>
  <div class="designer">
    <aside class="table-list">
      <div class="list-head">
        <strong>数据表</strong>
        <el-button :icon="Plus" circle @click="addTable" />
      </div>
      <el-empty v-if="!tables.length" description="暂无表结构" :image-size="88" />
      <button
        v-for="(table, index) in tables"
        v-else
        :key="table.tableId || table.id || index"
        class="table-item"
        :class="{ active: selectedIndex === index }"
        type="button"
        @click="selectedIndex = index"
      >
        <span>{{ table.tableName || '未命名表' }}</span>
        <small>{{ table.tableComment || '未填写备注' }}</small>
      </button>
    </aside>

    <section class="table-editor">
      <el-empty v-if="!currentTable" description="添加或选择一张数据表" />
      <template v-else>
        <div class="table-form">
          <el-form label-position="top">
            <el-row :gutter="16">
              <el-col :xs="24" :md="10">
                <el-form-item label="表名">
                  <el-input v-model="currentTable.tableName" placeholder="例如 sys_customer" />
                </el-form-item>
              </el-col>
              <el-col :xs="24" :md="10">
                <el-form-item label="备注">
                  <el-input v-model="currentTable.tableComment" placeholder="例如 客户信息表" />
                </el-form-item>
              </el-col>
              <el-col :xs="24" :md="4" class="delete-col">
                <el-button :icon="Delete" type="danger" plain @click="removeTable(selectedIndex)">
                  删除表
                </el-button>
              </el-col>
            </el-row>
          </el-form>
        </div>

        <div class="field-head">
          <h3>字段设计</h3>
          <el-button type="primary" :icon="Plus" @click="addField">添加字段</el-button>
        </div>

        <el-table :data="currentColumns" border>
          <el-table-column label="字段名" min-width="160">
            <template #default="{ row }">
              <el-input v-model="row.columnName" placeholder="字段名" />
            </template>
          </el-table-column>
          <el-table-column label="类型" width="160">
            <template #default="{ row }">
              <el-select v-model="row.columnType" placeholder="字段类型">
                <el-option label="varchar(255)" value="varchar(255)" />
                <el-option label="bigint(20)" value="bigint(20)" />
                <el-option label="int(11)" value="int(11)" />
                <el-option label="decimal(10,2)" value="decimal(10,2)" />
                <el-option label="datetime" value="datetime" />
                <el-option label="text" value="text" />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column label="备注" min-width="180">
            <template #default="{ row }">
              <el-input v-model="row.columnComment" placeholder="字段备注" />
            </template>
          </el-table-column>
          <el-table-column label="主键" width="90" align="center">
            <template #default="{ row }">
              <el-checkbox :model-value="row.isPk === '1'" @change="(checked) => row.isPk = checked ? '1' : '0'" />
            </template>
          </el-table-column>
          <el-table-column label="必填" width="90" align="center">
            <template #default="{ row }">
              <el-checkbox :model-value="row.isRequired === '1'" @change="(checked) => row.isRequired = checked ? '1' : '0'" />
            </template>
          </el-table-column>
          <el-table-column label="操作" width="90" align="center">
            <template #default="{ $index }">
              <el-button :icon="Delete" circle text type="danger" @click="removeField($index)" />
            </template>
          </el-table-column>
        </el-table>
      </template>
    </section>
  </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import { Delete, Plus } from '@element-plus/icons-vue'

const props = defineProps({
  modelValue: {
    type: Object,
    default: () => ({ tables: [], sql: '' })
  }
})

const emit = defineEmits(['update:modelValue'])
const selectedIndex = ref(0)

const database = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

const tables = computed(() => database.value.tables || [])
const currentTable = computed(() => tables.value[selectedIndex.value])
const currentColumns = computed(() => {
  if (!currentTable.value) return []
  if (!Array.isArray(currentTable.value.columns)) {
    currentTable.value.columns = []
  }
  return currentTable.value.columns
})

watch(
  () => tables.value.length,
  (length) => {
    if (selectedIndex.value >= length) {
      selectedIndex.value = Math.max(length - 1, 0)
    }
  }
)

watch(
  tables,
  (nextTables) => {
    nextTables.forEach(normalizeTable)
  },
  { deep: true, immediate: true }
)

function toPascalCase(value) {
  return String(value || '')
    .split(/[^A-Za-z0-9]+|_/)
    .filter(Boolean)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join('')
}

function toCamelCase(value) {
  const pascal = toPascalCase(value)
  return pascal ? pascal.charAt(0).toLowerCase() + pascal.slice(1) : ''
}

function javaTypeOf(columnType) {
  const normalized = String(columnType || '').toLowerCase()
  if (normalized.startsWith('bigint')) return 'Long'
  if (normalized.startsWith('int')) return 'Integer'
  if (normalized.startsWith('decimal')) return 'BigDecimal'
  if (normalized === 'datetime' || normalized === 'date') return 'Date'
  return 'String'
}

function normalizeTable(table) {
  if (!table) return
  table.className = toPascalCase(table.tableName)
  table.moduleName = table.moduleName || 'system'
  table.businessName = toCamelCase(table.tableName)
  table.functionName = table.tableComment || table.tableName
  table.tplCategory = table.tplCategory || 'crud'
  table.tplWebType = table.tplWebType || 'element-plus'

  const columns = Array.isArray(table.columns) ? table.columns : []
  columns.forEach((column) => normalizeColumn(column))
}

function normalizeColumn(column) {
  if (!column) return
  column.javaField = toCamelCase(column.columnName)
  column.javaType = javaTypeOf(column.columnType)
  column.isPk = column.isPk === '1' ? '1' : '0'
  column.isIncrement = column.isIncrement === '1' ? '1' : '0'
  column.isRequired = column.isRequired === '1' ? '1' : '0'
  column.isInsert = column.isInsert || '1'
  column.isEdit = column.isEdit || '1'
  column.isList = column.isList || '1'
  column.isQuery = column.isQuery || '0'
  column.queryType = column.queryType || 'EQ'
  column.htmlType = column.htmlType || 'input'
}

function uid(prefix) {
  return `${prefix}_${Date.now()}_${Math.random().toString(16).slice(2)}`
}

function updateTables(nextTables) {
  database.value = { ...database.value, tables: nextTables }
}

function addTable() {
  const nextTables = [
    ...tables.value,
    {
      id: uid('table'),
      tableName: 'new_table',
      tableComment: '新建数据表',
      className: 'NewTable',
      moduleName: 'system',
      businessName: 'newTable',
      functionName: '新建数据',
      tplCategory: 'crud',
      tplWebType: 'element-plus',
      columns: [
        {
          id: uid('field'),
          columnName: 'id',
          columnType: 'bigint(20)',
          columnComment: '主键',
          javaType: 'Long',
          javaField: 'id',
          isPk: '1',
          isIncrement: '1',
          isRequired: '1',
          isInsert: '1',
          isEdit: '1',
          isList: '1',
          isQuery: '0',
          queryType: 'EQ',
          htmlType: 'input'
        }
      ]
    }
  ]
  updateTables(nextTables)
  selectedIndex.value = nextTables.length - 1
}

function removeTable(index) {
  updateTables(tables.value.filter((_, itemIndex) => itemIndex !== index))
}

function addField() {
  if (!currentTable.value) return
  currentColumns.value.push({
    id: uid('field'),
    columnName: '',
    columnType: 'varchar(255)',
    columnComment: '',
    javaType: 'String',
    javaField: '',
    isPk: '0',
    isIncrement: '0',
    isRequired: '0',
    isInsert: '1',
    isEdit: '1',
    isList: '1',
    isQuery: '0',
    queryType: 'EQ',
    htmlType: 'input'
  })
}

function removeField(index) {
  if (!currentTable.value) return
  currentColumns.value.splice(index, 1)
}
</script>

<style scoped lang="scss">
.designer {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: 430px;
}

.table-list {
  border-right: 1px solid #e3e8f0;
  background: #f8fafc;
}

.list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
  border-bottom: 1px solid #e3e8f0;
}

.table-item {
  display: flex;
  width: calc(100% - 20px);
  flex-direction: column;
  gap: 5px;
  margin: 10px;
  padding: 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  color: #344054;
  background: transparent;
  text-align: left;
  cursor: pointer;

  span {
    font-weight: 700;
  }

  small {
    color: #667085;
  }

  &.active {
    border-color: #9bbcf5;
    background: #eef5ff;
    color: #1d4ed8;
  }
}

.table-editor {
  min-width: 0;
  padding: 18px;
}

.delete-col {
  display: flex;
  align-items: flex-start;
  padding-top: 30px;
}

.field-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 4px 0 14px;

  h3 {
    margin: 0;
    font-size: 16px;
  }
}

@media (max-width: 860px) {
  .designer {
    grid-template-columns: 1fr;
  }

  .table-list {
    border-right: 0;
    border-bottom: 1px solid #e3e8f0;
  }

  .delete-col {
    padding-top: 0;
  }
}
</style>
