/**
 * Shared provider + model selector for agent provider configuration.
 * Used by both the Settings page (global agent provider) and the Agent
 * Tasks page (per-task provider override).
 */
import { Cloud, Server, Cpu } from 'lucide-react';
import { Input } from '../ui/input';
import { Badge } from '../ui/badge';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '../ui/select';
import { ModelSelectField } from './ModelSelectField';
import { defaultBaseUrlForProvider, providerSupportsHarness, type ProviderInfo } from '../../hooks/use-providers';

// Display labels for the `agent.harness` field. Keys are the persisted
// identifier values (kept stable for back-compat with user configs);
// values are the user-facing strings shown in the runtime dropdown.
const HARNESS_LABELS: Record<string, string> = {
  'claude-sdk': 'Claude Agents',
  'openai-agents': 'OpenAI Agents',
};

const PROVIDER_LABELS: Record<string, string> = {
  anthropic: 'Anthropic',
  ollama: 'Ollama',
  lmstudio: 'LM Studio',
  openai: 'OpenAI',
  openrouter: 'OpenRouter',
  'openai-compatible': 'OpenAI-compatible',
};

const PROVIDER_ICONS: Record<string, typeof Cloud> = {
  anthropic: Cloud,
  ollama: Server,
  lmstudio: Cpu,
  openai: Cloud,
  openrouter: Cloud,
  'openai-compatible': Server,
};

const OPENAI_COMPATIBLE_BACKEND_OPTIONS = [
  { value: 'lmstudio', label: 'LM Studio' },
  { value: 'ollama', label: 'Ollama' },
] as const;

export interface ProviderModelSelectorProps {
  harness: string;
  providerType: string;
  localBackend?: 'ollama' | 'lmstudio' | '';
  model: string;
  baseUrl: string;
  contextLength: string;
  modelPlaceholder?: string;
  providers: ProviderInfo[];
  isLoadingProviders: boolean;
  showHarnessSelector?: boolean;
  /** When false, the model picker is hidden — used where the model is
   *  derived from a reasoning profile and exposed elsewhere (Task Config). */
  showModelSelector?: boolean;
  onHarnessChange: (harness: string) => void;
  onProviderChange: (type: string) => void;
  onLocalBackendChange?: (localBackend: 'ollama' | 'lmstudio' | '') => void;
  onModelChange: (model: string) => void;
  onBaseUrlChange: (url: string) => void;
  onContextLengthChange: (ctx: string) => void;
  /** Optional blur handlers — when present, callers commit text-input edits
   *  on blur rather than on every keystroke. */
  onBaseUrlBlur?: () => void;
  onContextLengthBlur?: () => void;
}

export function ProviderModelSelector({
  harness,
  providerType,
  localBackend = '',
  model,
  baseUrl,
  contextLength,
  modelPlaceholder,
  providers,
  isLoadingProviders,
  showHarnessSelector = true,
  showModelSelector = true,
  onHarnessChange,
  onProviderChange,
  onLocalBackendChange,
  onModelChange,
  onBaseUrlChange,
  onContextLengthChange,
  onBaseUrlBlur,
  onContextLengthBlur,
}: ProviderModelSelectorProps) {
  const providersForHarness = providers.filter((provider) => providerSupportsHarness(provider.type, harness as 'claude-sdk' | 'openai-agents'));
  const selectedProvider = providers.find((p) => p.type === providerType);
  const isLocal = providerType === 'ollama' || providerType === 'lmstudio' || providerType === 'openai-compatible';
  const resolvedBaseUrl = baseUrl || defaultBaseUrlForProvider(providerType as 'ollama' | 'lmstudio' | 'openai-compatible' | undefined, localBackend, selectedProvider?.baseUrl);

  return (
    <div className="space-y-3">
      {showHarnessSelector && (
        <div className="space-y-1">
          <label className="font-sans text-xs text-on-surface-variant">Runtime</label>
          <Select value={harness} onValueChange={onHarnessChange}>
            <SelectTrigger>
              <SelectValue placeholder="Select a runtime" />
            </SelectTrigger>
            <SelectContent>
              {Object.entries(HARNESS_LABELS).map(([value, label]) => (
                <SelectItem key={value} value={value}>
                  {label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
      )}

      {/* Provider selector — derived from /providers response order */}
      <div className="grid grid-cols-3 gap-2">
        {providersForHarness.map((info) => {
          const Icon = PROVIDER_ICONS[info.type];
          if (!Icon) return null;
          const isSelected = providerType === info.type;
          return (
            <button
              key={info.type}
              onClick={() => onProviderChange(info.type)}
              className={`
                flex flex-col items-center gap-1.5 rounded-md border px-3 py-2.5 transition-colors
                ${isSelected
                  ? 'border-primary/40 bg-primary/5 text-on-surface'
                  : 'border-[var(--ghost-border)] bg-surface-container-lowest text-on-surface-variant hover:border-primary/20'
                }
              `}
            >
              <Icon className="h-4 w-4" />
              <span className="font-sans text-xs font-medium">{PROVIDER_LABELS[info.type] ?? info.type}</span>
              {!isLoadingProviders && (
                <Badge
                  variant={info.authConfigured === false || !info.available ? 'destructive' : 'secondary'}
                  className="text-[10px] px-1.5 py-0"
                >
                  {info.authConfigured === false ? 'key required' : info.available ? 'online' : 'offline'}
                </Badge>
              )}
            </button>
          );
        })}
      </div>

      {/* Base URL (local providers only) */}
      {isLocal && (
        <div className="space-y-1">
          <label className="font-sans text-xs text-on-surface-variant">Base URL</label>
          <Input
            value={baseUrl}
            onChange={(e) => onBaseUrlChange(e.target.value)}
            onBlur={onBaseUrlBlur}
            placeholder={resolvedBaseUrl}
          />
        </div>
      )}

      {providerType === 'openai-compatible' && onLocalBackendChange && (
        <div className="space-y-1">
          <label className="font-sans text-xs text-on-surface-variant">Local Backend</label>
          <Select value={localBackend || 'lmstudio'} onValueChange={(value) => onLocalBackendChange(value as 'ollama' | 'lmstudio')}>
            <SelectTrigger>
              <SelectValue placeholder="Select a backend" />
            </SelectTrigger>
            <SelectContent>
              {OPENAI_COMPATIBLE_BACKEND_OPTIONS.map((option) => (
                <SelectItem key={option.value} value={option.value}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <p className="font-sans text-[11px] text-on-surface-variant/70">
            OpenAI-compatible chat endpoints look the same, but local backends
            still need different model-loading and context handling.
          </p>
        </div>
      )}

      {/* Context length (local providers only) */}
      {isLocal && (
        <div className="space-y-1">
          <label className="font-sans text-xs text-on-surface-variant">Context Length</label>
          <Input
            type="number"
            value={contextLength}
            onChange={(e) => onContextLengthChange(e.target.value)}
            onBlur={onContextLengthBlur}
            placeholder="32768 (default)"
          />
          <p className="font-sans text-[11px] text-on-surface-variant/70">
            Leave blank to use the 32K default. Myco creates a Modelfile
            variant at this size so the model loads at the size you asked
            for, not its (much larger) native default.
          </p>
        </div>
      )}

      {/* Model selector — hidden when the caller derives the model from a
          reasoning profile instead (Task Config). */}
      {showModelSelector && (
        <ModelSelectField
          providerType={providerType}
          localBackend={localBackend}
          baseUrl={baseUrl}
          model={model}
          modelPlaceholder={modelPlaceholder}
          providers={providers}
          onModelChange={onModelChange}
        />
      )}
    </div>
  );
}
