"use client";

import { useRouter } from "next/navigation";
import { useEffect, useId, useRef, useState } from "react";

interface SearchBarProps {
  defaultValue?: string;
  id?: string;
  size?: "md" | "lg";
}

interface Suggestion {
  slug: string;
  title: string;
  categoryName: string;
}

/**
 * Site search with live suggestions. Progressive enhancement: without JS the
 * plain GET form still submits to /games?q=… . With JS, a debounced fetch
 * offers up to 6 matches with full keyboard support (listbox pattern).
 */
export function SearchBar({ defaultValue = "", id, size = "md" }: SearchBarProps) {
  const generatedId = useId();
  const inputId = id ?? `site-search-${generatedId}`;
  const listId = `${inputId}-suggestions`;
  const router = useRouter();

  const [value, setValue] = useState(defaultValue);
  const [suggestions, setSuggestions] = useState<Suggestion[]>([]);
  const [open, setOpen] = useState(false);
  const [activeIndex, setActiveIndex] = useState(-1);
  const blurTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  const sizing = size === "lg" ? "h-14 text-base px-5" : "h-11 text-sm px-4";
  const showDropdown = open && value.trim().length > 0;

  useEffect(() => {
    const term = value.trim();
    if (!term) return;
    const controller = new AbortController();
    const timer = setTimeout(() => {
      fetch(`/api/suggest?q=${encodeURIComponent(term)}`, {
        signal: controller.signal,
      })
        .then((res) => (res.ok ? res.json() : { suggestions: [] }))
        .then((data: { suggestions?: Suggestion[] }) => {
          setSuggestions(
            Array.isArray(data.suggestions) ? data.suggestions : [],
          );
          setActiveIndex(-1);
        })
        .catch(() => {
          // Suggestions are a bonus — the form submit still works.
          setSuggestions([]);
        });
    }, 200);
    return () => {
      clearTimeout(timer);
      controller.abort();
    };
  }, [value]);

  useEffect(
    () => () => {
      if (blurTimer.current) clearTimeout(blurTimer.current);
    },
    [],
  );

  const goToSuggestion = (s: Suggestion) => {
    setOpen(false);
    router.push(`/games/${s.slug}`);
  };

  return (
    <form action="/games" method="get" role="search" className="relative w-full">
      <label htmlFor={inputId} className="sr-only">
        Search games
      </label>
      <div className="relative">
        <span
          aria-hidden="true"
          className="pointer-events-none absolute top-1/2 left-4 -translate-y-1/2 text-slate-500"
        >
          ⌕
        </span>
        <input
          id={inputId}
          name="q"
          type="search"
          value={value}
          onChange={(e) => {
            const next = e.target.value;
            setValue(next);
            setOpen(true);
            if (!next.trim()) {
              setSuggestions([]);
              setActiveIndex(-1);
            }
          }}
          onFocus={() => setOpen(true)}
          onBlur={() => {
            blurTimer.current = setTimeout(() => setOpen(false), 150);
          }}
          onKeyDown={(e) => {
            if (e.key === "ArrowDown" && suggestions.length > 0) {
              e.preventDefault();
              setActiveIndex((i) => (i + 1) % suggestions.length);
            } else if (e.key === "ArrowUp" && suggestions.length > 0) {
              e.preventDefault();
              setActiveIndex(
                (i) => (i - 1 + suggestions.length) % suggestions.length,
              );
            } else if (
              e.key === "Enter" &&
              activeIndex >= 0 &&
              suggestions[activeIndex]
            ) {
              e.preventDefault();
              goToSuggestion(suggestions[activeIndex]);
            } else if (e.key === "Escape") {
              setOpen(false);
              setActiveIndex(-1);
            }
          }}
          placeholder="Search games, categories, developers…"
          autoComplete="off"
          role="combobox"
          aria-expanded={showDropdown && suggestions.length > 0}
          aria-controls={listId}
          aria-activedescendant={
            activeIndex >= 0 ? `${listId}-${activeIndex}` : undefined
          }
          className={`w-full rounded-2xl border border-slate-700 bg-slate-900 pr-4 pl-11 text-slate-100 placeholder:text-slate-500 hover:border-slate-600 focus:border-brand-500 focus:outline-none ${sizing}`}
        />
      </div>
      {showDropdown && suggestions.length > 0 ? (
        <ul
          id={listId}
          role="listbox"
          aria-label="Search suggestions"
          className="absolute inset-x-0 top-full z-30 mt-2 overflow-hidden rounded-2xl border border-slate-700 bg-slate-900 shadow-2xl shadow-black/60"
        >
          {suggestions.map((s, i) => (
            <li key={s.slug} role="option" aria-selected={i === activeIndex}>
              <button
                type="button"
                id={`${listId}-${i}`}
                onMouseDown={(e) => e.preventDefault()}
                onClick={() => goToSuggestion(s)}
                onMouseEnter={() => setActiveIndex(i)}
                className={`flex w-full items-center justify-between gap-3 px-4 py-2.5 text-left text-sm transition-colors ${
                  i === activeIndex
                    ? "bg-brand-600/25 text-white"
                    : "text-slate-200"
                }`}
              >
                <span className="truncate font-medium">{s.title}</span>
                <span className="shrink-0 rounded-full bg-slate-800 px-2 py-0.5 text-xs text-slate-400">
                  {s.categoryName}
                </span>
              </button>
            </li>
          ))}
        </ul>
      ) : null}
    </form>
  );
}
