"use client";
import { useState, useRef, useMemo, useEffect } from "react";
import { X } from "lucide-react";
import { cn } from "@/lib/utils";

export type ChipSuggestion =
  | string
  | { name: string; aliases?: string[]; primaryAliases?: string[] };

export function ChipInput({
  values,
  onChange,
  placeholder,
  accent = "cyan",
  suggestions,
}: {
  values: string[];
  onChange: (next: string[]) => void;
  placeholder?: string;
  accent?: "cyan" | "violet";
  /** Strings or { name, aliases? } — when aliases are provided, they're matched but the chip stores `name`. */
  suggestions?: ChipSuggestion[];
}) {
  const [draft, setDraft] = useState("");
  const [highlight, setHighlight] = useState(0);
  const [focused, setFocused] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);
  const blurTimerRef = useRef<number | null>(null);
  // Cancel any pending blur-commit on unmount so we don't fire setState
  // (or commit a stale draft) after the component is gone.
  useEffect(() => () => {
    if (blurTimerRef.current != null) window.clearTimeout(blurTimerRef.current);
  }, []);
  const accentVar = accent === "cyan" ? "var(--color-cyan)" : "var(--color-violet)";

  const lowerSelected = useMemo(() => new Set(values.map((v) => v.toLowerCase())), [values]);

  type Resolved = { name: string; matchedAlias?: string; rank: number };
  const filtered = useMemo<Resolved[]>(() => {
    if (!suggestions || !draft.trim()) return [];
    const q = draft.trim().toLowerCase();
    // rank: 0 = canonical name match, 1 = primary alias (reverse), 2 = alt alias.
    const out: Resolved[] = [];
    for (const s of suggestions) {
      const name = typeof s === "string" ? s : s.name;
      if (lowerSelected.has(name.toLowerCase())) continue;
      const primaryAliases = typeof s === "string" ? [] : (s.primaryAliases ?? []);
      const altAliases = typeof s === "string" ? [] : (s.aliases ?? []);
      if (name.toLowerCase().includes(q)) {
        out.push({ name, rank: 0 });
        continue;
      }
      const primaryHit = primaryAliases.find((a) => a.toLowerCase().includes(q));
      if (primaryHit) {
        out.push({ name, matchedAlias: primaryHit, rank: 1 });
        continue;
      }
      const altHit = altAliases.find((a) => a.toLowerCase().includes(q));
      if (altHit) out.push({ name, matchedAlias: altHit, rank: 2 });
    }
    out.sort((a, b) => a.rank - b.rank);
    return out.slice(0, 8);
  }, [suggestions, draft, lowerSelected]);

  const showDropdown = focused && filtered.length > 0;

  const commitValue = (raw: string) => {
    const t = raw.trim();
    if (!t) return;
    if (!lowerSelected.has(t.toLowerCase())) {
      onChange([...values, t]);
    }
    setDraft("");
    setHighlight(0);
  };

  const commit = () => commitValue(draft);

  const remove = (idx: number) => {
    onChange(values.filter((_, i) => i !== idx));
  };

  return (
    <div className="relative">
      <div
        className="flex flex-wrap items-center gap-1.5 p-2 rounded-lg glass min-h-[42px] cursor-text"
        onClick={() => inputRef.current?.focus()}
      >
        {values.map((v, i) => (
          <span
            key={`${v}-${i}`}
            className="flex items-center gap-1 pl-2 pr-1 py-0.5 rounded-full text-xs border"
            style={{
              background: `color-mix(in oklch, ${accentVar} 14%, transparent)`,
              color: accentVar,
              borderColor: `color-mix(in oklch, ${accentVar} 35%, transparent)`,
            }}
          >
            {v}
            <button
              type="button"
              onClick={(e) => { e.stopPropagation(); remove(i); }}
              aria-label={`Remove ${v}`}
              className="w-4 h-4 grid place-items-center rounded-full hover:bg-black/30"
            >
              <X className="w-3 h-3" />
            </button>
          </span>
        ))}
        <input
          ref={inputRef}
          value={draft}
          onChange={(e) => { setDraft(e.target.value); setHighlight(0); }}
          onFocus={() => {
            if (blurTimerRef.current) { window.clearTimeout(blurTimerRef.current); blurTimerRef.current = null; }
            setFocused(true);
          }}
          onBlur={() => {
            // Delay to allow mousedown on a suggestion to fire commit before we hide.
            blurTimerRef.current = window.setTimeout(() => {
              setFocused(false);
              commit();
            }, 120);
          }}
          onKeyDown={(e) => {
            if (showDropdown && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
              e.preventDefault();
              setHighlight((h) => {
                const n = filtered.length;
                if (e.key === "ArrowDown") return (h + 1) % n;
                return (h - 1 + n) % n;
              });
              return;
            }
            if (e.key === "Enter" || e.key === "Tab") {
              if (showDropdown && filtered[highlight]) {
                e.preventDefault();
                commitValue(filtered[highlight].name);
                return;
              }
              if (e.key === "Enter") {
                e.preventDefault();
                commit();
              }
              return;
            }
            if (e.key === ",") {
              e.preventDefault();
              commit();
            } else if (e.key === "Escape" && showDropdown) {
              setFocused(false);
            } else if (e.key === "Backspace" && !draft && values.length) {
              remove(values.length - 1);
            }
          }}
          placeholder={values.length === 0 ? placeholder : ""}
          className={cn(
            "flex-1 min-w-[100px] bg-transparent text-sm outline-none placeholder:text-[var(--color-fg-muted)]",
          )}
        />
      </div>

      {showDropdown && (
        <div
          className="absolute left-0 right-0 top-full mt-1 z-20 rounded-lg border border-[var(--color-glass-border)] bg-[var(--color-bg-0)] shadow-2xl overflow-hidden"
          onMouseDown={(e) => e.preventDefault()}
        >
          {filtered.map((s, i) => (
            <button
              key={s.name}
              type="button"
              onMouseDown={(e) => {
                e.preventDefault();
                if (blurTimerRef.current) { window.clearTimeout(blurTimerRef.current); blurTimerRef.current = null; }
                commitValue(s.name);
                inputRef.current?.focus();
              }}
              onMouseEnter={() => setHighlight(i)}
              className={cn(
                "w-full flex items-center justify-between gap-2 px-3 py-1.5 text-sm text-left",
                i === highlight ? "bg-[var(--color-glass-strong)]" : "hover:bg-[var(--color-glass)]",
              )}
              style={{ color: accentVar }}
            >
              <span>{s.name}</span>
              {s.matchedAlias && (
                <span className="text-[10px] font-mono text-[var(--color-fg-muted)] truncate">
                  ↦ {s.matchedAlias}
                </span>
              )}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}
