<template>
  <div>
    <!-- Row -->
    <div
      class="flex items-center group"
      :style="{ paddingLeft: `${depth * 12}px` }"
    >
      <!-- Expand/collapse arrow — hidden when item is a known leaf -->
      <button
        v-if="expandable"
        @click.prevent.stop="toggleExpand"
        class="w-5 h-5 flex items-center justify-center text-gray-400 hover:text-gray-600 shrink-0 transition-colors"
        :aria-label="expanded ? 'Collapse' : 'Expand'"
      >
        <svg
          class="w-3 h-3 transition-transform duration-150"
          :class="{ 'rotate-90': expanded }"
          fill="none"
          stroke="currentColor"
          viewBox="0 0 24 24"
        >
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M9 5l7 7-7 7" />
        </svg>
      </button>
      <span v-else class="w-5 h-5 shrink-0"></span>

      <!-- Label row — router-link when `to` is provided, button otherwise -->
      <router-link
        v-if="to"
        :to="to"
        class="flex items-center gap-2 flex-1 min-w-0 px-2 py-1.5 rounded-lg text-sm font-medium transition-colors"
        :class="isActive
          ? 'bg-indigo-50 text-indigo-700'
          : 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'"
      >
        <slot name="icon" />
        <span class="truncate">{{ label }}</span>
      </router-link>
      <button
        v-else
        @click="$emit('select')"
        class="flex items-center gap-2 flex-1 min-w-0 px-2 py-1.5 rounded-lg text-sm font-medium transition-colors text-gray-600 hover:bg-gray-100 hover:text-gray-900"
      >
        <slot name="icon" />
        <span class="truncate">{{ label }}</span>
      </button>
    </div>

    <!-- Children -->
    <template v-if="expanded">
      <div
        v-if="loading"
        class="text-xs text-gray-400 py-1"
        :style="{ paddingLeft: `${(depth + 1) * 12 + 8}px` }"
      >
        Loading…
      </div>
      <div
        v-else-if="loadError"
        class="text-xs text-red-500 cursor-pointer py-1"
        :style="{ paddingLeft: `${(depth + 1) * 12 + 8}px` }"
        @click="retry"
      >
        Failed to load — tap to retry
      </div>
      <div
        v-else-if="children.length === 0"
        class="text-xs text-gray-400 py-1"
        :style="{ paddingLeft: `${(depth + 1) * 12 + 8}px` }"
      >
        Empty
      </div>
      <slot name="children" :children="children" />
    </template>
  </div>
</template>

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

const props = defineProps({
  label: { type: String, required: true },
  /** Router-link destination. When omitted, the label row renders as a button that emits 'select'. */
  to: { type: [String, Object], default: null },
  /** Whether this item can be expanded to reveal children. */
  expandable: { type: Boolean, default: true },
  /** Async function that returns an array of child items when called. */
  loadChildren: { type: Function, required: true },
  depth: { type: Number, default: 0 },
  /** Highlight the label row as the active route item. */
  isActive: { type: Boolean, default: false },
})

const emit = defineEmits(['select'])

const expanded = ref(false)
const children = ref([])
const loading = ref(false)
const loadError = ref(false)
const childrenLoaded = ref(false)

async function load() {
  loading.value = true
  loadError.value = false
  try {
    children.value = await props.loadChildren()
    childrenLoaded.value = true
  } catch {
    loadError.value = true
  } finally {
    loading.value = false
  }
}

async function retry() {
  await load()
}

async function toggleExpand() {
  if (!expanded.value && !childrenLoaded.value) {
    await load()
  }
  expanded.value = !expanded.value
}

/** Reload children if already expanded — called by parent when data changes. */
function refresh() {
  if (expanded.value && childrenLoaded.value) {
    load()
  }
}

defineExpose({ refresh })
</script>
