<template>
  <div class="node-detail-panel">
    <section class="detail-section">
      <div class="detail-section-head">
        <strong>节点摘要</strong>
        <span>{{ safeNode.type || '未知类型' }}</span>
      </div>
      <div v-if="descriptionItems.length" class="description-list">
        <p v-for="(description, index) in descriptionItems" :key="index">
          {{ description }}
        </p>
      </div>
      <div v-else class="detail-empty compact">
        暂无描述，LightRAG 还没有为该节点生成可展示的摘要。
      </div>
    </section>

    <section class="detail-section">
      <div class="detail-section-head">
        <strong>节点属性</strong>
        <span>{{ propertyItems.length }} 项</span>
      </div>
      <dl class="property-grid">
        <div>
          <dt>节点类型</dt>
          <dd>{{ safeNode.type || '未知类型' }}</dd>
        </div>
        <div>
          <dt>关联度</dt>
          <dd>{{ safeNode.degree || 0 }}</dd>
        </div>
        <div>
          <dt>入边</dt>
          <dd>{{ incoming.length }}</dd>
        </div>
        <div>
          <dt>出边</dt>
          <dd>{{ outgoing.length }}</dd>
        </div>
      </dl>

      <div v-if="labelItems.length" class="label-row">
        <span v-for="label in labelItems" :key="label">{{ label }}</span>
      </div>

      <dl v-if="propertyItems.length" class="raw-property-list">
        <div v-for="item in propertyItems" :key="item.key">
          <dt>{{ item.label }}</dt>
          <dd>{{ item.value }}</dd>
        </div>
      </dl>
    </section>

    <section class="detail-section relation-section">
      <div class="detail-section-head">
        <strong>关联关系</strong>
        <span>{{ relationRows.length }} 条</span>
      </div>
      <div v-if="relationRows.length" class="relation-detail-list">
        <button
          v-for="relation in relationRows"
          :key="relation.key"
          type="button"
          @click="$emit('focus-peer', relation.raw)"
        >
          <span class="relation-direction">{{ relation.directionLabel }}</span>
          <span class="relation-peer">{{ relation.peerName }}</span>
          <strong>{{ relation.type }}</strong>
          <p v-if="relation.description">{{ relation.description }}</p>
          <div v-if="relation.keywords.length" class="keyword-row">
            <span v-for="keyword in relation.keywords" :key="keyword">{{ keyword }}</span>
          </div>
        </button>
      </div>
      <div v-else class="detail-empty compact">暂无关联关系</div>
    </section>
  </div>
</template>

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

const props = defineProps({
  node: {
    type: Object,
    default: null
  },
  incoming: {
    type: Array,
    default: () => []
  },
  outgoing: {
    type: Array,
    default: () => []
  },
  relations: {
    type: Array,
    default: () => []
  }
})

defineEmits(['focus-peer'])

const safeNode = computed(() => (props.node && typeof props.node === 'object' ? props.node : {}))

const descriptionItems = computed(() => {
  const descriptions = Array.isArray(safeNode.value.descriptions)
    ? safeNode.value.descriptions
    : []
  const fallback = String(safeNode.value.description || '').trim()
  return dedupeTextItems(descriptions.length ? descriptions : [fallback]).slice(0, 6)
})

const labelItems = computed(() => dedupeTextItems(safeNode.value.labels).slice(0, 8))

const propertyItems = computed(() => {
  const properties =
    safeNode.value.properties && typeof safeNode.value.properties === 'object'
      ? safeNode.value.properties
      : {}
  return Object.entries(properties)
    .filter(([key, value]) => !hiddenPropertyKeys.has(key) && String(value || '').trim())
    .map(([key, value]) => ({
      key,
      label: formatPropertyKey(key),
      value: String(value).trim()
    }))
    .slice(0, 10)
})

const relationRows = computed(() => {
  const nodeName = String(safeNode.value.name || '').trim()
  if (!nodeName || !Array.isArray(props.relations)) return []
  return props.relations.map((relation, index) => {
    const isOutgoing = relation.source === nodeName
    const peerName = isOutgoing ? relation.target : relation.source
    return {
      key: `${relation.source}-${relation.target}-${relation.type}-${index}`,
      raw: relation,
      peerName,
      type: String(relation.type || '关联').trim(),
      directionLabel: isOutgoing ? '指向' : '来源',
      description: String(relation.description || '').trim(),
      keywords: dedupeTextItems(relation.keywords).slice(0, 6)
    }
  })
})

