<template>
  <div class="constructeur-categorie-select space-y-2">
    <div class="flex flex-wrap gap-2 min-h-[1.75rem]">
      <span v-if="!selected.length" class="text-sm text-base-content/50">
        Aucune catégorie
      </span>
      <span
        v-for="cat in selected"
        :key="cat.id || cat.name"
        class="badge badge-outline badge-lg gap-1"
      >
        <span>{{ cat.name }}</span>
        <button
          v-if="!disabled"
          type="button"
          class="btn btn-ghost btn-xs p-0 h-auto min-h-0"
          aria-label="Retirer la catégorie"
          @click="removeCategory(cat)"
        >
          <IconLucideX class="w-3 h-3" aria-hidden="true" />
        </button>
      </span>
    </div>

    <div v-if="!disabled" class="relative">
      <input
        v-model="searchTerm"
        type="text"
        class="input input-bordered input-sm md:input-md w-full"
        :placeholder="placeholder"
        @focus="open = true; ensureLoaded()"
        @keydown.escape="open = false"
      >
      <div
        v-if="open && (matches.length || canCreate)"
        class="absolute z-30 mt-1 w-full max-h-56 overflow-y-auto bg-base-100 border border-base-200 rounded-box shadow-lg"
      >
        <button
          v-for="cat in matches"
          :key="cat.id"
          type="button"
          class="w-full text-left px-3 py-2 hover:bg-base-200 focus:bg-base-200 focus:outline-none text-sm"
          @click="addCategory(cat)"
        >
          {{ cat.name }}
        </button>
        <button
          v-if="canCreate"
          type="button"
          class="w-full text-left px-3 py-2 hover:bg-base-200 focus:bg-base-200 focus:outline-none text-sm text-primary"
          @click="createAndAdd"
        >
          + Créer « {{ searchTerm.trim() }} »
        </button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import type { PropType } from 'vue'
import { useConstructeurCategories, type ConstructeurCategorie } from '~/composables/useConstructeurCategories'
import IconLucideX from '~icons/lucide/x'

const props = defineProps({
  modelValue: {
    type: Array as PropType<ConstructeurCategorie[]>,
    default: () => [],
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  placeholder: {
    type: String,
    default: 'Rechercher ou créer une catégorie…',
  },
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: ConstructeurCategorie[]): void
}>()

const { categories, loadCategories, createCategory } = useConstructeurCategories()

const searchTerm = ref('')
const open = ref(false)
const loadedOnce = ref(false)

const selected = computed<ConstructeurCategorie[]>(() => props.modelValue || [])

const selectedKeys = computed(() => new Set(selected.value.map(c => (c.name || '').toLowerCase())))

const matches = computed<ConstructeurCategorie[]>(() => {
  const term = searchTerm.value.trim().toLowerCase()
  return categories.value
    .filter(c => !selectedKeys.value.has((c.name || '').toLowerCase()))
    .filter(c => !term || (c.name || '').toLowerCase().includes(term))
    .slice(0, 50)
})

const canCreate = computed(() => {
  const term = searchTerm.value.trim()
  if (!term) {
    return false
  }
  const lower = term.toLowerCase()
  return !categories.value.some(c => (c.name || '').toLowerCase() === lower)
    && !selectedKeys.value.has(lower)
})

const ensureLoaded = async () => {
  if (loadedOnce.value) {
    return
  }
  loadedOnce.value = true
  await loadCategories()
}

const emitSelection = (value: ConstructeurCategorie[]) => {
  emit('update:modelValue', value)
}

const addCategory = (cat: ConstructeurCategorie) => {
  if (selectedKeys.value.has((cat.name || '').toLowerCase())) {
    return
  }
  emitSelection([...selected.value, cat])
  searchTerm.value = ''
}

const removeCategory = (cat: ConstructeurCategorie) => {
  emitSelection(selected.value.filter(c => c !== cat && c.id !== cat.id))
}

const createAndAdd = async () => {
  const created = await createCategory(searchTerm.value)
  if (created) {
    addCategory(created)
  }
}

const onDocumentClick = (event: Event) => {
  const target = event.target as HTMLElement | null
  if (target && !target.closest('.constructeur-categorie-select')) {
    open.value = false
  }
}

onMounted(() => document.addEventListener('click', onDocumentClick))
onBeforeUnmount(() => document.removeEventListener('click', onDocumentClick))
</script>
