import { useEffect, useState } from 'react';
import { Check, ChevronDown, Cpu } from 'lucide-react';
import { api } from '@/api/client';
import type { Provider } 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 {
  provider: string;
  model: string;
  onChange: (provider: string, model: string) => void | Promise<void>;
}

function ProviderModelList({
  providers,
  error,
  currentProvider,
  currentModel,
  onPick,
}: {
  providers: Provider[] | null;
  error: string | null;
  currentProvider: string;
  currentModel: string;
  onPick: (provider: string, model: string) => void;
}) {
  if (error) {
    return <div className="px-2 py-1.5 text-xs text-destructive">{error}</div>;
  }
  if (providers === null) {
    return <div className="px-2 py-1.5 text-xs text-muted-foreground">Loading...</div>;
  }

  const singleProvider = providers.length === 1;

  return (
    <>
      {providers.map((p) => (
        <div key={p.name}>
          {!singleProvider && (
            <div className="px-2 pt-2 pb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70">
              {p.label}
            </div>
          )}
          {p.models.map((m) => (
            <button
              key={`${p.name}:${m.id}`}
              type="button"
              onClick={() => onPick(p.name, 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 shrink-0 ${
                  p.name === currentProvider && m.id === currentModel
                    ? 'opacity-100'
                    : 'opacity-0'
                }`}
              />
              <span className="truncate">{m.label}</span>
            </button>
          ))}
        </div>
      ))}
    </>
  );
}

export function ProviderPicker({ provider, model, onChange }: Props) {
  const { isMobile } = useViewport();
  const [providers, setProviders] = useState<Provider[] | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [open, setOpen] = useState(false);

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

  function handlePick(prov: string, mod: string) {
    setOpen(false);
    void onChange(prov, mod);
  }

  const currentProviderLabel =
    providers?.find((p) => p.name === provider)?.label ?? provider;

  const triggerText = providers && providers.length > 1
    ? `${currentProviderLabel} / ${model}`
    : model;

  if (isMobile) {
    return (
      <>
        <button
          type="button"
          onClick={() => setOpen(true)}
          aria-label={`Provider: ${currentProviderLabel}, Model: ${model}`}
          title={`${currentProviderLabel} / ${model}`}
          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="Provider / Model">
          <div className="px-2 py-2 space-y-1">
            <ProviderModelList
              providers={providers}
              error={error}
              currentProvider={provider}
              currentModel={model}
              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 max-w-[260px]"
        >
          <span className="truncate">{triggerText}</span>
          <ChevronDown className="size-3 opacity-70 shrink-0" />
        </button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="max-h-80 overflow-y-auto min-w-[200px]">
        {error && (
          <div className="px-2 py-1.5 text-xs text-destructive">{error}</div>
        )}
        {providers === null && !error && (
          <div className="px-2 py-1.5 text-xs text-muted-foreground">Loading...</div>
        )}
        {providers && providers.map((p) => {
          const singleProvider = providers.length === 1;
          return (
            <div key={p.name}>
              {!singleProvider && (
                <div className="px-2 pt-2 pb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70 select-none">
                  {p.label}
                </div>
              )}
              {p.models.map((m) => (
                <DropdownMenuItem
                  key={`${p.name}:${m.id}`}
                  onSelect={() => handlePick(p.name, m.id)}
                  className="font-mono text-xs"
                >
                  <Check
                    className={`size-3 shrink-0 ${
                      p.name === provider && m.id === model
                        ? 'opacity-100'
                        : 'opacity-0'
                    }`}
                  />
                  {m.label}
                </DropdownMenuItem>
              ))}
            </div>
          );
        })}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
