<template>
  <div class="simple-field-page">
    <el-card v-loading="initializing" shadow="never" class="page-card" element-loading-text="正在加载字段数据…">
      <template #header>
        <div class="page-header">
          <div>
            <h2>字段管理</h2>
            <p>「默认」从 SimpleLite 拉取全部车型字段；「刷新」从数据库读取；「保存」将全部字段写入数据库。</p>
          </div>
          <div class="header-actions">
            <el-button :loading="initializing || loadingDefaults" @click="loadDefaults">默认</el-button>
            <el-button type="primary" :loading="saving" :disabled="initializing || !fieldRows.length" @click="saveAll">保存</el-button>
            <el-button :icon="Refresh" :loading="initializing || loading" @click="loadFromDb()">刷新</el-button>
          </div>
        </div>
      </template>

      <div class="filters">
        <div class="car-type-filter">
          <span class="filter-label">车辆类型：</span>
          <el-select
            v-model="filterCarType"
            filterable
            placeholder="请选择车型"
            class="car-type-select bordered-select"
            popper-class="car-type-option-popper"
          >
            <el-option
              v-for="c in carTypes"
              :key="c.typeName"
              :label="carTypeSelectLabel(c)"
              :value="buildCarType(c.assemblyName, c.shortName)"
            >
              <span class="car-type-option">
                <span class="car-type-option-cn">{{ carTypeCn(c) }}</span>
                <span class="car-type-option-en">({{ buildCarType(c.assemblyName, c.shortName) }})</span>
              </span>
            </el-option>
          </el-select>
        </div>
        <div class="keyword-filter">
          <span class="filter-label">搜索：</span>
          <el-input
            v-model="keyword"
            placeholder="当前车型下搜索属性 / key / 中文 / 英文 / 其他语言"
            clearable
            class="keyword-input"
          />
        </div>
        <el-button type="primary" :disabled="initializing" @click="openDialog()">新增字段</el-button>
      </div>

      <el-tabs v-model="activeCategory" class="field-tabs">
        <el-tab-pane
          v-for="cat in SIMPLE_FIELD_CATEGORIES"
          :key="cat.key"
          :name="cat.key"
          :label="cat.label"
        >
          <el-table
            v-loading="initializing || loading || loadingDefaults"
            :data="filteredRows"
            :row-class-name="searchRowClassName"
            border
            size="small"
            height="520"
          >
            <el-table-column prop="carType" label="车型 (car_type)" min-width="200" />
            <el-table-column prop="key" label="属性" min-width="140" sortable />
            <el-table-column prop="dataType" label="数据类型" min-width="130" sortable />
            <el-table-column prop="value" label="默认值" min-width="100" />
            <el-table-column prop="chinese" label="中文名" min-width="100" />
            <el-table-column prop="english" label="英文名" min-width="100" />
            <el-table-column prop="other" label="其他语言" min-width="100" />
            <el-table-column prop="isDefault" label="默认" width="72" sortable :sort-method="sortByIsDefault">
              <template #default="{ row }">
                <el-tag :type="row.isDefault ? 'info' : 'success'" size="small">{{ row.isDefault ? '是' : '否' }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="150" fixed="right">
              <template #default="{ row }">
                <el-button size="small" @click="openDialog(row)">编辑</el-button>
                <el-button size="small" type="danger" @click="removeRow(row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="520px" destroy-on-close>
      <el-form label-width="96px">
        <el-form-item label="车型" required>
          <el-select
            v-model="form.carType"
            filterable
            :disabled="!!editingRowKey"
            class="bordered-select"
            popper-class="car-type-option-popper"
            style="width: 100%"
          >
            <el-option
              v-for="c in carTypes"
              :key="c.typeName"
              :label="carTypeSelectLabel(c)"
              :value="buildCarType(c.assemblyName, c.shortName)"
            >
              <span class="car-type-option">
                <span class="car-type-option-cn">{{ carTypeCn(c) }}</span>
                <span class="car-type-option-en">({{ buildCarType(c.assemblyName, c.shortName) }})</span>
              </span>
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="字段类型" required>
          <el-select
            v-model="form.fieldType"
            :disabled="!!editingRowKey"
            class="bordered-select"
            style="width: 100%"
          >
            <el-option
              v-for="cat in SIMPLE_FIELD_CATEGORIES"
              :key="cat.key"
              :label="cat.label"
              :value="cat.key"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="属性" required>
          <el-input v-model="form.key" :disabled="!!editingRowKey" placeholder="属性名" />
        </el-form-item>
        <el-form-item label="数据类型" required>
          <el-select
            v-model="form.dataType"
            filterable
            allow-create
            :disabled="!!editingRowKey"
            class="bordered-select"
            style="width: 100%"
          >
            <el-option v-for="t in DATA_TYPE_OPTIONS" :key="t" :label="t" :value="t" />
          </el-select>
        </el-form-item>
        <el-form-item label="默认值" required>
          <el-input v-model="form.value" placeholder="默认值（字符串存储）" />
        </el-form-item>
        <el-form-item label="中文名">
          <el-input v-model="form.chinese" />
        </el-form-item>
        <el-form-item label="英文名">
          <el-input v-model="form.english" />
        </el-form-item>
        <el-form-item label="其他语言">
          <el-input v-model="form.other" placeholder="日语、德语等其他语言名称" />
        </el-form-item>
        <el-form-item v-if="editingRowKey" label="是否内置">
          <el-switch v-model="form.isDefault" class="builtin-switch" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="applyDialog">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import { reflectionApi, type CarTypeCoderFieldsRow, type ReflectionCreatableType } from '@/api/reflection'
import * as simpleFieldApi from '@/api/simpleField'
import {
  SIMPLE_FIELD_CATEGORIES,
  buildCarType,
  type FieldRow,
  type SimpleFieldCategory,
  type SimpleFieldRecord
} from '@/types/simpleField'

const DATA_TYPE_OPTIONS = [
  'System.Boolean',
  'System.Int32',
  'System.Single',
  'System.Double',
  'System.String'
]

const initializing = ref(true)
const loading = ref(false)
const loadingDefaults = ref(false)
const saving = ref(false)
const carTypes = ref<ReflectionCreatableType[]>([])
const fieldRows = ref<FieldRow[]>([])
const filterCarType = ref('')
const activeCategory = ref<SimpleFieldCategory>('siteFields')
const keyword = ref('')
const highlightRowKey = ref('')
const dialogVisible = ref(false)
const editingRowKey = ref('')

const form = reactive({
  carType: '',
  fieldType: 'siteFields' as SimpleFieldCategory,
  key: '',
  value: '',
  dataType: 'System.String',
  chinese: '',
  english: '',
  other: '',
  isDefault: false
})

const dialogTitle = computed(() => (editingRowKey.value ? '编辑字段' : '新增字段'))

const categoryRows = computed(() =>
  rowsForCurrentCar().filter((r) => r.fieldType === activeCategory.value)
)

function rowsForCurrentCar() {
  if (!filterCarType.value) return fieldRows.value
  return fieldRows.value.filter((r) => r.carType === filterCarType.value)
}

function rowMatchesKeyword(row: FieldRow, kw: string) {
  return (
    row.key.toLowerCase().includes(kw) ||
    (row.chinese ?? '').toLowerCase().includes(kw) ||
    (row.english ?? '').toLowerCase().includes(kw) ||
    row.other.toLowerCase().includes(kw) ||
    row.value.toLowerCase().includes(kw) ||
    row.dataType.toLowerCase().includes(kw)
  )
}

function findFirstSearchMatch(kw: string): FieldRow | undefined {
  const rows = rowsForCurrentCar()
  for (const cat of SIMPLE_FIELD_CATEGORIES) {
    const match = rows.find((r) => r.fieldType === cat.key && rowMatchesKeyword(r, kw))
    if (match) return match
  }
  return undefined
}

function searchRowClassName({ row }: { row: FieldRow }) {
  return row.rowKey === highlightRowKey.value ? 'search-hit-row' : ''
}

function sortByIsDefault(a: FieldRow, b: FieldRow) {
  return Number(a.isDefault) - Number(b.isDefault)
}

function scrollToHighlightedRow() {
  nextTick(() => {
    document.querySelector('.field-tabs .search-hit-row')?.scrollIntoView({ block: 'nearest' })
  })
}

function navigateSearchToFirstMatch() {
  const kw = keyword.value.trim().toLowerCase()
  highlightRowKey.value = ''
  if (!kw) return
  const first = findFirstSearchMatch(kw)
  if (!first) return
  activeCategory.value = first.fieldType
  highlightRowKey.value = first.rowKey
  scrollToHighlightedRow()
}

watch([keyword, filterCarType], () => {
  navigateSearchToFirstMatch()
})

const filteredRows = computed(() => {
  const rows = categoryRows.value
  const kw = keyword.value.trim().toLowerCase()
  if (!kw) return rows
  return rows.filter((r) => rowMatchesKeyword(r, kw))
})

function formatValue(v: unknown): string {
  if (v === null || v === undefined) return ''
  if (typeof v === 'object') return JSON.stringify(v)
  return String(v)
}

function makeRowKey(carType: string, fieldType: string, key: string) {
  return `${carType}:${fieldType}:${key}`
}

function recordToRow(r: SimpleFieldRecord): FieldRow {
  return {
    rowKey: makeRowKey(r.carType, r.fieldType, r.key),
    id: r.id,
    carType: r.carType,
    fieldType: r.fieldType as SimpleFieldCategory,
    key: r.key,
    dataType: r.dataType,
    value: r.value,
    chinese: r.chinese,
    english: r.english,
    other: r.other,
    isDefault: r.isDefault
  }
}

function carTypeToRows(car: CarTypeCoderFieldsRow): FieldRow[] {
  const carType = buildCarType(car.assemblyName, car.shortName)
  const rows: FieldRow[] = []
  for (const cat of SIMPLE_FIELD_CATEGORIES) {
    const group = car[cat.key]
    for (const f of group?.fields ?? []) {
      rows.push({
        rowKey: makeRowKey(carType, cat.key, f.name),
        carType,
        fieldType: cat.key,
        key: f.name,
        dataType: f.typeName,
        value: formatValue(f.defaultValue),
        chinese: '',
        english: '',
        other: '',
        isDefault: true
      })
    }
  }
  return rows
}

function allCarsToRows(cars: CarTypeCoderFieldsRow[]): FieldRow[] {
  return cars.flatMap(carTypeToRows)
}

/** 从已加载的数据库记录推导车型下拉（不请求 SimpleLite）。 */
function syncCarTypesFromFieldRows() {
  const labelByKey = new Map(
    carTypes.value.map((c) => [buildCarType(c.assemblyName, c.shortName), c.label])
  )
  const seen = new Set<string>()
  const options: ReflectionCreatableType[] = []
  for (const r of fieldRows.value) {
    if (seen.has(r.carType)) continue
    seen.add(r.carType)
    const carType = r.carType
    const dot = carType.lastIndexOf('.')
    const assemblyName = dot >= 0 ? carType.slice(0, dot) : ''
    const shortName = dot >= 0 ? carType.slice(dot + 1) : carType
    options.push({
      typeName: carType,
      shortName,
      label: labelByKey.get(carType) || shortName,
      assemblyName
    })
  }
  carTypes.value = options
}

/** 从 SimpleLite 补全车型中文名（轻量接口，不拉字段定义）。 */
async function enrichCarTypeLabels() {
  try {
    const types = await reflectionApi.listCreatableTypes('car')
    const labelMap = new Map(
      types.map((t) => [buildCarType(t.assemblyName, t.shortName), t.label || t.shortName])
    )
    carTypes.value = carTypes.value.map((c) => {
      const key = buildCarType(c.assemblyName, c.shortName)
      const label = labelMap.get(key)
      return label ? { ...c, label } : c
    })
  } catch {
    /* SimpleLite 未连接时保留现有显示 */
  }
}

function ensureDefaultCarType() {
  if (filterCarType.value) return
  if (carTypes.value.length) {
    const first = carTypes.value[0]
    filterCarType.value = buildCarType(first.assemblyName, first.shortName)
  } else if (fieldRows.value.length) {
    filterCarType.value = fieldRows.value[0].carType
  }
}

function carTypeCn(c: ReflectionCreatableType) {
  if (c.label && c.label !== c.shortName) return c.label
  return c.label || c.shortName
}

function carTypeSelectLabel(c: ReflectionCreatableType, fullCarType = true) {
  const en = fullCarType ? buildCarType(c.assemblyName, c.shortName) : c.shortName
  return `${carTypeCn(c)} (${en})`
}

async function loadFromDb(silent = false) {
  loading.value = true
  try {
    const records = await simpleFieldApi.listSimpleFields()
    fieldRows.value = records.map(recordToRow)
    syncCarTypesFromFieldRows()
    await enrichCarTypeLabels()
    ensureDefaultCarType()
    if (!silent) ElMessage.success(`已从数据库加载 ${fieldRows.value.length} 条字段`)
  } catch (e) {
    fieldRows.value = []
    carTypes.value = []
    ElMessage.error(e instanceof Error ? e.message : '从数据库加载失败')
  } finally {
    loading.value = false
  }
}

async function loadDefaults() {
  loadingDefaults.value = true
  try {
    const cars = await reflectionApi.getCarTypeCoderFields()
    if (!cars.length) {
      ElMessage.warning('未获取到车型列表，请确认 SimpleLite 已启动')
      return
    }
    carTypes.value = cars.map((c) => ({
      typeName: c.typeName,
      shortName: c.shortName,
      label: c.label,
      assemblyName: c.assemblyName
    }))
    ensureDefaultCarType()
    fieldRows.value = allCarsToRows(cars)
    ElMessage.success(`已从 SimpleLite 加载 ${cars.length} 种车型、共 ${fieldRows.value.length} 条默认字段（请点击保存写入数据库）`)
  } catch (e) {
    ElMessage.error(e instanceof Error ? e.message : '加载默认字段失败')
  } finally {
    loadingDefaults.value = false
  }
}

async function saveAll() {
  if (!fieldRows.value.length) return
  saving.value = true
  try {
    const { count } = await simpleFieldApi.saveSimpleFieldsBatch({
      replaceAll: true,
      items: fieldRows.value.map((r) => ({
        carType: r.carType,
        fieldType: r.fieldType,
        key: r.key,
        value: r.value,
        dataType: r.dataType,
        chinese: r.chinese ?? '',
        english: r.english ?? '',
        other: r.other,
        isDefault: r.isDefault
      }))
    })
    ElMessage.success(`已保存 ${count} 条字段到数据库`)
    await loadFromDb(true)
  } catch (e) {
    ElMessage.error(e instanceof Error ? e.message : '保存失败')
  } finally {
    saving.value = false
  }
}

function resetForm() {
  editingRowKey.value = ''
  form.carType = filterCarType.value
    || (carTypes.value[0] ? buildCarType(carTypes.value[0].assemblyName, carTypes.value[0].shortName) : '')
  form.fieldType = activeCategory.value
  form.key = ''
  form.value = ''
  form.dataType = 'System.String'
  form.chinese = ''
  form.english = ''
  form.other = ''
  form.isDefault = false
}

function openDialog(row?: FieldRow) {
  resetForm()
  if (row) {
    editingRowKey.value = row.rowKey
    form.carType = row.carType
    form.fieldType = row.fieldType
    form.key = row.key
    form.value = row.value
    form.dataType = row.dataType
    form.chinese = row.chinese ?? ''
    form.english = row.english ?? ''
    form.other = row.other
    form.isDefault = row.isDefault
  }
  dialogVisible.value = true
}

function applyDialog() {
  if (!form.carType.trim()) {
    ElMessage.warning('请选择车型')
    return
  }
  if (!form.key.trim()) {
    ElMessage.warning('请填写属性')
    return
  }
  if (!form.dataType.trim()) {
    ElMessage.warning('请选择数据类型')
    return
  }
  if (!form.value.trim()) {
    ElMessage.warning('请填写默认值')
    return
  }
  const rowKey = makeRowKey(form.carType.trim(), form.fieldType, form.key.trim())
  const payload: FieldRow = {
    rowKey,
    carType: form.carType.trim(),
    fieldType: form.fieldType,
    key: form.key.trim(),
    dataType: form.dataType,
    value: form.value,
    chinese: form.chinese,
    english: form.english,
    other: form.other,
    isDefault: editingRowKey.value ? form.isDefault : false,
  }
  if (editingRowKey.value) {
    const idx = fieldRows.value.findIndex((r) => r.rowKey === editingRowKey.value)
    if (idx >= 0) {
      fieldRows.value[idx] = {
        ...fieldRows.value[idx],
        value: form.value,
        chinese: form.chinese,
        english: form.english,
        other: form.other,
        isDefault: form.isDefault
      }
    }
  } else {
    if (fieldRows.value.some((r) => r.rowKey === rowKey)) {
      ElMessage.warning('该车型下该字段已存在')
      return
    }
    fieldRows.value.push(payload)
  }
  activeCategory.value = form.fieldType
  dialogVisible.value = false
}

async function removeRow(row: FieldRow) {
  await ElMessageBox.confirm(`确定删除字段「${row.carType} / ${row.key}」？`, '确认', { type: 'warning' })
  fieldRows.value = fieldRows.value.filter((r) => r.rowKey !== row.rowKey)
}

onMounted(async () => {
  initializing.value = true
  try {
    await loadFromDb(true)
  } catch (e) {
    ElMessage.error(e instanceof Error ? e.message : '初始化失败')
  } finally {
    initializing.value = false
  }
})
</script>

<style scoped>
.simple-field-page {
  padding: 10px 12px;
  height: calc(100vh - 56px);
  overflow: auto;
  box-sizing: border-box;
}
.page-card {
  min-height: calc(100vh - 88px);
  border: 1px solid rgba(40, 33, 58, 0.10) !important;
  border-radius: 8px !important;
  box-shadow: none !important;
  background: #fffefd !important;
}
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.page-header h2 { margin: 0 0 2px; font-size: 15px; font-weight: 650; }
.page-header p { margin: 0; color: var(--el-text-color-secondary); font-size: 12px; }
.header-actions { display: flex; gap: 6px; flex-shrink: 0; }
.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  padding: 8px 10px;
  border: 1px solid rgba(40, 33, 58, 0.08);
  border-radius: 8px;
  background: rgba(246, 243, 251, 0.65);
}
.car-type-filter,
.keyword-filter {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.filter-label {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  height: 32px;
  margin: 0;
  font-size: 14px;
  line-height: 1;
  color: var(--el-text-color-regular);
  white-space: nowrap;
}
.car-type-select {
  width: 480px;
}
.car-type-select :deep(.el-select__selected-item),
.car-type-select :deep(.el-select__placeholder) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.keyword-input {
  width: 400px;
}
.bordered-select :deep(.el-select__wrapper) {
  min-height: 32px;
  background-color: #fff !important;
  border: 1px solid #dcdfe6 !important;
  border-radius: var(--el-border-radius-base, 4px);
  box-shadow: none !important;
}
.bordered-select :deep(.el-select__wrapper:hover) {
  border-color: #c0c4cc !important;
  box-shadow: none !important;
}
.bordered-select :deep(.el-select__wrapper.is-focused),
.bordered-select :deep(.el-select__wrapper.is-hovering.is-focused) {
  border-color: var(--el-color-primary, #7c3aed) !important;
  box-shadow: 0 0 0 1px var(--el-color-primary, #7c3aed) inset !important;
}
.bordered-select :deep(.el-select__selected-item),
.bordered-select :deep(.el-select__placeholder) {
  line-height: 30px;
}
.field-tabs { margin-top: 2px; }
.field-tabs :deep(.el-tabs__item) {
  height: 34px;
  line-height: 34px;
  font-size: 13px;
}
.field-tabs :deep(.el-tabs__item.is-active) { font-weight: 700; }
.page-card :deep(.el-card__header) {
  padding: 10px 14px;
  border-bottom: 1px solid rgba(40, 33, 58, 0.08);
}
.page-card :deep(.el-card__body) { padding: 12px 14px; }
.page-card :deep(.el-table .cell) {
  font-variant-numeric: tabular-nums;
}
.field-tabs :deep(.search-hit-row > td.el-table__cell) {
  background-color: #f5f3ff !important;
}
.builtin-switch :deep(.el-switch__core) {
  border: 1px solid #c0c4cc;
  background-color: #dcdfe6 !important;
}
.builtin-switch.is-checked :deep(.el-switch__core) {
  background-color: var(--el-color-primary, #7c3aed) !important;
  border-color: var(--el-color-primary, #7c3aed) !important;
}
.builtin-switch :deep(.el-switch__action) {
  background-color: #fff;
}
</style>

<style>
.car-type-option-popper {
  min-width: 520px !important;
}
.car-type-option-popper .car-type-option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-width: 0;
}
.car-type-option-popper .car-type-option-cn {
  flex: 0 0 auto;
  max-width: 11em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.car-type-option-popper .car-type-option-en {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--el-text-color-secondary);
}
</style>
