import { useEffect, useState } from 'react';
import { Check, ChevronDown, Cpu } from 'lucide-react';
import { api } from '@/api/client';
import type { ModelInfo } from '@/api/types';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { BottomSheet } from '@/components/BottomSheet';
import { useViewport } from '@/hooks/useViewport';

interface Props {
  value: string;
  onChange: (model: string) => void | Promise<void>;
}

// v1.9: shared list rendered inside both shells. Lazy-fetches /api/models on
// first open so the picker doesn't pay for a request when it's never shown.
function ModelList({
  models,
  error,
  value,
  onPick,
}: {
  models: ModelInfo[] | null;
  error: string | null;
  value: string;
  onPick: (id: string) => void;
}) {
  if (error) {
    return <div className="px-2 py-1.5 text-xs text-destructive">{error}</div>;
  }
  if (models === null) {
    return <div className="px-2 py-1.5 text-xs text-muted-foreground">Loading…</div>;
  }
  return (
    <>
      {models.map((m) => (
        <button
          key={m.id}
          type="button"
          onClick={() => onPick(m.id)}
          className="w-full text-left flex items-center gap-2 font-mono text-xs px-2 py-1.5 hover:bg-accent rounded"
        >
          <Check className={`size-3 ${m.id === value ? 'opacity-100' : 'opacity-0'}`} />
          <span className="truncate">{m.id}</span>
        </button>
      ))}
    </>
  );
}

export function ModelPicker({ value, onChange }: Props) {
  const { isMobile } = useViewport();
  const [models, setModels] = useState<ModelInfo[] | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [open, setOpen] = useState(false);

  useEffect(() => {
    if (!open || models !== null) return;
    api
      .models()
      .then(setModels)
      .catch((err) =>
        setError(err instanceof Error ? err.message : 'failed to load models'),
      );
  }, [open, models]);

  function handlePick(id: string) {
    setOpen(false);
    void onChange(id);
  }

  // v1.9: mobile = icon-only trigger + bottom-sheet shell. Desktop = labeled
  // trigger (model name + chevron) + dropdown. Same ModelList under the hood.
  if (isMobile) {
    return (
      <>
        <button
          type="button"
          onClick={() => setOpen(true)}
          aria-label={`Model: ${value}`}
          title={value}
          className="inline-flex items-center justify-center min-h-[44px] min-w-[44px] rounded text-muted-foreground hover:text-foreground"
        >
          <Cpu className="size-4" />
        </button>
        <BottomSheet open={open} onClose={() => setOpen(false)} title="Model">
          <div className="px-2 py-2 space-y-1">
            <ModelList models={models} error={error} value={value} onPick={handlePick} />
          </div>
        </BottomSheet>
      </>
    );
  }

  return (
    <DropdownMenu open={open} onOpenChange={setOpen}>
      <DropdownMenuTrigger asChild>
        <button
          type="button"
          className="text-xs font-mono text-muted-foreground hover:text-foreground flex items-center gap-1 px-1.5 py-0.5 rounded hover:bg-muted/60"
        >
          {value}
          <ChevronDown className="size-3 opacity-70" />
        </button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="max-h-72 min-w-[16rem] overflow-y-auto">
        {error && (
          <div className="px-2 py-1.5 text-xs text-destructive">{error}</div>
        )}
        {models === null && !error && (
          <div className="px-2 py-1.5 text-xs text-muted-foreground">Loading…</div>
        )}
        {models?.map((m) => (
          <DropdownMenuItem
            key={m.id}
            onSelect={() => handlePick(m.id)}
            className="font-mono text-xs"
          >
            <Check
              className={`size-3 ${m.id === value ? 'opacity-100' : 'opacity-0'}`}
            />
            {m.id}
          </DropdownMenuItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
