import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Search, User as UserIcon, Loader2, X, Building2, Mail } from "lucide-react";
import { client } from "@/lib/api";

export type PickedUser = {
  /** Canonical identifier used by the backend (email preferred, fallback to whmcs client id). */
  id: string;
  email: string;
  name: string;
  company?: string | null;
  avatar?: string | null;
  source: "whmcs" | "local";
  whmcs_client_id?: number | null;
};

type WhmcsClient = {
  id?: number | string;
  userid?: number | string;
  email?: string | null;
  firstname?: string | null;
  lastname?: string | null;
  fullname?: string | null;
  companyname?: string | null;
  status?: string | null;
};

type Props = {
  value: string;
  onSelect: (user: PickedUser) => void;
  onClear?: () => void;
  /** Lower-cased identifiers (emails / ids) that already have a role assignment. */
  excludeIds?: string[];
  disabled?: boolean;
  placeholder?: string;
};

function deriveName(c: WhmcsClient): string {
  const first = (c.firstname || "").trim();
  const last = (c.lastname || "").trim();
  const full = (c.fullname || `${first} ${last}`).trim();
  return full || c.email || `Client #${c.id ?? c.userid ?? ""}`;
}

function initialsOf(name: string, email: string): string {
  const base = (name || email || "?").trim();
  const parts = base.split(/\s+/).filter(Boolean);
  if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase();
  return base.slice(0, 2).toUpperCase();
}

async function callApi<T>(path: string): Promise<T> {
  const res = await client.apiCall.invoke({ url: path, method: "GET" });
  if (res?.error) {
    const msg = typeof res.error === "string" ? res.error : JSON.stringify(res.error);
    throw new Error(msg);
  }
  return (res?.data ?? res) as T;
}

