import { useState, useRef, useEffect } from "react";
import { useQuery } from "@tanstack/react-query";
import { Search, UserPlus, ChevronDown } from "lucide-react";

import type { Client } from "@rubis/shared";
import { api } from "@/lib/api";
import { queryKeys } from "@/lib/queryKeys";
import { cn } from "@/lib/utils";

/**
 * ClientCombobox — autocomplete des clients existants avec création
 * à la volée si aucun ne match.
 *
 * Pas Radix Combobox (n'existe pas) ni cmdk (overkill pour V1) — version
 * maison minimale :
 *  - Input + dropdown qui s'affiche au focus / typing
 *  - Filtre case-insensitive sur le nom
 *  - Click sur une suggestion = sélection (renvoie le clientId au parent)
 *  - Si rien ne match, option "Créer un nouveau client : « X »"
 *  - Escape ferme le dropdown
 */
type ClientComboboxProps = {
  value: string;
  /** clientId si un client existant a été sélectionné, sinon null. */
  selectedClientId: string | null;
  onChange: (input: { value: string; clientId: string | null }) => void;
  placeholder?: string;
  id?: string;
  className?: string;
};

export function ClientCombobox({
  value,
  selectedClientId,
  onChange,
  placeholder = "Rechercher ou créer un client…",
  id,
  className,
}: ClientComboboxProps) {
  const [isOpen, setIsOpen] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  const { data: clients = [] } = useQuery({
    queryKey: queryKeys.clients.all(),
    queryFn: () => api.get<Client[]>("/api/v1/clients"),
    staleTime: 60_000,
  });

  // Filtre les clients selon la valeur tapée. Si l'utilisateur a déjà
  // sélectionné un client (selectedClientId), on ne filtre pas.
  const matches = value.trim().length > 0
    ? clients.filter((c) =>
        c.name.toLowerCase().includes(value.toLowerCase()),
      )
    : clients;

  const exactMatch = clients.some(
    (c) => c.name.toLowerCase() === value.toLowerCase(),
  );

  // Click outside → close
  useEffect(() => {
    if (!isOpen) return;
    const onClickOutside = (e: MouseEvent) => {
      if (
        containerRef.current &&
        !containerRef.current.contains(e.target as Node)
      ) {
        setIsOpen(false);
      }
    };
    document.addEventListener("mousedown", onClickOutside);
    return () => document.removeEventListener("mousedown", onClickOutside);
  }, [isOpen]);

  const selectClient = (client: Client) => {
    onChange({ value: client.name, clientId: client.id });
    setIsOpen(false);
  };

  const createNew = () => {
    // L'utilisateur valide la valeur tapée comme nom de nouveau client.
    onChange({ value: value.trim(), clientId: null });
    setIsOpen(false);
  };

  return (
    <div ref={containerRef} className={cn("relative", className)}>
      <div className="relative">
        <Search
          size={14}
          aria-hidden="true"
          className="absolute left-3.5 top-1/2 -translate-y-1/2 text-ink-3 pointer-events-none"
        />
        <input
          id={id}
          type="text"
          autoComplete="off"
          value={value}
          placeholder={placeholder}
          onFocus={() => setIsOpen(true)}
          onChange={(e) => {
            // Si l'utilisateur retape, on perd la sélection client précédente.
            onChange({ value: e.target.value, clientId: null });
            setIsOpen(true);
          }}
          onKeyDown={(e) => {
            if (e.key === "Escape") setIsOpen(false);
          }}
          className={cn(
            "block w-full rounded-default border border-line bg-white",
            "pl-10 pr-9 py-3 font-sans text-[15px] text-ink placeholder:text-ink-3",
            "transition-[border-color,box-shadow] duration-150",
            "focus:outline-none focus:border-rubis focus:ring-4 focus:ring-rubis-glow",
            selectedClientId && "border-rubis bg-rubis-glow/30",
          )}
        />
        <ChevronDown
          size={14}
          aria-hidden="true"
          className="absolute right-3.5 top-1/2 -translate-y-1/2 text-ink-3 pointer-events-none"
        />
      </div>

      {isOpen && (
        <div
          role="listbox"
          className={cn(
            "absolute z-20 mt-1 w-full max-h-[260px] overflow-y-auto",
            "rounded-card border border-line bg-white shadow-card p-1",
          )}
        >
          {matches.length === 0 && value.trim().length === 0 && (
            <p className="px-3 py-4 text-[13px] italic text-ink-3 text-center">
              Aucun client encore. Tapez pour en créer un.
            </p>
          )}

          {matches.map((c) => (
            <button
              key={c.id}
              type="button"
              role="option"
              aria-selected={selectedClientId === c.id}
              onClick={() => selectClient(c)}
              className={cn(
                "flex w-full items-center justify-between gap-2 rounded-default px-3 py-2",
                "text-left text-[14px] text-ink hover:bg-cream-2",
                selectedClientId === c.id && "bg-rubis-glow text-rubis-deep",
              )}
            >
              <span className="truncate">{c.name}</span>
              {c.email && (
                <span className="shrink-0 text-[11.5px] text-ink-3 truncate">
                  {c.email}
                </span>
              )}
            </button>
          ))}

          {value.trim().length >= 2 && !exactMatch && (
            <button
              type="button"
              onClick={createNew}
              className={cn(
                "flex w-full items-center gap-2 rounded-default px-3 py-2",
                "text-left text-[13.5px] text-rubis hover:bg-rubis-glow",
                matches.length > 0 && "border-t border-line mt-1",
              )}
            >
              <UserPlus size={14} aria-hidden="true" />
              <span>
                Créer le client{" "}
                <strong className="font-semibold">« {value.trim()} »</strong>
              </span>
            </button>
          )}
        </div>
      )}
    </div>
  );
}
