<template>
  <div class="tree-node">
    <template v-if="isObject">
      <div class="node-bracket">{</div>
      <div class="node-children">
        <div v-for="(value, key) in data" :key="key" class="node-item">
          <span class="node-key">"{{ key }}"</span>
          <span class="node-colon">:</span>
          <JsonTreeNode
            :data="value"
            :path="buildPath(key)"
            :fields="fields"
            :selected-paths="selectedPaths"
            @select="$emit('select', $event)"
          />
          <span v-if="!isLastKey(key)" class="node-comma">,</span>
        </div>
      </div>
      <div class="node-bracket">}</div>
    </template>
    
    <template v-else-if="isArray">
      <div class="node-bracket">[</div>
      <div class="node-children">
        <div v-for="(item, index) in data" :key="index" class="node-item">
          <span class="array-index">[{{ index }}]</span>
          <JsonTreeNode
            :data="item"
            :path="buildArrayPath(index)"
            :fields="fields"
            :selected-paths="selectedPaths"
            @select="$emit('select', $event)"
          />
          <span v-if="index < data.length - 1" class="node-comma">,</span>
        </div>
      </div>
      <div class="node-bracket">]</div>
    </template>
    
    <template v-else>
      <span 
        class="node-value" 
        :class="[valueType, { selected: isSelected, clickable: true }]"
        @click="handleClick"
        :title="'点击选择: ' + path"
      >
        <template v-if="isString">"{{ data }}"</template>
        <template v-else-if="isNull">null</template>
        <template v-else>{{ data }}</template>
        <span v-if="isSelected" class="selected-badge">{{ selectedFieldLabel }}</span>
      </span>
    </template>
  </div>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  data: {
    type: [Object, Array, String, Number, Boolean, null],
    default: null
  },
  path: {
    type: String,
    default: ''
  },
  fields: {
    type: Array,
    default: () => []
  },
  selectedPaths: {
    type: Object,
    default: () => ({})
  }
})

const emit = defineEmits(['select'])

const isObject = computed(() => {
  return props.data !== null && typeof props.data === 'object' && !Array.isArray(props.data)
})

const isArray = computed(() => {
  return Array.isArray(props.data)
})

const isString = computed(() => {
  return typeof props.data === 'string'
})

const isNull = computed(() => {
  return props.data === null
})

const valueType = computed(() => {
  if (props.data === null) return 'null'
  if (typeof props.data === 'string') return 'string'
  if (typeof props.data === 'number') return 'number'
  if (typeof props.data === 'boolean') return 'boolean'
  return 'unknown'
})

const isSelected = computed(() => {
  return Object.values(props.selectedPaths).includes(props.path)
})

const selectedFieldLabel = computed(() => {
  for (const [key, value] of Object.entries(props.selectedPaths)) {
    if (value === props.path) {
      const field = props.fields.find(f => f.key === key)
      return field ? field.label.split(' ')[0] : key
    }
  }
  return ''
})

const buildPath = (key) => {
  return props.path ? `${props.path}.${key}` : key
}

const buildArrayPath = (index) => {
  return `${props.path}[${index}]`
}

const isLastKey = (key) => {
  const keys = Object.keys(props.data)
  return keys[keys.length - 1] === key
}

const handleClick = () => {
  if (props.path) {
    emit('select', { path: props.path, value: props.data })
  }
}
</script>

<style scoped>
.tree-node {
  display: inline;
}

.node-bracket {
  color: #8c8c8c;
  display: inline;
}

.node-children {
  padding-left: 20px;
  display: block;
}

.node-item {
  display: block;
}

.node-key {
  color: #9254de;
  font-weight: 500;
}

.node-colon {
  color: #8c8c8c;
  margin: 0 4px;
}

.node-comma {
  color: #8c8c8c;
}

.array-index {
  color: #8c8c8c;
  font-size: 11px;
  margin-right: 4px;
}

.node-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 1px 4px;
  border-radius: 3px;
  transition: all 0.2s;
}

.node-value.clickable {
  cursor: pointer;
}

.node-value.clickable:hover {
  background: #e6f7ff;
  outline: 1px solid #1890ff;
}

.node-value.string {
  color: #389e0d;
}

.node-value.number {
  color: #1890ff;
}

.node-value.boolean {
  color: #eb2f96;
}

.node-value.null {
  color: #8c8c8c;
  font-style: italic;
}

.node-value.selected {
  background: #bae7ff;
  outline: 2px solid #1890ff;
}

.selected-badge {
  font-size: 10px;
  background: #1890ff;
  color: #fff;
  padding: 1px 6px;
  border-radius: 10px;
  font-weight: 500;
}
</style>
