"use client";

// Global conversation search in the topbar: type → debounced crm.search → dropdown of hits; click a
// hit to deep-link to exactly where it lives (mail → Inbox, chat → Messenger, on that thread).

import { useEffect, useRef, useState } from "react";
import { Icon } from "./ui";
import { useGlobalSearch, type SearchResult } from "@/lib/search-api";

/** Escape HTML but keep the engine's <em> highlight tags — so a match snippet can't inject markup. */
function safeSnippet(s: string): string {
  const esc = s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
  return esc.replace(/&lt;em&gt;/g, "<em>").replace(/&lt;\/em&gt;/g, "</em>");
}

export function GlobalSearch({ onNavigate }: { onNavigate: (surface: "messenger" | "inbox", threadId: string) => void }) {
  const search = useGlobalSearch();
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const [results, setResults] = useState<SearchResult[]>([]);
  const [loading, setLoading] = useState(false);
  const wrapRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const term = q.trim();
    if (!term) {
      setResults([]);
      return;
    }
    let alive = true;
    setLoading(true);
    const t = setTimeout(() => {
      search(term)
        .then((r) => { if (alive) setResults(r); })
        .catch(() => { if (alive) setResults([]); })
        .finally(() => { if (alive) setLoading(false); });
    }, 220);
    return () => { alive = false; clearTimeout(t); };
  }, [q, search]);

  useEffect(() => {
    function onDown(e: MouseEvent) {
      if (!wrapRef.current?.contains(e.target as Node)) setOpen(false);
    }
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, []);

  function pick(r: SearchResult) {
    onNavigate(r.surface, r.threadId);
    setOpen(false);
    setQ("");
  }

  return (
    <div className="gs-wrap" ref={wrapRef}>
      <div className="gs-field">
        <Icon name="search" size={16} />
        <input
          className="gs-input"
          placeholder="Search conversations…"
          value={q}
          onFocus={() => setOpen(true)}
          onChange={(e) => { setQ(e.target.value); setOpen(true); }}
          aria-label="Search conversations"
        />
      </div>
      {open && q.trim() ? (
        <div className="gs-pop">
          {loading && results.length === 0 ? <div className="gs-empty">Searching…</div> : null}
          {!loading && results.length === 0 ? <div className="gs-empty">No matches.</div> : null}
          {results.map((r) => (
            <button key={r.interactionId} type="button" className="gs-row" onClick={() => pick(r)}>
              <span className="gs-ic"><Icon name={r.surface === "inbox" ? "mail" : "send"} size={14} /></span>
              <span className="gs-main">
                <span className="gs-title">{r.title}</span>
                <span className="gs-snippet" dangerouslySetInnerHTML={{ __html: safeSnippet(r.snippet) }} />
              </span>
              <span className="gs-surface">{r.surface === "inbox" ? "Mail" : "Chat"}</span>
            </button>
          ))}
        </div>
      ) : null}
    </div>
  );
}
