import { useEffect } from 'react';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import type { ModelOption } from 'state/useModels';
import { getProviderDisplayName } from 'state/useModels';
import type { ChatMessage } from '../types';

const PROVIDER_DISPLAY: Record<string, string> = {
  anthropic: 'Anthropic',
  openai: 'OpenAI',
  google: 'Google',
  groq: 'Groq',
  mistral: 'Mistral',
  xai: 'xAI',
  openrouter: 'OpenRouter',
  huggingface: 'Hugging Face',
  'github-copilot': 'GitHub Copilot',
  minimax: 'MiniMax',
  bedrock: 'Amazon Bedrock',
  'google-vertex': 'Google Vertex AI',
  'azure-openai': 'Azure OpenAI',
  'claude-code': 'Claude Code',
  opencode: 'OpenCode Zen',
};

type ModelSelectorProps = {
  messages: ChatMessage[];
  availableModels: ModelOption[];
  selectedModel: string | null;
  onModelChange: (modelId: string) => void;
  model: string | null;
  isConnected: boolean;
  isGenerating: boolean;
  hasStarted: boolean;
  thinkingLevel: string | null;
  onThinkingChange: (level: string | null) => void;
};

export function ModelSelector({
  messages,
  availableModels,
  selectedModel,
  onModelChange,
  model,
  isConnected,
  isGenerating,
  hasStarted,
  thinkingLevel,
  onThinkingChange,
}: ModelSelectorProps) {
  const providers = [...new Set(availableModels.map((m) => m.provider).filter(Boolean))] as string[];

  // Determine which model to display: selectedModel takes precedence, then model (from server), then fallback
  const displayModel = selectedModel || model;

  const activeProvider = availableModels.find((m) => m.id === displayModel)?.provider ?? providers[0];
  const providerModels = availableModels.filter((m) => m.provider === activeProvider);
  const fallbackModelId = providerModels[0]?.id ?? null;

  // Sync actual selection when UI shows a fallback provider but nothing is selected
  useEffect(() => {
    if (!selectedModel && !model && fallbackModelId) {
      onModelChange(fallbackModelId);
    }
  }, [selectedModel, model, fallbackModelId]);

  // Lock after session has started
  const isLocked = hasStarted || isGenerating || !isConnected;

  const handleProviderClick = (provider: string) => {
    if (isLocked) return;
    const firstModel = availableModels.find((m) => m.provider === provider);
    if (firstModel) onModelChange(firstModel.id);
  };

  const displayName = (provider: string) => {
    // Handle local providers (officer-local-{uuid})
    if (provider.startsWith('officer-local-')) {
      return getProviderDisplayName(provider);
    }
    return PROVIDER_DISPLAY[provider] ?? provider;
  };

  // Get display text for the model
  const getModelDisplayText = () => {
    if (displayModel) {
      const found = availableModels.find((m) => m.id === displayModel);
      return found?.name || displayModel;
    }
    return 'Select model';
  };

  return (
    <div className="flex items-center justify-between mt-2">
      {isLocked ? (
        <span className="rounded-md bg-duck-dark/80 px-3 py-1 text-xs font-medium text-white">
          {activeProvider ? displayName(activeProvider) : 'Chat'}
        </span>
      ) : (
        <div className="flex items-center gap-1 rounded-lg bg-background/60 p-1">
          {providers.map((provider) => (
            <button
              key={provider}
              onClick={() => handleProviderClick(provider)}
              className={`rounded-md px-3 py-1 text-xs font-medium transition-colors cursor-pointer ${
                activeProvider === provider
                  ? 'bg-duck-dark/80 text-white shadow-sm'
                  : 'text-duck-dark/70 hover:text-duck-dark/90'
              }`}
            >
              {displayName(provider)}
            </button>
          ))}
        </div>
      )}
      <div className="flex items-center gap-2">
        {availableModels.find((m) => m.id === displayModel)?.reasoning && (
          <ThinkingToggle
            enabled={thinkingLevel === 'high'}
            onToggle={() => onThinkingChange(thinkingLevel === 'high' ? 'off' : 'high')}
            disabled={isGenerating}
          />
        )}
        <div className="text-xs text-duck-dark/50">
          {providerModels.length > 0 ? (
            <Select
              value={displayModel ?? fallbackModelId ?? undefined}
              onValueChange={(v) => !isLocked && onModelChange(v)}
              disabled={isLocked}
            >
              <SelectTrigger className="h-auto border-0 bg-transparent p-0 text-xs text-duck-dark/50 shadow-none focus:ring-0 gap-1 cursor-pointer">
                <SelectValue />
              </SelectTrigger>
              <SelectContent className="z-[800]" side="top">
                {providerModels.map((m) => (
                  <SelectItem key={m.id} value={m.id}>
                    {m.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          ) : (
            <span>{getModelDisplayText()}</span>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Thinking Toggle ──

type ThinkingToggleProps = {
  enabled: boolean;
  onToggle: () => void;
  disabled: boolean;
};

const ThinkingToggle = ({ enabled, onToggle, disabled }: ThinkingToggleProps) => (
  <button
    type="button"
    onClick={onToggle}
    disabled={disabled}
    title={enabled ? 'Thinking enabled (click to disable)' : 'Thinking disabled (click to enable)'}
    className={`rounded-md px-2 py-0.5 text-xs font-medium transition-colors cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed ${
      enabled ? 'bg-duck-teal/15 text-duck-teal' : 'text-duck-dark/40 hover:text-duck-dark/60'
    }`}
  >
    {enabled ? 'think' : 'no think'}
  </button>
);
