<template>
  <div class="dynamic-map-container">
    <el-row class="header">
      <el-col :span="10">键</el-col>
      <el-col :span="10">值</el-col>
      <el-col :span="4">操作</el-col>
    </el-row>
    <el-row
        v-for="(item, index) in items"
        :key="item.id"
        class="row"
    >
      <el-col :span="10">
        <el-input
            placeholder="请输入键"
            v-model="item.key"
            @input="debouncedEmitUpdate"
        />
      </el-col>
      <el-col :span="10">
        <el-input
            placeholder="请输入值"
            v-model="item.value"
            @input="debouncedEmitUpdate"
        />
      </el-col>
      <el-col :span="4" class="actions">
        <el-button
            type="danger"
            icon="Delete"
            @click="removeItem(index)"
        />
      </el-col>
    </el-row>
    <el-button
        type="primary"
        class="add-btn"
        @click="addNewItem"
    >
      添加新项
    </el-button>
  </div>
</template>

<script setup lang="ts">
import {onBeforeUnmount, ref, watch} from 'vue';
import {debounce} from 'lodash-es';

interface KeyValueItem {
  id: number;
  key: string;
  value: string;
}

const props = defineProps({
  modelValue: {
    type: Object,
    required: true,
    default: () => ({})
  }
});

const emit = defineEmits(['update:modelValue']);

// 用于生成唯一ID
let idCounter = 0;

// 将对象转换为带ID的键值对数组
const initItems = () => {
  return Object.entries(props.modelValue || {})
      .map(([key, value]) => ({
        id: idCounter++,
        key,
        value: String(value)
      }));
};

const items = ref<KeyValueItem[]>(initItems());

// 防抖更新事件
const debouncedEmitUpdate = debounce(() => {
  emit('update:modelValue', arrayToObject(items.value));
}, 300);

// 添加行
const addNewItem = () => {
  items.value.push({
    id: idCounter++,
    key: '',
    value: ''
  });
  emit('update:modelValue', arrayToObject(items.value));
};

// 删除行
const removeItem = (index: number) => {
  items.value.splice(index, 1);
  emit('update:modelValue', arrayToObject(items.value));
};

// 数组转对象（处理重复键）
const arrayToObject = (items: KeyValueItem[]) => {
  return items.reduce((obj, item) => {
    if (item.key) {
      obj[item.key] = item.value;
    }
    return obj;
  }, {} as Record<string, string>);
};

// 监听父组件传入值的变化
watch(() => props.modelValue, (newValue) => {
  const currentKeys = Object.keys(arrayToObject(items.value));
  const newKeys = Object.keys(newValue);

  // 仅在数据实际变化时更新（避免循环更新）
  if (
      newKeys.length !== currentKeys.length ||
      newKeys.some(key => newValue[key] !== arrayToObject(items.value)[key])
  ) {
    items.value = initItems();
  }
}, {deep: true});

// 清除防抖器
onBeforeUnmount(() => {
  debouncedEmitUpdate.cancel();
});
</script>

<style scoped lang="scss">
.dynamic-map-container {
  width: 100%;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  padding: 15px;

  .header {
    font-weight: bold;
    padding: 0 0 10px 0;
    margin-bottom: 8px;
    border-bottom: 1px solid #ebeef5;
  }

  .row {
    margin-bottom: 12px;
  }

  .actions {
    display: flex;
    align-items: center;
    padding-left: 10px;
  }

  .add-btn {
    width: 100%;
    margin-top: 8px;
  }
}
</style>