<!--
Composant de sélection hiérarchique simplifié pour les arbres de ressources.
Les items fournis sont déjà triés, traduits et structurés au format ResourceTreeContent.

## Exemple d'utilisation
```vue
<TreeSelect
  v-model="selectedValues"
  :items="resourceTreeContent"
  :max-visible-chips="3"
  label="Sélectionner des éléments"
/>
```
-->
<template>
  <v-select
    :model-value="modelValue"
    :label="label"
    v-bind="$attrs"
    :items="flattenedItems"
    item-title="label"
    item-value="value"
    :variant="variant"
    multiple
    :menu-props="{ maxHeight: 400 }"
    @update:model-value="$emit('update:modelValue', $event)"
  >
    <template #selection="{ item, index }">
      <v-chip
        v-if="maxVisibleChips && index < maxVisibleChips"
        :key="item.raw.value"
        closable
        @click:close="removeItem(String(item.raw.value!))"
      >
        {{ item.raw.label }}
      </v-chip>
      <span
        v-if="
          maxVisibleChips &&
          index === maxVisibleChips &&
          modelValue.length > maxVisibleChips
        "
        class="text-grey text-caption align-self-center"
      >
        (+{{ modelValue.length - maxVisibleChips }} autres)
      </span>
    </template>

    <template #item="{ item }">
      <template v-if="item.raw.type === 'category'">
        <v-list-item
          :ripple="false"
          :class="{
            'v-list-item--active': expandedCategories.has(item.raw.id),
          }"
          @click.stop="toggleCategory(item.raw.id)"
        >
          <template #prepend>
            <v-icon
              :icon="
                'fas ' +
                (expandedCategories.has(item.raw.id)
                  ? 'fa-angle-down'
                  : 'fa-angle-right')
              "
              size="small"
            />
          </template>
          <v-list-item-title class="font-weight-medium">
            {{ item.raw.label }}
          </v-list-item-title>
        </v-list-item>
      </template>

      <template v-else-if="item.raw.type === 'subcategory'">
        <v-list-item
          :ripple="false"
          :class="{
            'v-list-item--active': expandedSubcategories.has(item.raw.id),
            'pl-8': true,
          }"
          @click.stop="toggleSubcategory(item.raw.id)"
        >
          <template #prepend>
            <v-icon
              :icon="
                'fas ' +
                (expandedSubcategories.has(item.raw.id)
                  ? 'fa-angle-down'
                  : 'fa-angle-right')
              "
              size="small"
            />
          </template>
          <v-list-item-title>
            {{ item.raw.label }}
          </v-list-item-title>
        </v-list-item>
      </template>

      <template v-else>
        <v-list-item
          :active="modelValue.includes(String(item.raw.value!))"
          :class="{
            'd-flex': true,
            'pl-12': item.raw.level === 2,
            'pl-8': item.raw.level === 1,
          }"
          @click="toggleItem(String(item.raw.value!))"
        >
          <template #prepend>
            <v-checkbox
              :model-value="modelValue.includes(String(item.raw.value!))"
              color="primary"
              :hide-details="true"
              @click.stop="toggleItem(String(item.raw.value!))"
            />
          </template>
          <v-list-item-title>
            {{ item.raw.label }}
          </v-list-item-title>
        </v-list-item>
      </template>
    </template>
  </v-select>
</template>

<script setup lang="ts">
import { ref, computed, type PropType, type Ref } from 'vue'
import type { ResourceTreeContent } from '~/types/data'

interface FlattenedItem {
  id: string
  label: string
  value?: string
  type: 'category' | 'subcategory' | 'item'
  level: number
  parentId?: string
}

