tsx
import React, { useState, useRef, useEffect } from 'react'
import { useAppStore } from '@/store/useAppStore'
import { AI_MODELS, CATEGORY_NAMES, CATEGORY_DESCRIPTIONS, getModelsByCategory } from '@/utils/constants'
import { AIModel, AICategory } from '@/types'
import { ChevronDown, Search, Zap } from 'lucide-react'

/**
 * Component for selecting AI models with categorized dropdown
 */
export function ModelSelector() {
  const { selectedModel, setSelectedModel } = useAppStore()
  const [isOpen, setIsOpen] = useState(false)
  const [searchTerm, setSearchTerm] = useState('')
  const [selectedCategory, setSelectedCategory] = useState<AICategory | null>(null)
  const dropdownRef = useRef<HTMLDivElement>(null)
  const searchRef = useRef<HTMLInputElement>(null)

  /**
   * Filter models based on search term and category
   */
  const filteredModels = AI_MODELS.filter(model => {
    const matchesSearch = model.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
                         model.description.toLowerCase().includes(searchTerm.toLowerCase())
    const matchesCategory = !selectedCategory || model.category === selectedCategory
    return matchesSearch && matchesCategory
  })

  /**
   * Close dropdown when clicking outside
   */
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
        setIsOpen(false)
      }
    }

    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [])

  /**
   * Focus search input when dropdown opens
   */
  useEffect(() => {
    if (isOpen && searchRef.current) {
      searchRef.current.focus()
    }
  }, [isOpen])

  /**
   * Handle keyboard navigation
   */
  const handleKeyDown = (event: React.KeyboardEvent) => {
    if (!isOpen && (event.key === 'Enter' || event.key === ' ')) {
      event.preventDefault()
      setIsOpen(true)
    } else if (isOpen && event.key === 'Escape') {
      setIsOpen(false)
    }
  }

  /**
   * Handle model selection
   */
  const handleModelSelect = (model: AIModel) => {
    setSelectedModel(model)
    setIsOpen(false)
    setSearchTerm('')
    setSelectedCategory(null)
  }

  /**
   * Handle category selection
   */
  const handleCategorySelect = (category: AICategory) => {
    setSelectedCategory(selectedCategory === category ? null : category)
  }

  /**
   * Get selected model info
   */
  const selectedModelInfo = selectedModel ? AI_MODELS.find(m => m.id === selectedModel) : null

  /**
   * Get category icon
   */
  const getCategoryIcon = (category: AICategory) => {
    switch (category) {
      case 'llm':
        return <Zap className="w-4 h-4" />
      case 'code':
        return <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
        </svg>
      case 'image':
        return <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
        </svg>
      case 'special':
        return <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
        </svg>
    }
  }

  return (
    <div className="space-y-4">
      {/* Selected Model Display */}
      <div className="relative" ref={dropdownRef}>
        <button
          type="button"
          onClick={() => setIsOpen(!isOpen)}
          onKeyDown={handleKeyDown}
          className="w-full input-field flex items-center justify-between text-left"
          aria-label="KI-Modell auswählen"
          aria-expanded={isOpen}
          aria-haspopup="listbox"
        >
          {selectedModelInfo ? (
            <div className="flex items-center space-x-3">
              <div className="w-8 h-8 bg-gradient-to-br from-primary-500 to-secondary-500 rounded-lg flex items-center justify-center flex-shrink-0">
                {getCategoryIcon(selectedModelInfo.category)}
              </div>
              <div>
                <div className="font-medium text-gray-900 dark:text-gray-100">
                  {selectedModelInfo.name}
                </div>
                <div className="text-sm text-gray-600 dark:text-gray-400 truncate max-w-[200px]">
                  {selectedModelInfo.description}
                </div>
              </div>
            </div>
          ) : (
            <span className="text-gray-500 dark:text-gray-400">
              Wähle eine KI-Plattform aus...
            </span>
          )}
          <ChevronDown className={`w-5 h-5 text-gray-400 transition-transform ${isOpen ? 'rotate-180' : ''}`} />
        </button>

        {/* Dropdown Menu */}
        {isOpen && (
          <div className="absolute z-50 w-full mt-1 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg shadow-lg max-h-96 overflow-hidden">
            {/* Search Input */}
            <div className="p-3 border-b border-gray-200 dark:border-gray-700">
              <div className="relative">
                <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
                <input
                  ref={searchRef}
                  type="text"
                  placeholder="KI suchen..."
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                  className="w-full pl-9 pr-3 py-2 text-sm input-field"
                />
              </div>
            </div>

            {/* Categories */}
            <div className="p-2 space-y-2 max-h-80 overflow-y-auto">
              {Object.entries(CATEGORY_NAMES).map(([categoryKey, categoryName]) => {
                const category = categoryKey as AICategory
                const categoryModels = getModelsByCategory(category)
                const filteredCategoryModels = categoryModels.filter(model => 
                  filteredModels.includes(model)
                )

                if (filteredCategoryModels.length === 0) return null

                return (
                  <div key={category} className="space-y-1">
                    {/* Category Header */}
                    <button
                      type="button"
                      onClick={() => handleCategorySelect(category)}
                      className="w-full flex items-center justify-between p-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors"
                    >
                      <div className="flex items-center space-x-2">
                        {getCategoryIcon(category)}
                        <span>{categoryName}</span>
                        <span className="text-xs text-gray-500 dark:text-gray-400">
                          ({filteredCategoryModels.length})
                        </span>
                      </div>
                      <div className={`transform transition-transform ${selectedCategory === category ? 'rotate-180' : ''}`}>
                        <ChevronDown className="w-3 h-3" />
                      </div>
                    </button>

                    {/* Models in Category */}
                    {(selectedCategory === category || selectedCategory === null) && (
                      <div className="ml-6 space-y-1">
                        {filteredCategoryModels.map((model) => (
                          <button
                            key={model.id}
                            type="button"
                            onClick={() => handleModelSelect(model.id)}
                            className={`w-full text-left p-2 rounded-md transition-colors ${
                              selectedModel === model.id
                                ? 'bg-primary-100 dark:bg-primary-900 text-primary-900 dark:text-primary-100'
                                : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300'
                            }`}
                          >
                            <div className="flex items-center justify-between">
                              <div>
                                <div className="font-medium text-sm">{model.name}</div>
                                <div className="text-xs text-gray-500 dark:text-gray-400 truncate">
                                  {model.description}
                                </div>
                              </div>
                              {model.supportsStreaming && (
                                <div className="w-2 h-2 bg-green-400 rounded-full flex-shrink-0 ml-2" />
                              )}
                            </div>
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                )
              })}
            </div>
          </div>
        )}
      </div>

      {/* Selected Model Info */}
      {selectedModelInfo && (
        <div className="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
          <div className="flex items-start space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-primary-500 to-secondary-500 rounded-lg flex items-center justify-center flex-shrink-0">
              {getCategoryIcon(selectedModelInfo.category)}
            </div>
            <div className="flex-1">
              <h4 className="font-medium text-gray-900 dark:text-gray-100">
                {selectedModelInfo.name}
              </h4>
              <p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
                {selectedModelInfo.description}
              </p>
              <div className="flex items-center space-x-4 mt-2 text-xs text-gray-500 dark:text-gray-400">
                <span className="flex items-center">
                  <span className="capitalize">{CATEGORY_NAMES[selectedModelInfo.category]}</span>
                </span>
                {selectedModelInfo.maxTokens && (
                  <span>Max: {(selectedModelInfo.maxTokens / 1000).toFixed(0)}k Tokens</span>
                )}
                {selectedModelInfo.supportsStreaming && (
                  <span className="flex items-center">
                    <span className="w-2 h-2 bg-green-400 rounded-full mr-1" />
                    Streaming
                  </span>
                )}
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}

</html>