import { useEffect, useRef, useState, type CSSProperties } from 'react';

export interface ModelCapability {
  /** Short id (e.g. 'vision', 'tools', 'streaming'). */
  id: string;
  /** Human-friendly label rendered in the chip. */
  label: string;
}

export interface ModelOption {
  /** Stable model id (e.g. 'gpt-4o', 'claude-3-5-sonnet'). */
  id: string;
  /** Display name. */
  name: string;
  /** Provider label (e.g. 'OpenAI', 'Anthropic', 'Local'). */
  provider: string;
  /** Optional avatar / glyph for the provider. */
  providerGlyph?: string;
  /** Cost per 1k input tokens (USD), used for sort + display. */
  inputCostPer1k?: number;
  /** Cost per 1k output tokens (USD). */
  outputCostPer1k?: number;
  /** Typical latency ms (P50). */
  latencyMs?: number;
  /** Context window size in tokens. */
  contextTokens?: number;
  /** Capability chips rendered next to the model name. */
  capabilities?: ModelCapability[];
  /** Mark the model as unavailable (greyed out, unselectable). */
  disabled?: boolean;
  /** Optional short description. */
  description?: string;
}

export interface ModelPickerProps {
  models: ModelOption[];
  value: string;
  onChange: (modelId: string) => void;
  /** Show cost cells. Default: true. */
  showCost?: boolean;
  /** Show latency cells. Default: true. */
  showLatency?: boolean;
  /** Trigger label override (default: the active model's name). */
  triggerLabel?: string;
  className?: string;
  style?: CSSProperties;
}

/**
 * `<ModelPicker>` — dropdown that exposes the full capability profile
 * of each available LLM. Designed for the top of a chat surface where
 * power-users want to swap models mid-conversation.
 *
 * Shows: provider · name · capability chips · ctx window · cost · latency.
 * Closes on outside-click and Escape.
 */
export function ModelPicker({
  models,
  value,
  onChange,
  showCost = true,
  showLatency = true,
  triggerLabel,
  className,
  style,
}: ModelPickerProps) {
  const [open, setOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!open) return;
    const handler = (e: MouseEvent) => {
      if (!rootRef.current?.contains(e.target as Node)) setOpen(false);
    };
    const keys = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setOpen(false);
    };
    document.addEventListener('mousedown', handler);
    document.addEventListener('keydown', keys);
    return () => {
      document.removeEventListener('mousedown', handler);
      document.removeEventListener('keydown', keys);
    };
  }, [open]);

  const active = models.find(m => m.id === value);

  return (
    <div
      ref={rootRef}
      data-testid="bl-model-picker"
      className={className}
      style={{ position: 'relative', display: 'inline-block', ...style }}
    >
      <button
        type="button"
        data-testid="bl-model-picker-trigger"
        aria-haspopup="listbox"
        aria-expanded={open}
        onClick={() => setOpen(o => !o)}
        style={{
          display: 'inline-flex',
          alignItems: 'center',
          gap: 'var(--bl-space-2, 8px)',
          padding: 'var(--bl-space-1, 4px) var(--bl-space-2, 8px)',
          background: 'var(--bl-surface-card, #fff)',
          border: '1px solid var(--bl-border, rgba(0,0,0,0.12))',
          borderRadius: 'var(--bl-radius-pill, 999px)',
          color: 'var(--bl-text-primary, inherit)',
          fontSize: '0.85rem',
          cursor: 'pointer',
          minWidth: 0,
        }}
      >
        {active?.providerGlyph && <span aria-hidden>{active.providerGlyph}</span>}
        <span style={{ fontWeight: 600, whiteSpace: 'nowrap' }}>
          {triggerLabel ?? active?.name ?? 'Select model'}
        </span>
        <span aria-hidden style={{ color: 'var(--bl-text-tertiary, #888)' }}>
          ▾
        </span>
      </button>

      {open && (
        <div
          role="listbox"
          data-testid="bl-model-picker-listbox"
          aria-label="Model selector"
          style={{
            position: 'absolute',
            top: 'calc(100% + 6px)',
            right: 0,
            zIndex: 50,
            minWidth: 340,
            maxWidth: 480,
            maxHeight: 420,
            overflowY: 'auto',
            background: 'var(--bl-surface-card, #fff)',
            border: '1px solid var(--bl-border, rgba(0,0,0,0.12))',
            borderRadius: 'var(--bl-radius-card, 10px)',
            boxShadow: '0 16px 40px rgba(0,0,0,0.20)',
            padding: 'var(--bl-space-1, 4px)',
          }}
        >
          {models.map(m => (
            <button
              key={m.id}
              type="button"
              role="option"
              aria-selected={m.id === value}
              data-testid={`bl-model-picker-option-${m.id}`}
              disabled={m.disabled}
              onClick={() => {
                onChange(m.id);
                setOpen(false);
              }}
              style={{
                display: 'block',
                width: '100%',
                textAlign: 'left',
                padding: 'var(--bl-space-2, 8px) var(--bl-space-3, 12px)',
                background:
                  m.id === value
                    ? 'var(--bl-accent-muted, rgba(99,102,241,0.12))'
                    : 'transparent',
                border: 'none',
                borderRadius: 'var(--bl-radius-control, 6px)',
                color: m.disabled
                  ? 'var(--bl-text-tertiary, #888)'
                  : 'var(--bl-text-primary, inherit)',
                cursor: m.disabled ? 'not-allowed' : 'pointer',
                opacity: m.disabled ? 0.5 : 1,
              }}
            >
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
                <span style={{ fontWeight: 600, fontSize: '0.9rem' }}>{m.name}</span>
                <span
                  style={{
                    fontSize: '0.7rem',
                    color: 'var(--bl-text-tertiary, #888)',
                  }}
                >
                  {m.provider}
                </span>
                {m.capabilities && m.capabilities.length > 0 && (
                  <span style={{ marginLeft: 'auto', display: 'flex', gap: 4 }}>
                    {m.capabilities.map(c => (
                      <span
                        key={c.id}
                        style={{
                          fontSize: '0.65rem',
                          padding: '1px 6px',
                          borderRadius: 'var(--bl-radius-pill, 999px)',
                          background: 'var(--bl-surface-muted, rgba(0,0,0,0.05))',
                          color: 'var(--bl-text-secondary, #555)',
                        }}
                      >
                        {c.label}
                      </span>
                    ))}
                  </span>
                )}
              </div>
              {m.description && (
                <div
                  style={{
                    fontSize: '0.75rem',
                    color: 'var(--bl-text-secondary, #555)',
                    marginTop: 2,
                  }}
                >
                  {m.description}
                </div>
              )}
              {(showCost || showLatency || m.contextTokens) && (
                <div
                  style={{
                    display: 'flex',
                    gap: 12,
                    marginTop: 6,
                    fontSize: '0.7rem',
                    color: 'var(--bl-text-tertiary, #888)',
                  }}
                >
                  {showCost && typeof m.inputCostPer1k === 'number' && (
                    <span>
                      ${m.inputCostPer1k.toFixed(3)} in
                      {typeof m.outputCostPer1k === 'number' &&
                        ` · $${m.outputCostPer1k.toFixed(3)} out`}
                      /1k
                    </span>
                  )}
                  {showLatency && typeof m.latencyMs === 'number' && (
                    <span>~{m.latencyMs}ms</span>
                  )}
                  {m.contextTokens && (
                    <span>{(m.contextTokens / 1000).toFixed(0)}k ctx</span>
                  )}
                </div>
              )}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}
