import { useState, useEffect, useRef } from 'react';
import { ChevronDown, Bot, Check } from 'lucide-react';
import { t } from '@/lib/i18n';
import { optionalKylinUserIdForPersist } from '@/lib/kylinPersist';
import { loadTrialModels, loadConfiguredModels, type ModelInfo } from '@/lib/models';

export interface ModelSelectorProps {
  /** Currently selected model value */
  currentModel?: string;
  /** Currently selected model provider */
  currentProvider?: string;
  /** Callback when a model is selected */
  onSelect: (model: ModelInfo) => void;
  /** Send a WebSocket message to set the model */
  sendWsMessage?: (payload: object) => void;
  /** Whether the WebSocket is connected */
  connected: boolean;
}

export default function ModelSelector({
  currentModel,
  currentProvider,
  onSelect,
  sendWsMessage,
  connected,
}: ModelSelectorProps) {
  const [open, setOpen] = useState(false);
  const [configuredModels, setConfiguredModels] = useState<ModelInfo[]>([]);
  const [trialModels, setTrialModels] = useState<ModelInfo[]>([]);
  const [loading, setLoading] = useState(false);
  const [pressedItem, setPressedItem] = useState<string | null>(null);
  const [hoveredItem, setHoveredItem] = useState<string | null>(null);
  const menuRef = useRef<HTMLDivElement>(null);

  // Close menu when clicking outside
  useEffect(() => {
    if (!open) return;
    const handler = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
        setOpen(false);
      }
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [open]);

  const fetchModels = async () => {
    setLoading(true);
    try {
      const [trial, configured] = await Promise.all([loadTrialModels(), loadConfiguredModels()]);
      setTrialModels(trial);
      setConfiguredModels(
        configured.map((model: ModelInfo) => ({
          ...model,
          description: model.description ?? t('agent.model_selector_configured'),
        })),
      );
    } catch {
      // Silently ignore errors
    } finally {
      setLoading(false);
    }
  };

  // Load models on mount to ensure currentLabel can be resolved
  useEffect(() => {
    void fetchModels();
  }, []);

  const handleOpen = async () => {
    if (open) {
      setOpen(false);
      return;
    }
    setOpen(true);
    await fetchModels();
  };

  const handleSelect = (model: ModelInfo) => {
    const normalizedProvider =
      model.provider === 'custom' && model.baseUrl?.trim()
        ? `custom:${model.baseUrl.trim()}`
        : model.provider;
    const normalizedModel = {
      ...model,
      provider: normalizedProvider,
    };
    if (sendWsMessage && connected) {
      const apiKey =
        normalizedModel.provider === 'kylin-proxy' ? optionalKylinUserIdForPersist() : undefined;
      sendWsMessage({
        type: 'set_model',
        provider: normalizedModel.provider,
        model: normalizedModel.value,
        api_key: apiKey,
      });
    }
    onSelect(normalizedModel);
    setOpen(false);
  };

  const isModelSelected = (model: ModelInfo) => {
    if (!currentModel) return false;
    if (currentProvider && currentModel === model.value && currentProvider === model.provider) {
      return true;
    }
    if (currentModel !== model.value) return false;
    const allModels = [...trialModels, ...configuredModels];
    const sameValueModels = allModels.filter((item) => item.value === currentModel);
    return sameValueModels.length === 1 && sameValueModels[0]?.provider === model.provider;
  };

  const fallbackCurrentModel = configuredModels[0];
  const currentLabel =
    trialModels.find((m) => m.value === currentModel && (currentProvider ? m.provider === currentProvider : true))?.label
    ?? configuredModels.find((m) => m.value === currentModel && (currentProvider ? m.provider === currentProvider : true))?.label
    ?? fallbackCurrentModel?.label
    ?? currentModel
    ?? t('agent.model_selector_title');

  return (
    <div className="relative" ref={menuRef}>
      <button
        type="button"
        onClick={handleOpen}
        disabled={!connected}
        className="inline-flex items-center gap-1 text-[12px] leading-none transition-all disabled:opacity-40 h-[36px] w-auto px-2 rounded-lg"
        style={{
          color: '#262626',
          background: open
            ? 'rgba(0, 0, 0, 0.08)'
            : 'rgba(0, 0, 0, 0.03)',
        }}
        onMouseEnter={(e) => {
          if (!open) {
            e.currentTarget.style.background = 'rgba(0, 0, 0, 0.05)';
          }
        }}
        onMouseLeave={(e) => {
          if (!open) {
            e.currentTarget.style.background = 'rgba(0, 0, 0, 0.03)';
          }
        }}
      >
        <Bot className="h-4 w-4 opacity-[0.86] flex-shrink-0" />
        <span className="max-w-[208px] truncate">{currentLabel}</span>
        <ChevronDown
          className="h-4 w-4 opacity-60 transition-transform flex-shrink-0"
          style={{ transform: open ? 'rotate(180deg)' : 'none' }}
        />
      </button>

      {open && (
        <div
          className="absolute bottom-full left-0 mb-2 rounded-lg overflow-hidden animate-fade-in"
          style={{
            width: '290px',
            background: '#FFFFFF',
            border: '1px solid rgba(0, 0, 0, 0.1)',
            borderRadius: '8px',
            boxShadow: '0 4px 20px rgba(0, 0, 0, 0.2)',
            zIndex: 9999,
            maxHeight: '378px',
          }}
        >
          <div
            className="overflow-y-auto"
            style={{
              maxHeight: '376px',
            }}
          >
            <div className="py-[7px] px-1">
              <div className="space-y-[2px]">
                <div
                  className="py-1.5 text-[10px] font-semibold uppercase tracking-wider"
                  style={{ color: 'rgba(0, 0, 0, 0.35)', paddingLeft: '32px' }}
                >
                  {t('agent.model_selector_trial')}
                </div>
                {trialModels.map((model) => {
                  const isSelected = isModelSelected(model);
                  const isPressed = pressedItem === `trial-${model.value}`;
                  const isHovered = hoveredItem === `trial-${model.value}`;
                  const showWhite = isPressed || isHovered;
                  return (
                    <button
                      key={`trial-${model.value}`}
                      type="button"
                      onClick={() => handleSelect(model)}
                      onMouseDown={() => setPressedItem(`trial-${model.value}`)}
                      onMouseUp={() => setPressedItem(null)}
                      onMouseEnter={() => setHoveredItem(`trial-${model.value}`)}
                      onMouseLeave={() => {
                        setHoveredItem(null);
                        setPressedItem(null);
                      }}
                      className="w-full text-left flex items-center gap-2 transition-colors"
                      style={{
                        height: '36px',
                        borderRadius: '6px',
                        padding: '0 8px',
                        background: isPressed
                          ? 'rgba(44, 115, 200, 1)'
                          : isHovered
                            ? 'rgba(55, 144, 250, 1)'
                            : 'transparent',
                      }}
                    >
                      <div
                        className="w-4 h-4 flex-shrink-0 flex items-center justify-center"
                        style={{ opacity: isSelected ? 1 : 0 }}
                      >
                        <Check
                          className="h-4 w-4"
                          style={{ color: showWhite ? '#FFFFFF' : 'currentColor' }}
                        />
                      </div>
                      <Bot
                        className="h-4 w-4 flex-shrink-0"
                        style={{ color: showWhite ? '#FFFFFF' : 'currentColor' }}
                      />
                      <span
                        className="model-label text-[13px] font-medium truncate flex-1"
                        style={{ color: showWhite ? '#FFFFFF' : 'rgba(0, 0, 0, 0.85)' }}
                      >
                        {model.label}
                      </span>
                    </button>
                  );
                })}
              </div>

              {configuredModels.length > 0 && (
                <div className="space-y-[2px] mt-[2px]">
                  <div
                    className="py-1.5 text-[10px] font-semibold uppercase tracking-wider"
                    style={{ color: 'rgba(0, 0, 0, 0.35)', paddingLeft: '32px' }}
                  >
                    {t('agent.model_selector_configured')}
                  </div>
                  {configuredModels.map((model) => {
                    const isSelected = isModelSelected(model);
                    const configuredItemKey = `configured-${model.provider}-${model.value}`;
                    const isPressed = pressedItem === configuredItemKey;
                    const isHovered = hoveredItem === configuredItemKey;
                    const showWhite = isPressed || isHovered;
                    return (
                      <button
                        key={configuredItemKey}
                        type="button"
                        onClick={() => handleSelect(model)}
                        onMouseDown={() => setPressedItem(configuredItemKey)}
                        onMouseUp={() => setPressedItem(null)}
                        onMouseEnter={() => setHoveredItem(configuredItemKey)}
                        onMouseLeave={() => {
                          setHoveredItem(null);
                          setPressedItem(null);
                        }}
                        className="w-full text-left flex items-center gap-2 transition-colors"
                        style={{
                          height: '36px',
                          borderRadius: '6px',
                          padding: '0 8px',
                          background: isPressed
                            ? 'rgba(44, 115, 200, 1)'
                            : isHovered
                              ? 'rgba(55, 144, 250, 1)'
                              : 'transparent',
                        }}
                      >
                        <div
                          className="w-4 h-4 flex-shrink-0 flex items-center justify-center"
                          style={{ opacity: isSelected ? 1 : 0 }}
                        >
                          <Check
                            className="h-4 w-4"
                            style={{ color: showWhite ? '#FFFFFF' : 'currentColor' }}
                          />
                        </div>
                        <Bot
                          className="h-4 w-4 flex-shrink-0"
                          style={{ color: showWhite ? '#FFFFFF' : 'currentColor' }}
                        />
                        <span
                          className="model-label text-[13px] font-medium truncate flex-1"
                          style={{ color: showWhite ? '#FFFFFF' : 'rgba(0, 0, 0, 0.85)' }}
                        >
                          {model.label}
                        </span>
                      </button>
                    );
                  })}
                </div>
              )}

              {loading && configuredModels.length === 0 && (
                <div className="px-4 py-3 text-[12px]" style={{ color: 'rgba(0, 0, 0, 0.35)' }}>
                  {t('common.loading')}
                </div>
              )}

              {!loading && configuredModels.length === 0 && (
                <div className="px-4 py-3 text-[12px]" style={{ color: 'rgba(0, 0, 0, 0.35)' }}>
                  {t('agent.model_selector_no_configured')}
                </div>
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
