<template>
  <div class="tree-node">
    <div
        class="node-header"
        @click="toggleExpanded"
        :class="{
        'expandable': isExpandable,
        'expanded': localExpanded,
        'leaf': !isExpandable
      }"
    >
      <span class="expand-icon" v-if="isExpandable">
        <PhCaretDown v-if="localExpanded"></PhCaretDown>
        <PhCaretRight v-else></PhCaretRight>
      </span>
      <span class="key-name" :class="keyClass">{{ displayKey }}</span>
      <span class="colon" v-if="keyName !== 'root'">:</span>
      <span class="value-preview" v-if="!isExpandable || !localExpanded">
        {{ valuePreview }}
      </span>
      <!--      <span class="type-badge" :class="typeClass">{{ typeLabel }}</span>-->
    </div>

    <div
        v-if="isExpandable"
        class="node-children-wrapper"
        :class="{ 'expanded': localExpanded }"
    >
      <div class="node-children">
        <tree-node
            v-for="(value, key) in data"
            :key="key"
            :data="value"
            :key-name="key"
            :level="level + 1"
            :expanded="expanded"
            @toggle="$emit('toggle', $event)"
        />
      </div>
    </div>
  </div>
</template>

<script>
import {PhArrowArcLeft, PhCaretDown, PhCaretRight} from "@phosphor-icons/vue";

export default {
  name: 'TreeNode',
  components: {PhCaretDown, PhCaretRight, PhArrowArcLeft},
  emits: ['toggle'],
  props: {
    data: {
      required: true
    },
    keyName: {
      type: [String, Number],
      required: true
    },
    level: {
      type: Number,
      default: 0
    },
    expanded: {
      type: Boolean,
      default: false
    },
  },
  data() {
    return {
      localExpanded: false
    }
  },
  computed: {
    isExpandable() {
      return this.data !== null &&
          this.data !== undefined &&
          (typeof this.data === 'object') &&
          Object.keys(this.data).length > 0
    },
    displayKey() {
      if (this.keyName === 'root') return 'JSON'
      return  this.keyName
    },
    keyClass() {
      return {
        'object-key': this.keyName !== 'root',
        'root-key': this.keyName === 'root'
      }
    },
    valuePreview() {
      if (this.data === null) return 'null'
      if (this.data === undefined) return 'undefined'

      if (this.isExpandable) {
        const keys = Object.keys(this.data)
        const count = keys.length
        if (Array.isArray(this.data)) {
          return `Array(${count})`
        } else {
          return `Object {${count} ${count === 1 ? 'property' : 'properties'}}`
        }
      }

      if (typeof this.data === 'string') {
        return `"${this.data}"`
      }

      return String(this.data)
    },
    typeClass() {
      if (this.data === null) return 'null'
      if (this.data === undefined) return 'undefined'
      if (Array.isArray(this.data)) return 'array'
      return typeof this.data
    },
    typeLabel() {
      if (this.data === null) return 'null'
      if (this.data === undefined) return 'undefined'
      if (Array.isArray(this.data)) return 'array'
      return typeof this.data
    }
  },
  watch: {
    expanded(newValue) {
      this.localExpanded = newValue
    }
  },
  mounted() {
    this.localExpanded = this.expanded
  },
  methods: {
    toggleExpanded() {
      if (this.isExpandable) {
        this.localExpanded = !this.localExpanded
        this.$emit('toggle', this.localExpanded)
      }
    }
  }
}
</script>

<style scoped>
.tree-node {
  font-size: 14px;
  line-height: 1.5;
  margin-left: 20px;
}

.node-header {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  min-height: 28px;
}

.node-header:hover {
  background-color: rgba(107, 134, 156, 0.05);
}

.node-header.expandable {
  cursor: pointer;
}

.node-header.leaf {
  cursor: default;
}

.expand-icon {
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 6px;
  font-size: 10px;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  color: #002F54;
  font-weight: 500;
}

.node-header.expanded .expand-icon {
  transform: rotate(0deg);
}

.key-name {
  font-weight: 500;
  margin-right: 6px;
  min-width: fit-content;
}

.key-name.root-key {
  color: #002F54;
  font-size: 16px;
  font-weight: 500;
}

.key-name.object-key {
  color: #002F54;
}

.key-name.array-index {
  color: #BC2B72;
}

.colon {
  margin-right: 8px;
  color: #6b7280;
  font-weight: 600;
}

.value-preview {
  color: #6b7280;
  flex: 1;
  margin-right: 12px;
  word-break: break-all;
  transition: opacity 0.2s ease;
}

.type-badge {
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  min-width: fit-content;
}

.type-badge.string {
  background-color: #5AF0B4;
  color: #002F54;
}

.type-badge.number {
  background-color: #c3cfdf;
  color: #002F54;
}

.type-badge.boolean {
  border: 0.1rem solid #002F54;
  background-color: transparent;
  color: #002F54;
}

.type-badge.object {
  background-color: #DCDCDC;
  color: #002F54;
}

.type-badge.array {
  background-color: #BC2B72;
  color: #ffffff;
}

.type-badge.null {
  background: #f3f4f6;
  color: #6b7280;
}

.type-badge.undefined {
  background: #f3f4f6;
  color: #6b7280;
}

/* Wrapper for the children with animation */
.node-children-wrapper {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.node-children-wrapper.expanded {
  max-height: 9999px; /* Large enough value to accommodate any content */
}

.node-children {
  border-left: 1px solid #E3EDFF;
  margin-left: 8px;
  margin-top: 4px;
  padding-left: 4px;
}
</style>