const hiddenPropertyKeys = new Set(['source_id', 'file_path', 'truncate'])

function dedupeTextItems(items) {
  const sourceItems = Array.isArray(items)
    ? items
    : String(items || '')
        .split('<SEP>')
        .filter(Boolean)
  const result = []
  const seen = new Set()
  for (const item of sourceItems) {
    const text = String(item || '').trim()
    if (!text || seen.has(text)) continue
    seen.add(text)
    result.push(text)
  }
  return result
}

function formatPropertyKey(key) {
  const labels = {
    entity_id: '实体ID',
    entity_type: '实体类型',
    created_at: '创建时间',
    weight: '权重'
  }
  return labels[key] || key
}
</script>

<style scoped>
.node-detail-panel,
.detail-section,
.description-list,
.relation-detail-list {
  display: grid;
  gap: 10px;
}

.detail-section {
  min-width: 0;
  padding: 11px;
  border: 1px solid #e5edf5;
  border-radius: 8px;
  background: #f8fafc;
}

.detail-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.detail-section-head strong {
  color: #0f172a;
  font-size: 13px;
}

.detail-section-head span {
  max-width: 56%;
  overflow: hidden;
  color: #475569;
  font-size: 11px;
  font-weight: 800;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.description-list {
  max-height: 190px;
  overflow: auto;
  padding-right: 3px;
}

.description-list p {
  margin: 0;
  padding: 9px;
  border: 1px solid color-mix(in srgb, var(--theme-primary) 18%, #ffffff);
  border-radius: 8px;
  background: #fff;
  color: #1e293b;
  font-size: 12px;
  line-height: 1.62;
}

.property-grid,
.raw-property-list {
  display: grid;
  gap: 8px;
}

.property-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.property-grid div,
.raw-property-list div {
  min-width: 0;
  display: grid;
  gap: 4px;
}

.property-grid div {
  padding: 8px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #fff;
}

.property-grid dt,
.raw-property-list dt {
  color: #64748b;
  font-size: 11px;
  font-weight: 750;
}

.property-grid dd,
.raw-property-list dd {
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
  color: #0f172a;
  font-size: 12px;
  font-weight: 800;
}

.label-row,
.keyword-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.label-row span,
.keyword-row span,
.relation-direction {
  min-height: 22px;
  display: inline-flex;
  align-items: center;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--theme-primary-light-9);
  color: var(--theme-primary-active);
  font-size: 11px;
  font-weight: 800;
}

.raw-property-list {
  max-height: 160px;
  overflow: auto;
  padding-top: 2px;
}

.relation-section {
  max-height: 360px;
  overflow: hidden;
}

.relation-detail-list {
  min-height: 0;
  overflow: auto;
  padding-right: 3px;
}

.relation-detail-list button {
  min-width: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 7px;
  padding: 9px;
  border: 1px solid color-mix(in srgb, var(--theme-primary) 18%, #ffffff);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.18s ease, background 0.18s ease, transform 0.18s ease;
}

.relation-detail-list button:hover {
  border-color: color-mix(in srgb, var(--theme-primary) 38%, #ffffff);
  background: var(--theme-primary-light-9);
  transform: translateY(-1px);
}

.relation-peer,
.relation-detail-list strong {
  min-width: 0;
  overflow: hidden;
  color: #0f172a;
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.relation-detail-list strong {
  color: var(--theme-primary-active);
}

.relation-detail-list p,
.detail-empty {
  grid-column: 1 / -1;
  margin: 0;
  color: #334155;
  font-size: 12px;
  line-height: 1.55;
}

.keyword-row {
  grid-column: 1 / -1;
}

.keyword-row span {
  background: var(--theme-primary-light-9);
  color: var(--theme-primary-active);
}

.detail-empty {
  min-height: 82px;
  display: grid;
  place-items: center;
  text-align: center;
}

.detail-empty.compact {
  min-height: 52px;
  padding: 8px;
  border: 1px dashed #cbd5e1;
  border-radius: 8px;
  background: #fff;
}

@media (prefers-reduced-motion: reduce) {
  .relation-detail-list button {
    transition: none;
  }
}
</style>
