"use client";

import { useEffect, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { Dialog, DialogPanel } from "@headlessui/react";
import { IconSearch } from "@tabler/icons-react";
import Fuse from "fuse.js";

import type { DocsSearchRecord } from "@/lib/search/site-index";

export function SiteSearch({
  records,
  lang,
  label,
  placeholder,
  className,
  variant = "icon",
}: {
  records: DocsSearchRecord[];
  lang: string;
  label: string;
  placeholder: string;
  className?: string;
  variant?: "icon" | "bar";
}) {
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const router = useRouter();

  const fuse = useMemo(
    () =>
      new Fuse(records, {
        keys: ["title", "pageTitle", "content"],
        threshold: 0.4,
        ignoreLocation: true,
      }),
    [records],
  );

  const results = useMemo(
    () =>
      query
        ? fuse
            .search(query)
            .slice(0, 8)
            .map((r) => r.item)
        : [],
    [query, fuse],
  );

  // ⌘K / Ctrl+K opens the dialog. Only the icon variant owns the global
  // shortcut: a page may render a visible "bar" search alongside the navbar's
  // icon search (e.g. the blog), and binding both would open two dialogs on ⌘K.
  useEffect(() => {
    if (variant === "bar") return;
    const onKey = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        setOpen(true);
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [variant]);

  const go = (href: string) => {
    setOpen(false);
    setQuery("");
    router.push(`/${lang}${href}`);
  };

  return (
    <>
      {variant === "bar" ? (
        <button
          type="button"
          onClick={() => setOpen(true)}
          aria-label={label}
          className={`border-hairline hover:bg-foreground/5 group flex w-full items-center gap-3 rounded-full border bg-transparent px-4 py-2.5 text-left transition-colors ${className ?? ""}`}
        >
          <IconSearch className="text-ink-4 size-5 shrink-0" />
          <span className="text-ink-4 flex-1 text-sm">{placeholder}</span>
          <kbd className="text-ink-4 border-hairline hidden rounded border px-1.5 py-0.5 text-[11px] font-medium sm:inline-block">
            ⌘K
          </kbd>
        </button>
      ) : (
        <button
          type="button"
          onClick={() => setOpen(true)}
          aria-label={label}
          className={`text-ink-2 hover:bg-foreground/5 -m-2.5 inline-flex items-center justify-center rounded-lg p-2.5 transition-colors ${className ?? ""}`}
        >
          <IconSearch className="size-5" />
        </button>
      )}

      <Dialog open={open} onClose={setOpen} className="relative z-[70]">
        <div
          className="fixed inset-0 bg-black/40 backdrop-blur-sm"
          aria-hidden="true"
        />
        <div className="fixed inset-0 flex items-start justify-center p-4 pt-[15vh]">
          <DialogPanel
            transition
            className="bg-background ring-hairline w-full max-w-lg overflow-hidden rounded-2xl shadow-2xl ring-1 transition data-[closed]:scale-95 data-[closed]:opacity-0"
          >
            <div className="border-hairline flex items-center gap-2 border-b px-4">
              <IconSearch className="text-ink-4 size-5" />
              <input
                autoFocus
                type="search"
                name="q"
                value={query}
                onChange={(e) => setQuery(e.target.value)}
                placeholder={placeholder}
                aria-label={label}
                autoComplete="off"
                inputMode="search"
                enterKeyHint="search"
                className="text-ink-1 placeholder:text-ink-4 w-full bg-transparent py-3.5 text-sm outline-none"
              />
            </div>
            {query && (
              <ul className="max-h-80 overflow-y-auto p-2">
                {results.length === 0 ? (
                  <li className="text-ink-4 px-3 py-6 text-center text-sm">
                    {lang === "fr"
                      ? `Aucun résultat pour « ${query} »`
                      : `No results for “${query}”`}
                  </li>
                ) : (
                  results.map((r, i) => (
                    <li key={`${r.href}-${i}`}>
                      <button
                        type="button"
                        onClick={() => go(r.href)}
                        className="hover:bg-foreground/5 block w-full rounded-lg px-3 py-2 text-left"
                      >
                        <div className="text-ink-1 text-sm font-medium">
                          {r.title}
                        </div>
                        {r.title !== r.pageTitle && (
                          <div className="text-ink-4 text-xs">
                            {r.pageTitle}
                          </div>
                        )}
                      </button>
                    </li>
                  ))
                )}
              </ul>
            )}
          </DialogPanel>
        </div>
      </Dialog>
    </>
  );
}
