<script lang="ts">
export interface GroupedOption {
  value: string
  label: string
  type: string
  connection?: string | null
}

export interface OptionGroup {
  type: string
  connection: string | null
  displayName: string
  options: GroupedOption[]
}
</script>

<script setup lang="ts">
import { computed, ref, nextTick } from 'vue'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'

const props = withDefaults(
  defineProps<{
    options: GroupedOption[]
    modelValue: string
    placeholder?: string
    searchPlaceholder?: string
    emptyText?: string
    maxHeight?: string
    disabled?: boolean
  }>(),
  {
    placeholder: 'Select...',
    searchPlaceholder: 'Filter...',
    emptyText: 'No items found',
    maxHeight: '300px',
    disabled: false,
  }
)

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

const searchQuery = ref('')
const isOpen = ref(false)
const listRef = ref<HTMLElement | null>(null)

// Type name mapping for display
const typeDisplayNames: Record<string, string> = {
  'OPENAI': 'OpenAI',
  'VERTEX': 'Vertex Generative AI',
  'AZURE_OPENAI': 'Azure OpenAI',
  'ANTHROPIC': 'Anthropic',
  'BEDROCK': 'AWS Bedrock',
  'COHERE': 'Cohere',
  'MISTRAL': 'Mistral AI',
  'HUGGING_FACE': 'Hugging Face',
}

function formatTypeName(type: string): string {
  return typeDisplayNames[type] || type
}

const filteredOptions = computed(() => {
  if (!searchQuery.value) return props.options
  const query = searchQuery.value.toLowerCase()
  return props.options.filter(opt => {
    return opt.label.toLowerCase().includes(query) || opt.value.toLowerCase().includes(query)
  })
})

// Group filtered options by type + connection
const groupedOptions = computed((): OptionGroup[] => {
  const groups = new Map<string, OptionGroup>()

  for (const opt of filteredOptions.value) {
    const key = `${opt.type}::${opt.connection || ''}`
    if (!groups.has(key)) {
      groups.set(key, {
        type: opt.type,
        connection: opt.connection || null,
        displayName: formatTypeName(opt.type),
        options: [],
      })
    }
    groups.get(key)!.options.push(opt)
  }

  // Sort groups by type, then by connection
  return Array.from(groups.values()).sort((a, b) => {
    const typeCompare = a.type.localeCompare(b.type)
    if (typeCompare !== 0) return typeCompare
    return (a.connection || '').localeCompare(b.connection || '')
  })
})

const selectedLabel = computed(() => {
  if (!props.modelValue) return ''
  const opt = props.options.find(o => o.value === props.modelValue)
  return opt?.label || props.modelValue
})

function selectOption(value: string) {
  emit('update:modelValue', value)
  isOpen.value = false
}

function scrollToSelected() {
  nextTick(() => {
    if (listRef.value && props.modelValue) {
      const selectedEl = listRef.value.querySelector('[data-selected="true"]')
      if (selectedEl) {
        selectedEl.scrollIntoView({ block: 'center' })
      }
    }
  })
}

function handleOpenChange(open: boolean) {
  if (props.disabled) return
  isOpen.value = open
  if (open) {
    scrollToSelected()
  } else {
    searchQuery.value = ''
  }
}
</script>

<template>
  <div class="w-full min-w-0">
    <DropdownMenu :open="isOpen" @update:open="handleOpenChange">
      <DropdownMenuTrigger as-child :disabled="disabled">
        <button
          type="button"
          class="flex w-full max-w-full items-center justify-between overflow-hidden rounded-md border border-input bg-background px-2 py-1 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
          :disabled="disabled"
        >
          <span v-if="!modelValue" class="body-333 min-w-0 flex-1 truncate text-left text-muted-foreground">
            {{ placeholder }}
          </span>
          <span v-else class="body-333 min-w-0 flex-1 truncate text-left">
            {{ selectedLabel }}
          </span>
          <i class="dku-icon-chevron-down-12 ml-1 shrink-0 opacity-50" />
        </button>
      </DropdownMenuTrigger>
      <DropdownMenuContent
        class="w-[--reka-dropdown-menu-trigger-width] min-w-[280px] p-0"
        align="start"
      >
        <!-- Search input -->
        <div class="flex items-center border-b px-3 py-2">
          <i class="dku-icon-search-16 mr-2 shrink-0 opacity-50" />
          <input
            v-model="searchQuery"
            type="text"
            :placeholder="searchPlaceholder"
            class="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
          />
        </div>

        <!-- Options list -->
        <div
          ref="listRef"
          class="overflow-y-auto p-1"
          :style="{ maxHeight }"
        >
          <div
            v-if="groupedOptions.length === 0"
            class="py-6 text-center text-sm text-muted-foreground"
          >
            {{ emptyText }}
          </div>

          <template v-for="(group, groupIndex) in groupedOptions" :key="`${group.type}-${group.connection}`">
            <!-- Separator between groups -->
            <div v-if="groupIndex > 0" class="my-1 h-px bg-border" />

            <!-- Group header -->
            <div class="flex items-center gap-2 px-2 py-1.5">
              <span class="text-xs font-semibold text-foreground">{{ group.displayName }}</span>
              <template v-if="group.connection">
                <i class="dku-icon-link-12 text-muted-foreground" />
                <span class="text-xs text-muted-foreground">{{ group.connection }}</span>
              </template>
            </div>

            <!-- Group options -->
            <button
              v-for="option in group.options"
              :key="option.value"
              type="button"
              class="body-333 relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
              :data-selected="modelValue === option.value"
              @click.stop="selectOption(option.value)"
            >
              <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
                <i
                  v-if="modelValue === option.value"
                  class="dku-icon-checkmark-16 text-primary"
                />
              </span>
              <span :class="{ 'font-medium': modelValue === option.value }">
                {{ option.label }}
              </span>
            </button>
          </template>
        </div>
      </DropdownMenuContent>
    </DropdownMenu>
  </div>
</template>
