<script setup lang="ts">
import { CommandEmpty, CommandGroup, CommandItem, CommandList } from '@/components/ui/command'
import {
  TagsInput,
  TagsInputInput,
  TagsInputItem,
  TagsInputItemDelete,
  TagsInputItemText
} from '@/components/ui/tags-input'

import { ComboboxAnchor, ComboboxInput, ComboboxPortal, ComboboxRoot } from 'radix-vue'
import { computed, ref, watch } from 'vue'

const props = withDefaults(
  defineProps<{
    modelValue?: string[]
    items: string[]
    placeholder?: string
    disabled?: boolean
  }>(),
  {
    modelValue: () => [],
    items: () => [],
    placeholder: '',
    disabled: false
  }
)

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

const open = ref(false)
const searchTerm = ref('')
const selectedItems = ref<string[]>(props.modelValue)

watch(
  () => selectedItems.value,
  (value) => emit('update:modelValue', value),
  { deep: true }
)

const filteredItems = computed(() => {
  if (!selectedItems.value) return props.items
  return props.items.filter((i) => !selectedItems.value.includes(i))
})

const removeItem = (item: string) => {
  const index = selectedItems.value.indexOf(item)
  if (index > -1) {
    selectedItems.value.splice(index, 1)
  }
}
</script>

<template>
  <TagsInput class="flex items-center gap-2 px-2" :modelValue="selectedItems">
    <div class="flex flex-wrap items-center gap-2">
      <TagsInputItem v-for="item in selectedItems" :key="item" :value="item">
        <TagsInputItemText />
        <TagsInputItemDelete v-if="!disabled" @click="removeItem(item)" />
      </TagsInputItem>
    </div>

    <ComboboxRoot
      v-if="!disabled"
      v-model="selectedItems"
      v-model:open="open"
      v-model:searchTerm="searchTerm"
      class="flex-1"
    >
      <ComboboxAnchor as-child>
        <ComboboxInput
          :placeholder="placeholder"
          as-child
          :class="selectedItems.length < items.length ? '' : 'hidden'"
        >
          <TagsInputInput @keydown.enter.prevent @focus="open = true" @blur="open = false" />
        </ComboboxInput>
      </ComboboxAnchor>

      <ComboboxPortal>
        <CommandList
          v-if="selectedItems.length < items.length"
          position="popper"
          class="w-(--radix-popper-anchor-width) mt-2 rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
        >
          <CommandEmpty />
          <CommandGroup>
            <CommandItem
              v-for="item in filteredItems"
              :key="item"
              :value="item"
              @select.prevent="
                (ev) => {
                  if (typeof ev.detail.value === 'string') {
                    searchTerm = ''
                    selectedItems.push(ev.detail.value)
                  }

                  if (filteredItems.length === 0) {
                    open = false
                  }
                }
              "
            >
              {{ item }}
            </CommandItem>
          </CommandGroup>
        </CommandList>
      </ComboboxPortal>
    </ComboboxRoot>
  </TagsInput>
</template>
