<template>
  <el-dialog
    :model-value="open"
    title="选择字段增加"
    width="520px"
    append-to-body
    destroy-on-close
    class="better-add-field-dialog"
    @update:model-value="onOpenChange"
  >
    <p class="baf-hint">
      目标：{{ targetSummary }}。选择场景已有字段，再输入要批量写入的值（对齐 Ctrl+I）。
    </p>
    <el-input
      v-model="search"
      clearable
      placeholder="搜索字段名"
      class="baf-search"
    />
    <div v-loading="loadingKeys" class="baf-list">
      <button
        v-for="key in filteredKeys"
        :key="key"
        type="button"
        class="baf-key"
        :class="{ 'is-active': key === pickedKey }"
        @click="pickedKey = key"
      >
        {{ key }}
      </button>
      <div v-if="!loadingKeys && filteredKeys.length === 0" class="baf-empty">
        {{ keys.length === 0 ? '当前场景还没有任何自定义字段可选' : '无匹配字段' }}
      </div>
    </div>
    <el-input
      v-model="value"
      :disabled="!pickedKey"
      :placeholder="pickedKey ? `输入字段 ${pickedKey} 的值` : '先选择字段'"
      class="baf-value"
      @keydown.enter.prevent="confirm"
    />
    <template #footer>
      <el-button @click="close">取消</el-button>
      <el-button type="primary" :loading="applying" :disabled="!pickedKey" @click="confirm">
        写入选中对象
      </el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { mapEditApi } from '@/api/mapEdit'

const props = defineProps<{
  open: boolean
  targets: Array<{ kind: string; id: number }>
  targetSummary: string
}>()

const emit = defineEmits<{
  'update:open': [v: boolean]
  applied: [payload: { key: string; value: string; affected: number }]
}>()

const keys = ref<string[]>([])
const loadingKeys = ref(false)
const search = ref('')
const pickedKey = ref('')
const value = ref('')
const applying = ref(false)

const filteredKeys = computed(() => {
  const q = search.value.trim().toLowerCase()
  if (!q) return keys.value
  return keys.value.filter((k) => k.toLowerCase().includes(q))
})

watch(
  () => props.open,
  async (v) => {
    if (!v) return
    search.value = ''
    pickedKey.value = ''
    value.value = ''
    loadingKeys.value = true
    try {
      const r = await mapEditApi.sceneFieldKeys()
      keys.value = r.keys ?? []
    } catch (err) {
      keys.value = []
      ElMessage.error(`加载字段列表失败：${(err as Error).message}`)
    } finally {
      loadingKeys.value = false
    }
  }
)

function onOpenChange(v: boolean) {
  emit('update:open', v)
}

function close() {
  emit('update:open', false)
}

async function confirm() {
  if (!pickedKey.value || props.targets.length === 0) return
  applying.value = true
  try {
    const r = await mapEditApi.batchSetField(pickedKey.value, value.value, props.targets)
    ElMessage.success(`已对 ${r.affected}/${props.targets.length} 个对象设置 ${pickedKey.value}`)
    emit('applied', { key: pickedKey.value, value: value.value, affected: r.affected })
    close()
  } catch (err) {
    ElMessage.error(`写入失败：${(err as Error).message}`)
  } finally {
    applying.value = false
  }
}
</script>

<style scoped>
.baf-hint {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--el-text-color-secondary);
}
.baf-search { margin-bottom: 10px; width: 100%; }
.baf-list {
  min-height: 180px;
  max-height: 280px;
  overflow: auto;
  border: 1px solid var(--el-border-color);
  border-radius: 8px;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 12px;
}
.baf-key {
  appearance: none;
  border: 0;
  background: transparent;
  text-align: left;
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 13px;
  color: var(--el-text-color-primary);
  cursor: pointer;
}
.baf-key:hover { background: var(--el-fill-color-light); }
.baf-key.is-active {
  background: var(--el-color-primary-light-9);
  color: var(--el-color-primary);
  font-weight: 600;
}
.baf-empty {
  padding: 28px 12px;
  text-align: center;
  font-size: 13px;
  color: var(--el-text-color-secondary);
}
.baf-value { width: 100%; }
</style>
