<template>
  <div class="json-table-input" ref="tableContainer">
    <!-- JSON 解析错误提示 -->
    <div v-if="error" class="error-tip">
      <i class="el-icon-warning"></i> {{ error }}
    </div>

    <!-- 表格编辑区域 -->
    <el-table :data="tableData" border size="mini" :show-header="columns.length > 0" class="table-container">
      <!-- 动态渲染列 -->
      <el-table-column v-for="col in columns" :key="col.prop" :label="col.label" :width="col.width">
        <template slot-scope="scope">
          <!-- 新增聚焦/失焦事件，全局记录聚焦状态 -->
          <el-input v-model="scope.row[col.prop]" size="mini" @input="handleCellChange" @focus="handleInputFocus"
            @blur="handleInputBlur" placeholder="请输入" />
        </template>
      </el-table-column>

      <!-- 操作列：删除行（空行不可删） -->
      <el-table-column label="操作" width="90">
        <template slot-scope="scope">
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDeleteRow(scope.$index)"
            :disabled="isLastEmptyRow(scope.$index)">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 原始 JSON 预览（可选，方便调试） -->
    <div class="json-preview" v-if="showPreview">
      <div class="preview-label">JSON 预览（自动格式化）：</div>
      <pre>{{ formattedJson }}</pre>
    </div>
  </div>
</template>