const props = defineProps({
  modelValue: {
    type: Array as PropType<string[]>,
    required: true,
  },
  items: {
    type: [Array, Object] as PropType<ResourceTreeContent>,
    required: true,
  },
  maxVisibleChips: {
    type: Number,
    required: false,
    default: null,
  },
  label: {
    type: String,
    required: false,
    default: '',
  },
  variant: {
    type: String as PropType<
      | 'filled'
      | 'outlined'
      | 'plain'
      | 'underlined'
      | 'solo'
      | 'solo-inverted'
      | 'solo-filled'
      | undefined
    >,
    required: false,
    default: 'outlined',
  },
})

const emit = defineEmits(['update:modelValue'])

const expandedCategories: Ref<Set<string>> = ref(new Set())
const expandedSubcategories: Ref<Set<string>> = ref(new Set())

/**
 * Flatten the ResourceTreeContent into a flat array for v-select
 */
const flattenedItems = computed(() => {
  const items: FlattenedItem[] = []
  let itemCounter = 0

  if (Array.isArray(props.items)) {
    // Simple array of strings
    props.items.forEach((item) => {
      items.push({
        id: `item-${itemCounter++}`,
        label: item,
        value: item,
        type: 'item',
        level: 0,
      })
    })
  } else {
    // Object structure (2 or 3 levels)
    Object.entries(props.items).forEach(([categoryKey, categoryValue]) => {
      const categoryId = `category-${categoryKey}`

      // Add category
      items.push({
        id: categoryId,
        label: categoryKey,
        type: 'category',
        level: 0,
      })

      if (Array.isArray(categoryValue)) {
        // 2-level structure: Record<string, string[]>
        if (expandedCategories.value.has(categoryId)) {
          categoryValue.forEach((item) => {
            items.push({
              id: `item-${itemCounter++}`,
              label: item,
              value: item,
              type: 'item',
              level: 1,
              parentId: categoryId,
            })
          })
        }
      } else {
        // 3-level structure: Record<string, Record<string, string[]>>
        if (expandedCategories.value.has(categoryId)) {
          Object.entries(categoryValue).forEach(([subcategoryKey, subcategoryValue]) => {
            const subcategoryId = `subcategory-${categoryKey}-${subcategoryKey}`

            // Add subcategory
            items.push({
              id: subcategoryId,
              label: subcategoryKey,
              type: 'subcategory',
              level: 1,
              parentId: categoryId,
            })

            if (expandedSubcategories.value.has(subcategoryId)) {
              subcategoryValue.forEach((item) => {
                items.push({
                  id: `item-${itemCounter++}`,
                  label: item,
                  value: item,
                  type: 'item',
                  level: 2,
                  parentId: subcategoryId,
                })
              })
            }
          })
        }
      }
    })
  }

  return items
})

/**
 * Toggle category expansion
 */
const toggleCategory = (categoryId: string) => {
  if (expandedCategories.value.has(categoryId)) {
    expandedCategories.value.delete(categoryId)
    // Also collapse all subcategories
    Array.from(expandedSubcategories.value).forEach(subId => {
      if (subId.startsWith(`subcategory-${categoryId.replace('category-', '')}-`)) {
        expandedSubcategories.value.delete(subId)
      }
    })
  } else {
    expandedCategories.value.add(categoryId)
  }
}

/**
 * Toggle subcategory expansion
 */
const toggleSubcategory = (subcategoryId: string) => {
  if (expandedSubcategories.value.has(subcategoryId)) {
    expandedSubcategories.value.delete(subcategoryId)
  } else {
    expandedSubcategories.value.add(subcategoryId)
  }
}

/**
 * Toggle item selection
 */
const toggleItem = (value: string) => {
  const currentSelection = [...props.modelValue]
  const index = currentSelection.indexOf(value)

  if (index > -1) {
    currentSelection.splice(index, 1)
  } else {
    currentSelection.push(value)
  }

  emit('update:modelValue', currentSelection)
}

/**
 * Remove item from selection
 */
const removeItem = (value: string) => {
  emit(
    'update:modelValue',
    props.modelValue.filter((item) => item !== value),
  )
}
</script>
