import { useState, useEffect, useCallback, useMemo } from "react";
import { motion } from "motion/react";
import { cn } from "@/lib/utils";
import { client } from "@/client";
import type { AiModelListItem } from "@/client/models/aiModelListItem";
import {
  ModelSelector,
  ModelSelectorTrigger,
  ModelSelectorContent,
  ModelSelectorInput,
  ModelSelectorList,
  ModelSelectorEmpty,
  ModelSelectorGroup,
  ModelSelectorItem,
} from "@/components/ai-elements/model-selector";
import { DialogTitle } from "@/components/ui/dialog";
import { getModelIcon } from "./provider-icon";

const STORAGE_KEY = "gitdataai:last-model-id";

function loadLastModelId(sessionId?: string | null): string | null {
  try {
    if (sessionId) {
      const val = localStorage.getItem(`${STORAGE_KEY}:${sessionId}`);
      if (val) return val;
    }
    return localStorage.getItem(STORAGE_KEY);
  } catch {
    return null;
  }
}

function saveLastModelId(modelId: string, sessionId?: string | null) {
  try {
    localStorage.setItem(STORAGE_KEY, modelId);
    if (sessionId) {
      localStorage.setItem(`${STORAGE_KEY}:${sessionId}`, modelId);
    }
  } catch {
    // Storage full or unavailable — non-critical.
  }
}

interface ModelSelectorPopoverProps {
  sessionId?: string | null;
  onModelChange?: (name: string, provider: string) => void;
}

export function ModelSelectorPopover({
  sessionId,
  onModelChange,
}: ModelSelectorPopoverProps) {
  const [models, setModels] = useState<AiModelListItem[]>([]);
  const [selected, setSelected] = useState<string>("");
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [initialised, setInitialised] = useState(false);

  // Load model list.
  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    client
      .aiListModels()
      .then(({ data }) => {
        if (!cancelled) {
          const enabled = data.filter((m) => m.enabled);
          setModels(enabled);
        }
      })
      .catch((err: unknown) => {
        if (!cancelled) {
          console.error("Failed to load models:", err);
        }
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  // Auto-select last-used model once models are loaded.
  useEffect(() => {
    if (initialised || models.length === 0) return;

    const lastId = loadLastModelId(sessionId);
    const matched = lastId ? models.find((m) => m.id === lastId) : null;
    const chosen = matched ?? models[0];
    if (chosen) {
      setSelected(chosen.id);
      onModelChange?.(chosen.name, chosen.provider_name);
    }
    setInitialised(true);
  }, [models, sessionId, initialised, onModelChange]);

  const handleSelect = useCallback(
    (id: string) => {
      setSelected(id);
      saveLastModelId(id, sessionId);
      const model = models.find((m) => m.id === id);
      if (model) onModelChange?.(model.name, model.provider_name);
      setOpen(false);
    },
    [models, sessionId, onModelChange],
  );

  const selectedModel = models.find((m) => m.id === selected);
  const displayName =
    selectedModel?.display_name || selectedModel?.name || "Select model";

  const ProviderIcon = useMemo(
    () => getModelIcon(selectedModel?.name ?? "", selectedModel?.provider_name),
    [selectedModel?.name, selectedModel?.provider_name],
  );

  return (
    <ModelSelector open={open} onOpenChange={setOpen}>
      <ModelSelectorTrigger
        className={cn(
          "flex cursor-pointer items-center gap-1.5 rounded-lg border border-border/60 bg-muted/40 px-2.5 py-1.5 text-xs text-muted-foreground transition-[background-color,border-color,color,box-shadow]",
          "hover:bg-muted/70 hover:text-foreground hover:border-border/80 hover:shadow-sm",
          "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
        )}
        aria-label={`Select model (current: ${displayName})`}
      >
        {ProviderIcon ? (
          <ProviderIcon className="size-3.5 shrink-0 text-muted-foreground/60" />
        ) : (
          <div className="grid size-3.5 shrink-0 place-items-center rounded-full bg-gradient-to-br from-primary/20 to-primary/10">
            <div className="size-1.5 rounded-full bg-primary/50" />
          </div>
        )}
        <span className="max-w-[120px] truncate font-medium">{displayName}</span>
      </ModelSelectorTrigger>

      <ModelSelectorContent title="Choose a model">
        <DialogTitle className="sr-only">Choose a model</DialogTitle>
        <ModelSelectorInput placeholder="Search models…" />
        <ModelSelectorList>
          <ModelSelectorEmpty>
            {loading ? (
              <span className="flex items-center gap-2 text-muted-foreground/50">
                <span className="relative flex size-2">
                  <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-primary/30 opacity-75" />
                  <span className="relative inline-flex size-2 rounded-full bg-primary/40" />
                </span>
                Loading models…
              </span>
            ) : (
              "No models found"
            )}
          </ModelSelectorEmpty>
          <ModelSelectorGroup>
            {models.map((m) => {
              const ModelIcon = getModelIcon(m.name, m.provider_name);
              const isSelected = m.id === selected;
              return (
                <ModelSelectorItem
                  key={m.id}
                  className={cn(
                    "flex items-center gap-2.5 rounded-lg px-3 py-2 transition-colors",
                    isSelected && "bg-primary/[0.08]",
                  )}
                  onSelect={() => handleSelect(m.id)}
                >
                  {ModelIcon ? (
                    <ModelIcon
                      className={cn(
                        "size-4 shrink-0",
                        isSelected ? "text-primary/80" : "text-muted-foreground/50",
                      )}
                    />
                  ) : (
                    <div className="grid size-4 shrink-0 place-items-center rounded-full bg-gradient-to-br from-primary/15 to-primary/5">
                      <div className="size-1.5 rounded-full bg-primary/40" />
                    </div>
                  )}
                  <span
                    className={cn(
                      "flex-1 truncate text-sm",
                      isSelected ? "font-medium text-foreground" : "text-muted-foreground",
                    )}
                  >
                    {m.display_name || m.name}
                  </span>
                  <span className="shrink-0 text-[10px] text-muted-foreground/50">
                    {m.provider_name}
                  </span>
                  {isSelected && (
                    <motion.span
                      layoutId="model-check"
                      className="ml-1 inline-flex size-1.5 rounded-full bg-primary"
                    />
                  )}
                </ModelSelectorItem>
              );
            })}
          </ModelSelectorGroup>
        </ModelSelectorList>
      </ModelSelectorContent>
    </ModelSelector>
  );
}
