<template>
  <div>
    <div class="page-header">
      <div>
        <h2>数据库管理</h2>
        <p class="subtitle">浏览数据库表结构和数据，支持关键字搜索。仅限私有化部署使用。</p>
      </div>
    </div>

    <div class="db-layout">
      <!-- 左侧：表列表 -->
      <el-card class="table-list-card">
        <template #header>
          <div class="card-header">
            <span>数据表</span>
            <el-button text size="small" :loading="loadingTables" @click="loadTables">
              <el-icon><Refresh /></el-icon>
            </el-button>
          </div>
        </template>
        <el-skeleton v-if="loadingTables" :rows="5" animated />
        <el-empty v-else-if="tables.length === 0" description="暂无数据表" :image-size="48" />
        <div v-else class="table-list">
          <div
            v-for="t in tables"
            :key="t.name"
            class="table-item"
            :class="{ active: activeTable === t.name }"
            @click="selectTable(t.name)"
          >
            <el-icon class="table-icon"><Coin /></el-icon>
            <div class="table-meta">
              <span class="table-name">{{ t.name }}</span>
              <span v-if="t.comment" class="table-comment">{{ t.comment }}</span>
            </div>
          </div>
        </div>
      </el-card>

      <!-- 右侧：数据浏览 -->
      <el-card class="data-card">
        <template v-if="activeTable">
          <div class="data-header">
            <h3 class="data-title">{{ activeTable }}</h3>
            <div class="data-controls">
              <el-input
                v-model="keyword"
                placeholder="搜索关键字..."
                clearable
                style="width: 240px"
                size="default"
                @keyup.enter="doSearch"
              >
                <template #prefix><el-icon><Search /></el-icon></template>
              </el-input>
              <el-button type="primary" @click="doSearch">搜索</el-button>
              <el-button @click="() => { keyword = ''; loadData(0) }">重置</el-button>
              <el-button :loading="loadingData" @click="() => loadData(currentPage)">刷新</el-button>
            </div>
          </div>

          <el-skeleton v-if="loadingData" :rows="8" animated />
          <template v-else>
            <div class="data-status">
              共 {{ total }} 条记录，第 {{ currentPage + 1 }} / {{ totalPages }} 页
            </div>
            <el-table
              :data="rows"
              border
              stripe
              size="small"
              max-height="calc(100vh - 340px)"
              @row-click="showDetail"
              style="cursor: pointer"
            >
              <el-table-column
                v-for="col in displayColumns"
                :key="col"
                :prop="col"
                :label="col"
                :min-width="getColumnWidth(col)"
                show-overflow-tooltip
              >
                <template #default="{ row }">
                  {{ formatCell(row[col]) }}
                </template>
              </el-table-column>
            </el-table>

            <div class="pagination-wrap">
              <el-pagination
                v-model:current-page="currentPage"
                :page-size="pageSize"
                :total="total"
                layout="prev, pager, next, jumper, total"
                @current-change="(p: number) => loadData(p - 1)"
              />
            </div>
          </template>
        </template>
        <template v-else>
          <el-empty description="请从左侧选择一个数据表" :image-size="80" />
        </template>
      </el-card>
    </div>

    <!-- 行详情弹窗 -->
    <el-dialog v-model="detailVisible" title="记录详情" width="600px" destroy-on-close>
      <el-table :data="detailRows" border size="small" :show-header="false">
        <el-table-column prop="field" label="字段" width="180" />
        <el-table-column prop="value" label="值">
          <template #default="{ row }">
            <span class="detail-value">{{ formatCell(row.value) }}</span>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Coin, Refresh, Search } from '@element-plus/icons-vue'
import { listDatabaseTables, getTableData } from '@/api/system'
import type { TableInfo } from '@/api/system'

const tables = ref<TableInfo[]>([])
const loadingTables = ref(false)
const activeTable = ref('')

const keyword = ref('')
const currentPage = ref(0)
const pageSize = ref(50)
const total = ref(0)
const totalPages = ref(0)
const displayColumns = ref<string[]>([])
const rows = ref<Record<string, any>[]>([])
const loadingData = ref(false)

const detailVisible = ref(false)
const detailRows = ref<{ field: string; value: any }[]>([])

// ── 初始化 ──────────────────────────────────────────────────────────────────

onMounted(loadTables)

async function loadTables() {
  loadingTables.value = true
  try {
    tables.value = await listDatabaseTables()
  } catch (e: any) {
    ElMessage.error(e?.message ?? '获取表列表失败')
  } finally {
    loadingTables.value = false
  }
}

// ── 表选择与数据加载 ────────────────────────────────────────────────────────

function selectTable(name: string) {
  activeTable.value = name
  keyword.value = ''
  currentPage.value = 0
  loadData(0)
}

async function loadData(page: number) {
  if (!activeTable.value) return
  loadingData.value = true
  try {
    const data = await getTableData(activeTable.value, {
      page,
      size: pageSize.value,
      keyword: keyword.value || undefined,
    })
    displayColumns.value = data.columns
    rows.value = data.rows
    total.value = data.total
    totalPages.value = data.totalPages
    currentPage.value = data.page
  } catch (e: any) {
    ElMessage.error(e?.message ?? '查询数据失败')
  } finally {
    loadingData.value = false
  }
}

function doSearch() {
  loadData(0)
}

// ── 行详情 ──────────────────────────────────────────────────────────────────

function showDetail(row: Record<string, any>) {
  detailRows.value = displayColumns.value.map(col => ({
    field: col,
    value: row[col],
  }))
  detailVisible.value = true
}

// ── 工具函数 ────────────────────────────────────────────────────────────────

function formatCell(value: any): string {
  if (value === null || value === undefined) return ''
  if (typeof value === 'object') return JSON.stringify(value)
  return String(value)
}

function getColumnWidth(col: string): number {
  if (col === 'id') return 280
  if (col.includes('content') || col.includes('json') || col.includes('text')) return 200
  return 120
}
</script>

<style scoped>
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 16px;
}
.subtitle {
  margin: 6px 0 0;
  color: #606266;
}

.db-layout {
  display: flex;
  gap: 16px;
  min-height: calc(100vh - 200px);
}

.table-list-card {
  width: 280px;
  flex-shrink: 0;
}
.table-list-card :deep(.el-card__body) {
  padding: 0;
}
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.table-list {
  max-height: calc(100vh - 260px);
  overflow-y: auto;
}
.table-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  cursor: pointer;
  border-bottom: 1px solid #f0f0f0;
  transition: background 0.15s;
}
.table-item:hover {
  background: #f5f7fa;
}
.table-item.active {
  background: #ecf5ff;
  color: #409eff;
}
.table-icon {
  flex-shrink: 0;
  color: #909399;
}
.table-item.active .table-icon {
  color: #409eff;
}
.table-meta {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.table-name {
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.table-comment {
  font-size: 11px;
  color: #909399;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.data-card {
  flex: 1;
  min-width: 0;
}
.data-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.data-title {
  margin: 0;
  font-size: 16px;
}
.data-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}
.data-status {
  font-size: 12px;
  color: #909399;
  margin-bottom: 8px;
}

.pagination-wrap {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
}

.detail-value {
  word-break: break-all;
  white-space: pre-wrap;
}

@media (max-width: 767px) {
  .db-layout {
    flex-direction: column;
    min-height: auto;
  }
  .table-list-card {
    width: 100%;
  }
  .table-list {
    max-height: 200px;
  }
  .data-header {
    flex-direction: column;
    align-items: flex-start;
  }
  .data-controls {
    width: 100%;
    flex-wrap: wrap;
  }
}
</style>
