import React, { KeyboardEvent, useRef, useState } from 'react';
import { ChevronUp, ChevronDown, Search } from 'lucide-react';

export interface ModelOption {
  value: string;
  label: string;
  provider?: string;
}

export interface ModelSelectorProps {
  id?: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  options?: ModelOption[];
  allowCustom?: boolean;
  className?: string;
  disabled?: boolean;
}

const DEFAULT_MODEL_OPTIONS: ModelOption[] = [
  { value: 'gpt-4o', label: 'GPT-4o', provider: 'OpenAI' },
  { value: 'gpt-4o-mini', label: 'GPT-4o Mini', provider: 'OpenAI' },
  { value: 'gpt-4-turbo', label: 'GPT-4 Turbo', provider: 'OpenAI' },
  { value: 'claude-3-5-sonnet-20241022', label: 'Claude 3.5 Sonnet', provider: 'Anthropic' },
  { value: 'claude-3-opus-20240229', label: 'Claude 3 Opus', provider: 'Anthropic' },
  { value: 'glm-5.1', label: 'GLM-5.1', provider: 'Zhipu AI' },
  { value: 'gemini-2.0-flash-exp', label: 'Gemini 2.0 Flash', provider: 'Google' },
  { value: 'deepseek-chat', label: 'DeepSeek Chat', provider: 'DeepSeek' },
];

export const ModelSelector: React.FC<ModelSelectorProps> = ({
  id,
  value,
  onChange,
  placeholder = 'Select or enter a model',
  options = DEFAULT_MODEL_OPTIONS,
  allowCustom = true,
  className = '',
  disabled = false,
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [isCustomMode, setIsCustomMode] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const filteredOptions = options.filter((option) => {
    const query = searchQuery.toLowerCase();
    return (
      option.label.toLowerCase().includes(query) ||
      option.value.toLowerCase().includes(query) ||
      option.provider?.toLowerCase().includes(query)
    );
  });

  const selectedOption = options.find((opt) => opt.value === value);

  const handleSelect = (optionValue: string) => {
    onChange(optionValue);
    setIsOpen(false);
    setSearchQuery('');
    setIsCustomMode(false);
  };

  const handleCustomMode = () => {
    setIsCustomMode(true);
    setIsOpen(false);
    setTimeout(() => inputRef.current?.focus(), 0);
  };

  const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter' && isCustomMode) {
      e.preventDefault();
      if (value.trim()) {
        setIsCustomMode(false);
      }
    }
    if (e.key === 'Escape') {
      setIsOpen(false);
      setIsCustomMode(false);
    }
  };

  const handleBlur = (e: React.FocusEvent<HTMLDivElement>) => {
    if (!containerRef.current?.contains(e.relatedTarget)) {
      setIsOpen(false);
      if (!value.trim()) {
        setIsCustomMode(false);
      }
    }
  };

  return (
    <div
      ref={containerRef}
      className={`relative ${className}`}
      onBlur={handleBlur}
    >
      {!isCustomMode ? (
        <button
          id={id}
          type="button"
          onClick={() => !disabled && setIsOpen(!isOpen)}
          disabled={disabled}
          className="w-full border border-[#2a2a2a] bg-[#111111] px-3 py-2 text-left text-sm font-mono text-[#e0e0e0] outline-none transition-all hover:border-[#3a3a3a] focus:border-[#58a6ff] disabled:cursor-not-allowed disabled:opacity-50 border-l-2 focus:border-l-[#58a6ff] hover:border-l-[#3a3a3a]"
          aria-haspopup="listbox"
          aria-expanded={isOpen}
        >
          <div className="flex items-center justify-between gap-3">
            <span className="flex-1 min-w-0 truncate">
              {selectedOption ? (
                <span>
                  {selectedOption.label}
                  {selectedOption.provider && (
                    <span className="ml-2 text-[#666666]">{selectedOption.provider}</span>
                  )}
                </span>
              ) : (
                <span className="text-[#666666]">{placeholder}</span>
              )}
            </span>
            <span className="text-[#666666] flex-shrink-0" aria-hidden="true">
              {isOpen ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
            </span>
          </div>
        </button>
      ) : (
        <input
          id={id}
          ref={inputRef}
          type="text"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          onBlur={(e) => {
            if (!e.target.value.trim()) {
              setIsCustomMode(false);
            }
          }}
          onKeyDown={handleKeyDown}
          placeholder="Enter custom model name"
          className="w-full border border-[#58a6ff] bg-[#111111] px-3 py-2 text-sm font-mono text-[#e0e0e0] outline-none focus:border-l-[#58a6ff] border-l-2 transition-all"
        />
      )}

      {isOpen && !isCustomMode && (
        <div className="absolute z-10 mt-1 max-h-60 w-full overflow-auto border border-[#2a2a2a] bg-[#111111] shadow-lg">
          <div className="border-b border-[#1a1a1a] p-3">
            <div className="relative group">
              <Search className="absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-[#666666] group-focus-within:text-[#58a6ff] transition-colors" />
              <input
                type="text"
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                placeholder="Search models..."
                className="w-full bg-transparent py-1.5 pl-8 pr-2 text-sm font-mono text-[#e0e0e0] outline-none border-l-2 border-[#1a1a1a] focus:border-l-[#58a6ff] transition-colors"
                autoFocus
              />
            </div>
          </div>
          <ul role="listbox" className="py-1">
            {filteredOptions.length === 0 ? (
              <li className="px-3 py-4 text-center">
                <div className="flex items-center justify-center gap-2 text-xs font-mono text-[#666666]">
                  <div className="h-px w-8 bg-[#2a2a2a]" />
                  <span>No models found</span>
                  <div className="h-px w-8 bg-[#2a2a2a]" />
                </div>
              </li>
            ) : (
              filteredOptions.map((option) => (
                <li
                  key={option.value}
                  role="option"
                  aria-selected={value === option.value}
                  onClick={() => handleSelect(option.value)}
                  className={`cursor-pointer px-3 py-2 text-sm font-mono transition-colors border-l-2 ${
                    value === option.value
                      ? 'border-l-[#58a6ff] bg-[#1d4c7d]/30 text-[#8dc3ff]'
                      : 'border-l-transparent text-[#e0e0e0] hover:border-l-[#2a2a2a] hover:bg-[#1a1a1a]'
                  }`}
                >
                  <div className="flex items-center justify-between">
                    <span className="truncate">{option.label}</span>
                    {option.provider && (
                      <span className="text-xs text-[#666666] ml-2">{option.provider}</span>
                    )}
                  </div>
                </li>
              ))
            )}
            {allowCustom && (
              <>
                <li className="my-1 border-t border-[#1a1a1a]" role="separator" />
                <li
                  role="option"
                  onClick={handleCustomMode}
                  className="cursor-pointer px-3 py-2 text-sm font-mono text-[#888888] transition-colors hover:text-[#e0e0e0] hover:bg-[#1a1a1a]"
                >
                  + Custom model...
                </li>
              </>
            )}
          </ul>
        </div>
      )}
    </div>
  );
};
