<script setup lang="ts">
import { cn } from '~/lib/utils'
import { type Item } from './index'

const props = defineProps<{
  id?: string
  modelValue?: string
  items: Item[]
  placeholder?: string
  searchPlaceholder?: string
  emptyMessage?: string
  class?: string
  isDisabled?: boolean
  page?: number
  totalPage?: number
  hasNext?: boolean
  hasPrev?: boolean
  isLoading?: boolean
  searchText?: string
}>()

const emit = defineEmits<{
  'update:modelValue': [value: string]
  'update:searchText': [value: string]
  'page-change': [page: number]
  next: []
  prev: []
}>()

const open = ref(false)
const internalSearchText = ref(props.searchText || '')

// Keep internal search text synced with props
watch(
  () => props.searchText,
  (val) => {
    if (val !== internalSearchText.value) internalSearchText.value = val || ''
  },
)

const selectedItem = computed(() => props.items.find((item) => item.value === props.modelValue))
const displayText = computed(() => {
  if (selectedItem.value?.label) return selectedItem.value.label
  return props.placeholder || 'Pilih item'
})

const searchableItems = computed(() => {
  const itemsWithSearch = props.items.map((item) => ({
    ...item,
    searchValue: `${item.code || ''} ${item.label}`.trim(),
    isSelected: item.value === props.modelValue,
  }))

  return itemsWithSearch.sort((a, b) => {
    const aPriority = a.priority ?? 0
    const bPriority = b.priority ?? 0
    if (aPriority !== bPriority) return bPriority - aPriority
    if (a.isSelected && !b.isSelected) return -1
    if (!a.isSelected && b.isSelected) return 1
    return a.label.localeCompare(b.label)
  })
})

function onSelect(item: Item) {
  emit('update:modelValue', item.value)
  open.value = false
}

function onSearchInput(value: string) {
  console.log('[ComboboxPaginated] emit update:searchText', value)
  internalSearchText.value = value
  emit('update:searchText', value)
}

function handlePrev() {
  if (props.hasPrev) emit('prev')
}

function handleNext() {
  if (props.hasNext) emit('next')
}
</script>

<template>
  <Popover v-model:open="open">
    <PopoverTrigger as-child>
      <Button
        :id="props.id"
        :disabled="props.isDisabled"
        variant="outline"
        role="combobox"
        :aria-expanded="open"
        :aria-controls="`${props.id}-list`"
        :aria-describedby="`${props.id}-search`"
        :class="
          cn(
            'h-8 w-full justify-between rounded-md border px-3 font-normal focus:outline-none focus:ring-1 focus:ring-black dark:!border-slate-400 dark:focus:ring-white md:text-xs 2xl:h-9 2xl:text-sm',
            {
              'cursor-not-allowed border-gray-300 bg-gray-100 text-gray-500 opacity-50': props.isDisabled,
              'border-gray-400 bg-white text-black hover:bg-gray-50 dark:border-gray-600 dark:bg-slate-950 dark:text-white dark:hover:bg-gray-700':
                !props.isDisabled,
              'text-gray-400 dark:text-gray-500': !props.modelValue && !props.isDisabled,
            },
            props.class,
          )
        "
      >
        {{ displayText }}
        <Icon
          name="i-lucide-chevrons-up-down"
          :class="
            cn('ml-2 h-4 w-4 shrink-0', {
              'opacity-30': props.isDisabled,
              'text-gray-500 opacity-50 dark:text-gray-300': !props.isDisabled,
            })
          "
        />
      </Button>
    </PopoverTrigger>

    <PopoverContent
      class="w-[var(--radix-popover-trigger-width)] border border-gray-200 bg-white p-0 dark:border-gray-700 dark:bg-gray-800"
    >
      <Command class="bg-white dark:bg-gray-800">
        <CommandInput
          :id="`${props.id}-search`"
          class="h-9 border-0 border-b border-gray-200 bg-white text-black focus:ring-0 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
          :placeholder="searchPlaceholder || 'Cari...'"
          v-model="internalSearchText"
          @input="onSearchInput(($event.target as HTMLInputElement).value)"
          :aria-label="`Cari ${displayText}`"
        />

        <CommandEmpty class="py-6 text-center text-sm text-gray-500 dark:text-gray-400">
          {{ emptyMessage || 'Item tidak ditemukan.' }}
        </CommandEmpty>

        <CommandList
          :id="`${props.id}-list`"
          role="listbox"
          class="max-h-60 overflow-auto"
        >
          <CommandGroup>
            <CommandItem
              v-for="item in searchableItems"
              :key="item.value"
              :value="item.value"
              :class="
                cn(
                  'flex w-full cursor-pointer items-center justify-between rounded-sm px-2 py-1.5 md:text-xs xl:text-sm',
                  'text-black focus:outline-none dark:text-white',
                  'hover:bg-primary hover:text-white focus:bg-primary focus:text-white',
                  'data-[highlighted]:bg-primary data-[highlighted]:text-white',
                )
              "
              @select="onSelect(item)"
            >
              <div class="flex w-full items-center justify-between">
                <span>{{ item.label }}</span>
                <div class="flex items-center gap-2">
                  <span
                    v-if="item.code"
                    class="text-xs text-muted-foreground"
                  >
                    {{ item.code }}
                  </span>
                  <Icon
                    name="i-lucide-check"
                    :class="cn('h-4 w-4', props.modelValue === item.value ? 'opacity-100' : 'opacity-0')"
                  />
                </div>
              </div>
            </CommandItem>
          </CommandGroup>
        </CommandList>

        <div class="flex items-center justify-between border-t border-gray-200 p-2 text-xs dark:border-gray-700">
          <div class="flex items-center gap-2">
            <Icon
              v-if="props.isLoading"
              name="i-lucide-loader-2"
              class="h-3 w-3 animate-spin"
            />
            <span v-else>{{ props.page || 1 }} / {{ props.totalPage || 1 }}</span>
          </div>
          <div class="flex items-center gap-2">
            <Button
              size="sm"
              variant="ghost"
              :disabled="!props.hasPrev || props.isDisabled"
              @click="handlePrev"
            >
              Prev
            </Button>
            <Button
              size="sm"
              variant="ghost"
              :disabled="!props.hasNext || props.isDisabled"
              @click="handleNext"
            >
              Next
            </Button>
          </div>
        </div>
      </Command>
    </PopoverContent>
  </Popover>
</template>
