<script setup lang="ts">
import { Check, CirclePlus } from 'lucide-vue-next'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'

import { cn } from '@/lib/utils'

interface FilterOption {
  value: string
  label: string
  icon?: any
  count?: number
}

interface Props {
  title: string
  options: FilterOption[]
  modelValue: string
}

const props = defineProps<Props>()
const emit = defineEmits<{
  'update:modelValue': [value: string]
}>()

const { t } = useI18n()

const selectedValue = computed(() => props.modelValue)
const filterFunction = (list: FilterOption[], term: string) => list.filter(i => i.label.toLowerCase()?.includes(term))
</script>

<template>
  <UiPopover>
    <UiPopoverTrigger as-child>
      <UiButton variant="outline" size="sm" class="h-8 border-dashed">
        <CirclePlus class="size-4 mr-2" />
        {{ title }}
        <template v-if="selectedValue">
          <UiSeparator orientation="vertical" class="h-4 mx-2" />
          <UiBadge
            variant="secondary"
            class="px-1 font-normal rounded-sm"
          >
            {{ options.find(o => o.value === selectedValue)?.label }}
          </UiBadge>
        </template>
      </UiButton>
    </UiPopoverTrigger>
    <UiPopoverContent class="w-[200px] p-0" align="start">
      <UiCommand :filter-function="filterFunction as unknown as any">
        <UiCommandInput :placeholder="title" />
        <UiCommandList>
          <UiCommandEmpty>{{ t('common.noResults') }}</UiCommandEmpty>
          <UiCommandGroup>
            <UiCommandItem
              v-for="option in options"
              :key="option.value"
              :value="option"
              @select="() => {
                emit('update:modelValue', option.value === selectedValue ? '' : option.value)
              }"
            >
              <div
                :class="cn(
                  'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
                  selectedValue === option.value
                    ? 'bg-primary'
                    : 'opacity-50 [&_svg]:invisible',
                )"
              >
                <Check :class="cn('h-4 w-4', selectedValue === option.value ? 'text-primary-foreground' : '')" />
              </div>
              <component :is="option.icon" v-if="option.icon" class="size-4 mr-2 text-muted-foreground" />
              <span>{{ option.label }}</span>
              <span v-if="option.count" class="flex items-center justify-center size-4 ml-auto font-mono text-xs">
                {{ option.count }}
              </span>
            </UiCommandItem>
          </UiCommandGroup>

          <template v-if="selectedValue">
            <UiCommandSeparator />
            <UiCommandGroup>
              <UiCommandItem
                :value="{ label: 'Clear filters' }"
                class="justify-center text-center"
                @select="emit('update:modelValue', '')"
              >
                {{ t('common.clearFilters') }}
              </UiCommandItem>
            </UiCommandGroup>
          </template>
        </UiCommandList>
      </UiCommand>
    </UiPopoverContent>
  </UiPopover>
</template>