export default function UserPicker({
  value,
  onSelect,
  onClear,
  excludeIds = [],
  disabled,
  placeholder = "Search users by email, name, or company…",
}: Props) {
  const [query, setQuery] = useState(value || "");
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [results, setResults] = useState<PickedUser[]>([]);
  const [error, setError] = useState<string | null>(null);
  const debounceRef = useRef<number | null>(null);
  const rootRef = useRef<HTMLDivElement | null>(null);

  // Keep internal query in sync if parent value changes externally.
  useEffect(() => {
    setQuery(value || "");
  }, [value]);

  // Close dropdown on outside click.
  useEffect(() => {
    function onDocClick(e: MouseEvent) {
      if (!rootRef.current) return;
      if (!rootRef.current.contains(e.target as Node)) setOpen(false);
    }
    document.addEventListener("mousedown", onDocClick);
    return () => document.removeEventListener("mousedown", onDocClick);
  }, []);

  const excludeSet = useMemo(
    () => new Set((excludeIds || []).map((s) => s.toLowerCase()).filter(Boolean)),
    [excludeIds]
  );

  const runSearch = useCallback(
    async (term: string) => {
      const trimmed = term.trim();
      setLoading(true);
      setError(null);
      try {
        const params = new URLSearchParams({ limit: "25", offset: "0" });
        if (trimmed) params.set("search", trimmed);
        const resp = await callApi<{ ok: boolean; clients: WhmcsClient[]; message?: string }>(
          `/api/v1/whmcs/admin/clients/all?${params.toString()}`
        );
        if (!resp?.ok) {
          setResults([]);
          setError(resp?.message || "WHMCS client search is unavailable.");
          return;
        }
        const mapped: PickedUser[] = (resp.clients || [])
          .map((c): PickedUser => {
            const email = (c.email || "").trim();
            const name = deriveName(c);
            return {
              id: email || String(c.id ?? c.userid ?? ""),
              email,
              name,
              company: c.companyname || null,
              avatar: null,
              source: "whmcs",
              whmcs_client_id:
                c.id !== undefined && c.id !== null && !Number.isNaN(Number(c.id))
                  ? Number(c.id)
                  : null,
            };
          })
          .filter((u) => !!u.id);
        setResults(mapped);
      } catch (e) {
        const msg = e instanceof Error ? e.message : String(e);
        setError(`Search failed: ${msg}`);
        setResults([]);
      } finally {
        setLoading(false);
      }
    },
    []
  );

  // Debounced search.
  useEffect(() => {
    if (!open) return;
    if (debounceRef.current) window.clearTimeout(debounceRef.current);
    debounceRef.current = window.setTimeout(() => {
      runSearch(query);
    }, 250);
    return () => {
      if (debounceRef.current) window.clearTimeout(debounceRef.current);
    };
  }, [query, open, runSearch]);

  const handlePick = (u: PickedUser) => {
    if (excludeSet.has((u.id || "").toLowerCase())) return;
    onSelect(u);
    setOpen(false);
  };

  const handleClear = () => {
    setQuery("");
    setResults([]);
    if (onClear) onClear();
  };

  return (
    <div ref={rootRef} className="relative w-full">
      <div className="relative">
        <Search className="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none" />
        <input
          type="text"
          value={query}
          disabled={disabled}
          onFocus={() => setOpen(true)}
          onChange={(e) => {
            setQuery(e.target.value);
            setOpen(true);
          }}
          placeholder={placeholder}
          className="w-full pl-9 pr-9 py-2 rounded-lg border border-slate-300 bg-white text-sm text-slate-800 placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-[#0b6e3e]/40 focus:border-[#0b6e3e] disabled:bg-slate-50 disabled:cursor-not-allowed"
        />
        {query && !disabled && (
          <button
            type="button"
            onClick={handleClear}
            className="absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-slate-100 text-slate-400 hover:text-slate-600"
            aria-label="Clear"
          >
            <X className="w-3.5 h-3.5" />
          </button>
        )}
      </div>

      {open && !disabled && (
        <div className="absolute z-30 mt-1 w-full rounded-lg border border-slate-200 bg-white shadow-lg max-h-80 overflow-auto">
          {loading && (
            <div className="flex items-center gap-2 px-3 py-3 text-xs text-slate-500">
              <Loader2 className="w-3.5 h-3.5 animate-spin" />
              Searching WHMCS clients…
            </div>
          )}

          {!loading && error && (
            <div className="px-3 py-2 text-xs text-red-700 bg-red-50 border-b border-red-100">
              {error}
            </div>
          )}

          {!loading && !error && results.length === 0 && (
            <div className="px-3 py-4 text-xs text-slate-500 text-center">
              No matching users. Try a different email, name, or company.
            </div>
          )}

          <ul className="divide-y divide-slate-100">
            {results.map((u) => {
              const taken = excludeSet.has((u.id || "").toLowerCase());
              return (
                <li key={`${u.source}-${u.id}-${u.whmcs_client_id ?? "x"}`}>
                  <button
                    type="button"
                    disabled={taken}
                    onClick={() => handlePick(u)}
                    className={`w-full text-left flex items-center gap-3 px-3 py-2 transition ${
                      taken
                        ? "opacity-50 cursor-not-allowed bg-slate-50"
                        : "hover:bg-[#0b6e3e]/5"
                    }`}
                  >
                    <div className="w-9 h-9 rounded-full bg-gradient-to-br from-[#0b6e3e] to-[#0a8048] text-white flex items-center justify-center text-xs font-bold shrink-0">
                      {u.avatar ? (
                        <img
                          src={u.avatar}
                          alt={u.name}
                          className="w-full h-full rounded-full object-cover"
                        />
                      ) : (
                        initialsOf(u.name, u.email)
                      )}
                    </div>
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-2">
                        <span className="text-sm font-semibold text-slate-800 truncate">
                          {u.name}
                        </span>
                        <span className="text-[10px] uppercase tracking-wider font-bold px-1.5 py-0.5 rounded bg-slate-100 text-slate-600">
                          {u.source}
                        </span>
                        {taken && (
                          <span className="text-[10px] uppercase tracking-wider font-bold px-1.5 py-0.5 rounded bg-amber-100 text-amber-700">
                            already assigned
                          </span>
                        )}
                      </div>
                      <div className="flex items-center gap-3 text-xs text-slate-500 mt-0.5">
                        {u.email && (
                          <span className="inline-flex items-center gap-1 truncate">
                            <Mail className="w-3 h-3" />
                            {u.email}
                          </span>
                        )}
                        {u.company && (
                          <span className="inline-flex items-center gap-1 truncate">
                            <Building2 className="w-3 h-3" />
                            {u.company}
                          </span>
                        )}
                        {!u.email && !u.company && (
                          <span className="inline-flex items-center gap-1">
                            <UserIcon className="w-3 h-3" />#{u.whmcs_client_id ?? u.id}
                          </span>
                        )}
                      </div>
                    </div>
                  </button>
                </li>
              );
            })}
          </ul>
        </div>
      )}
    </div>
  );
}