<script>
export default {
  name: 'JSONTableInput',
  props: {
    // 双向绑定的值（JSON 数组字符串 / JSON 数组对象）
    value: {
      type: [String, Array],
      default: '[]'
    },
    // 表格列配置：[{ prop: 'name', label: '姓名', width: 150 }, ...]
    columns: {
      type: Array,
      required: true,
      default: () => []
    },
    // 是否显示 JSON 预览（默认关闭）
    showPreview: {
      type: Boolean,
      default: false
    },
    // 防抖延迟（ms）：所有输入停止 + 无输入框聚焦 后触发更新
    debounceDelay: {
      type: Number,
      default: 500 // 默认500ms防抖
    }
  },
  data() {
    return {
      tableData: [], // 表格内部数据
      error: '', // JSON 解析错误提示
      debounceTimer: null, // 组件级防抖定时器（所有input共用）
      hasFocus: false // 全局标记：是否有任意input处于聚焦状态
    }
  },
  computed: {
    // 格式化后的 JSON 字符串（输出给 v-model）
    formattedJson() {
      try {
        // 过滤空行（所有字段为空的行）
        const validData = this.tableData.filter(row => this.isRowValid(row))
        // 格式化 JSON（缩进2个空格，保证可读性）
        return JSON.stringify(validData, null, 2)
      } catch (e) {
        this.error = 'JSON 格式化失败：' + e.message
        return '[]'
      }
    }
  },
  watch: {
    // 监听外部传入的 value 变化，解析为表格数据
    value: {
      immediate: true,
      handler(val) {
        this.parseValueToTableData(val)
      }
    },
    // 监听聚焦状态变化：当失去所有焦点时，触发防抖检查
    hasFocus(newVal) {
      if (!newVal) {
        this.triggerDebounceChange()
      }
    }
  },
  beforeDestroy() {
    // 销毁时清除防抖定时器，防止内存泄漏
    if (this.debounceTimer) clearTimeout(this.debounceTimer)
  },
  methods: {
    /**
     * 解析外部传入的 value 为表格数据
     * @param {String|Array} val - 外部绑定的 value
     */
    parseValueToTableData(val) {
      try {
        this.error = ''
        let data = []
        // 1. 如果是字符串，解析为 JSON 数组
        if (typeof val === 'string') {
          data = val.trim() ? JSON.parse(val) : []
        }
        // 2. 如果是数组，直接使用
        else if (Array.isArray(val)) {
          data = [...val]
        }
        // 校验是否为数组
        if (!Array.isArray(data)) {
          throw new Error('数据必须是 JSON 数组')
        }
        // 3. 赋值并确保空行
        this.tableData = data
        this.ensureEmptyRow()
      } catch (e) {
        this.error = 'JSON 解析失败：' + e.message
        this.tableData = []
        this.ensureEmptyRow()
      }
    },

    /**
     * 确保表格最后一行是空行
     */
    ensureEmptyRow() {
      if (this.tableData.length === 0) {
        // 无数据时添加空行
        this.tableData.push(this.createEmptyRow())
      } else {
        const lastRow = this.tableData[this.tableData.length - 1]
        // 最后一行非空时，添加空行
        if (this.isRowValid(lastRow)) {
          this.tableData.push(this.createEmptyRow())
        }
      }
    },

    /**
     * 创建空行（字段与列配置一致）
     */
    createEmptyRow() {
      const emptyRow = {}
      this.columns.forEach(col => {
        emptyRow[col.prop] = ''
      })
      return emptyRow
    },

    /**
     * 判断行是否有效（非空行）
     * @param {Object} row - 表格行数据
     */
    isRowValid(row) {
      return this.columns.some(col => {
        const val = row[col.prop]
        return val !== '' && val !== null && val !== undefined
      })
    },

    /**
     * 判断是否是最后一行空行（用于禁用删除按钮）
     * @param {Number} index - 行索引
     */
    isLastEmptyRow(index) {
      return index === this.tableData.length - 1 && !this.isRowValid(this.tableData[index])
    },

    /**
     * 单元格内容变化（仅更新表格数据，触发防抖更新）
     */
    handleCellChange() {
      // 确保始终保留一个空行
      this.ensureEmptyRow()
      // 触发防抖更新（跨input输入时，重置同一个定时器）
      this.triggerDebounceChange()
    },

    /**
     * 任意input聚焦：标记全局聚焦状态
     */
    handleInputFocus() {
      this.hasFocus = true
      // 聚焦时清除防抖定时器（用户还在输入，不触发更新）
      if (this.debounceTimer) {
        clearTimeout(this.debounceTimer)
        this.debounceTimer = null
      }
    },

    /**
     * 任意input失焦：延迟判断是否真的无聚焦（避免切换input误触发）
     */
    handleInputBlur() {
      // 延迟 100ms 检查聚焦状态（切换input时，新input的focus会先触发）
      setTimeout(() => {
        try {
          // 1. 获取表格内所有 el-input 的原生 input 元素
          const tableEl = this.$refs.tableContainer;
          if (!tableEl) {
            this.hasFocus = false;
            return;
          }
          const inputs = tableEl.querySelectorAll('.el-input__inner'); // 精准匹配 Element UI 输入框

          console.log('所有输入框:', inputs)
          // 2. 判断是否有任意输入框处于聚焦状态
          const hasAnyFocus = Array.from(inputs).some(input => {
            // 核心：判断当前输入框是否是文档的激活元素
            console.log('当前激活元素:', document.activeElement === input)
            return input === document.activeElement;
          });

          // 3. 只有无任何输入框聚焦时，才标记全局失焦
          this.hasFocus = hasAnyFocus;
        } catch (e) {
          // 异常兜底：标记为失焦
          this.hasFocus = false;
        }
      }, 100);
    },

    /**
     * 删除指定行
     * @param {Number} index - 行索引
     */
    handleDeleteRow(index) {
      if (this.isLastEmptyRow(index)) return // 空行不可删
      this.tableData.splice(index, 1)
      this.ensureEmptyRow() // 删除后重新检查空行
      // 删除后立即触发更新（用户主动操作，无需防抖）
      this.emitUpdate()
    },

    /**
     * 防抖触发更新：仅当「无输入框聚焦 + 防抖超时」时触发
     */
    triggerDebounceChange() {
      // 若还有输入框聚焦，直接返回（用户还在输入）
      if (this.hasFocus) return

      // 清除原有定时器（重置计时）
      if (this.debounceTimer) clearTimeout(this.debounceTimer)
      // 设置新定时器，延迟触发更新
      this.debounceTimer = setTimeout(() => {
        this.emitUpdate()
        this.debounceTimer = null // 清空定时器标识
      }, this.debounceDelay)
    },

    /**
     * 统一触发更新父组件的逻辑
     */
    emitUpdate() {
      // 触发 input（双向绑定）和 change（通知父组件）
      this.$emit('input', this.formattedJson)
      this.$emit('change', this.formattedJson)
    }
  }
}
</script>

<style scoped>
.json-table-input {
  width: 100%;
  box-sizing: border-box;
}

.error-tip {
  color: #f56c6c;
  font-size: 12px;
  margin-bottom: 8px;
  padding: 4px 8px;
  background: #fef0f0;
  border-radius: 4px;
  display: flex;
  align-items: center;
}

.error-tip i {
  margin-right: 4px;
}

.table-container {
  margin-bottom: 12px;
}

.json-preview {
  background: #f5f7fa;
  padding: 8px;
  border-radius: 4px;
  font-size: 12px;
}

.json-preview .preview-label {
  color: #606266;
  margin-bottom: 4px;
}

.json-preview pre {
  margin: 0;
  color: #303133;
  white-space: pre-wrap;
  word-wrap: break-word;
}
</style>