"use client";

import { useState, useRef, useEffect, useLayoutEffect, useCallback } from "react";
import { createPortal } from "react-dom";
import { ChevronDown, Search, X } from "lucide-react";

export type VendorOption = { id: string; name: string; vendorId: string | null };

/**
 * Filter vendors by a free-text query, matching case-insensitively against the
 * vendor name and the formal code (`vendorId`). An empty/whitespace query
 * returns the full list unchanged.
 */
export function filterVendors<T extends VendorOption>(vendors: T[], query: string): T[] {
  const q = query.trim().toLowerCase();
  if (!q) return vendors;
  return vendors.filter(
    (v) =>
      v.name.toLowerCase().includes(q) ||
      (v.vendorId ? v.vendorId.toLowerCase().includes(q) : false)
  );
}

/** Label shown for a vendor: "{name} (CODE)" when verified, "{name} (unverified)" otherwise. */
export function vendorLabel(v: VendorOption): string {
  return `${v.name} ${v.vendorId ? `(${v.vendorId})` : "(unverified)"}`;
}

interface Props {
  name: string;
  vendors: VendorOption[];
  /** Initial selected vendor id (uncontrolled — the component owns its state). */
  initialValue?: string;
  placeholder?: string;
  /** Optional callback when the selection changes. */
  onChange?: (value: string) => void;
}

export function VendorSelect({
  name,
  vendors,
  initialValue = "",
  placeholder = "No vendor selected",
  onChange,
}: Props) {
  const [value, setValue] = useState(initialValue);
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const containerRef = useRef<HTMLDivElement>(null);
  const searchRef = useRef<HTMLInputElement>(null);
  const [portalStyle, setPortalStyle] = useState<React.CSSProperties>({});
  const [mounted, setMounted] = useState(false);

  useEffect(() => { setMounted(true); }, []);

  const updatePortalPos = useCallback(() => {
    if (!containerRef.current) return;
    const rect = containerRef.current.getBoundingClientRect();
    setPortalStyle({
      position: "fixed",
      top: rect.bottom + 4,
      left: rect.left,
      width: rect.width,
      zIndex: 9999,
    });
  }, []);

  useLayoutEffect(() => {
    if (!open) return;
    updatePortalPos();
  }, [open, updatePortalPos]);

  useEffect(() => {
    if (!open) return;
    window.addEventListener("scroll", updatePortalPos, true);
    window.addEventListener("resize", updatePortalPos);
    return () => {
      window.removeEventListener("scroll", updatePortalPos, true);
      window.removeEventListener("resize", updatePortalPos);
    };
  }, [open, updatePortalPos]);

  // Close on outside click / Escape
  useEffect(() => {
    if (!open) return;
    function handleKey(e: KeyboardEvent) {
      if (e.key === "Escape") { setOpen(false); setQuery(""); }
    }
    function handleClick(e: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setOpen(false);
        setQuery("");
      }
    }
    document.addEventListener("keydown", handleKey);
    document.addEventListener("mousedown", handleClick);
    return () => {
      document.removeEventListener("keydown", handleKey);
      document.removeEventListener("mousedown", handleClick);
    };
  }, [open]);

  useEffect(() => {
    if (open) searchRef.current?.focus();
  }, [open]);

  const selected = vendors.find((v) => v.id === value);
  const selectedLabel = selected ? vendorLabel(selected) : "";

  const filtered = filterVendors(vendors, query);

  const select = useCallback((id: string) => {
    setValue(id);
    onChange?.(id);
    setOpen(false);
    setQuery("");
  }, [onChange]);

  const handleClear = useCallback((e: React.MouseEvent) => {
    e.stopPropagation();
    setValue("");
    onChange?.("");
  }, [onChange]);

  const dropdownPanel = (
    <div
      style={portalStyle}
      className="rounded-lg border border-neutral-200 bg-white shadow-xl"
    >
      {/* Search input */}
      <div className="flex items-center gap-2 p-2 border-b border-neutral-100">
        <Search className="h-4 w-4 text-neutral-400 shrink-0" />
        <input
          ref={searchRef}
          type="text"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Search by name or code…"
          className="flex-1 text-sm outline-none placeholder:text-neutral-400"
        />
        {query && (
          <button type="button" onClick={() => setQuery("")} className="text-neutral-300 hover:text-neutral-500">
            <X className="h-3.5 w-3.5" />
          </button>
        )}
      </div>

      {/* Options list */}
      <div className="max-h-72 overflow-y-auto overscroll-contain [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-neutral-300">
        {/* "No vendor selected" empty option — always available */}
        <button
          type="button"
          onMouseDown={(e) => { e.preventDefault(); select(""); }}
          className={`w-full text-left px-3 py-2 text-sm hover:bg-primary-50 transition-colors
            ${value === "" ? "bg-primary-50 text-primary-700 font-medium" : "text-neutral-500"}`}
        >
          No vendor selected
        </button>
        {filtered.length === 0 ? (
          <p className="px-3 py-5 text-sm text-center text-neutral-400">No vendors match &ldquo;{query}&rdquo;</p>
        ) : (
          filtered.map((v) => (
            <button
              key={v.id}
              type="button"
              onMouseDown={(e) => { e.preventDefault(); select(v.id); }}
              className={`w-full text-left flex items-baseline gap-2.5 px-3 py-2 text-sm hover:bg-primary-50 transition-colors
                ${value === v.id ? "bg-primary-50 text-primary-700 font-medium" : "text-neutral-800"}`}
            >
              <span className="flex-1 leading-snug">{v.name}</span>
              <span className="font-mono text-xs text-neutral-400 shrink-0">
                {v.vendorId ?? "unverified"}
              </span>
            </button>
          ))
        )}
      </div>
    </div>
  );

  return (
    <div ref={containerRef} className="relative w-full">
      <input type="hidden" name={name} value={value} />

      <button
        type="button"
        onClick={() => setOpen((v) => !v)}
        className={`w-full flex items-center justify-between gap-2 rounded-lg border
          ${open ? "border-primary-500 ring-2 ring-primary-500/20" : "border-neutral-300"}
          bg-white text-left transition-colors px-3 py-2.5 text-sm
          focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20`}
      >
        <span className={`truncate flex-1 min-w-0 ${selectedLabel ? "text-neutral-900" : "text-neutral-400"}`}>
          {selectedLabel || placeholder}
        </span>
        <span className="flex items-center gap-1 shrink-0">
          {value && (
            <span role="button" tabIndex={0} onClick={handleClear}
              onKeyDown={(e) => e.key === "Enter" && handleClear(e as unknown as React.MouseEvent)}
              className="text-neutral-300 hover:text-neutral-500 transition-colors">
              <X className="h-4 w-4" />
            </span>
          )}
          <ChevronDown className={`text-neutral-400 transition-transform h-4 w-4 ${open ? "rotate-180" : ""}`} />
        </span>
      </button>

      {open && mounted && createPortal(dropdownPanel, document.body)}
    </div>
  );
}
