'use client';
/**
 * Client-side dealer search island. Filters an embedded index — the
 * server-rendered listings below remain the canonical crawlable content.
 * (~60KB of JSON at 600 dealers; acceptable per spec §4.3.)
 *
 * ARIA: APG editable-combobox-with-listbox pattern. Focus stays in the
 * input; ArrowUp/Down move aria-activedescendant, Enter follows the
 * active dealer's URL, Escape closes then clears. A polite live region
 * announces result counts for screen readers.
 */
import { useEffect, useMemo, useRef, useState } from 'react';
import { filterDealers, DEALER_SEARCH_MIN_CHARS, type SearchDealer } from '@/lib/dealer-search';

export type { SearchDealer };

export function DealerSearch({
  dealers,
  regionNoun = 'state',
}: {
  dealers: SearchDealer[];
  /** "state" (US) or "province" (CA); keeps the label matching the page. */
  regionNoun?: string;
}) {
  const [query, setQuery] = useState('');
  const [open, setOpen] = useState(false);
  const [activeIndex, setActiveIndex] = useState(-1);
  const blurTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Clear any pending blur-close timer if the component unmounts mid-flight.
  useEffect(
    () => () => {
      if (blurTimeout.current) clearTimeout(blurTimeout.current);
    },
    []
  );

  const results = useMemo(() => filterDealers(dealers, query), [query, dealers]);

  const showListbox = open && results.length > 0;
  const showEmpty = open && query.trim().length >= DEALER_SEARCH_MIN_CHARS && results.length === 0;

  function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === 'Escape') {
      if (open) {
        setOpen(false);
      } else if (query) {
        setQuery('');
      }
      setActiveIndex(-1);
      return;
    }
    if (results.length === 0) return;
    if (e.key === 'ArrowDown') {
      e.preventDefault();
      setOpen(true);
      setActiveIndex((i) => (i + 1) % results.length);
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      setOpen(true);
      setActiveIndex((i) => (i <= 0 ? results.length - 1 : i - 1));
    } else if (e.key === 'Enter' && open && activeIndex >= 0) {
      e.preventDefault();
      window.location.assign(results[activeIndex].url);
    }
  }

  return (
    <div className="relative mx-auto mt-6 max-w-md text-left">
      <label htmlFor="dealer-search" className="sr-only">
        Search dealers by name, city, or {regionNoun}
      </label>
      <input
        id="dealer-search"
        type="search"
        role="combobox"
        aria-expanded={showListbox}
        aria-controls="dealer-search-listbox"
        aria-autocomplete="list"
        aria-activedescendant={
          showListbox && activeIndex >= 0 ? `dealer-search-option-${activeIndex}` : undefined
        }
        autoComplete="off"
        value={query}
        onChange={(e) => {
          setQuery(e.target.value);
          setOpen(true);
          setActiveIndex(-1);
        }}
        onFocus={() => setOpen(true)}
        onBlur={() => {
          // Delay so option mousedown/click wins the race against blur-close.
          blurTimeout.current = setTimeout(() => setOpen(false), 150);
        }}
        onKeyDown={handleKeyDown}
        placeholder={`Search by name, city, or ${regionNoun}…`}
        className="w-full rounded-full border-2 border-[#c6c6c6] bg-white px-5 py-3 text-base text-[#1a1a1a] transition-[border-color,box-shadow] placeholder:text-[#6b7280] focus:border-[#093b66] focus:outline-none focus:ring-4 focus:ring-[#093b66]/10"
      />
      <div aria-live="polite" className="sr-only">
        {query.trim().length >= DEALER_SEARCH_MIN_CHARS
          ? results.length > 0
            ? `${results.length} dealers found. Use up and down arrows to review, Enter to visit.`
            : 'No dealers match your search.'
          : ''}
      </div>
      {showListbox && (
        <ul
          id="dealer-search-listbox"
          role="listbox"
          aria-label="Matching dealers"
          className="absolute z-10 mt-2 max-h-80 w-full divide-y divide-[#e5e7eb] overflow-auto rounded-lg border border-[#c6c6c6] bg-white shadow-lg"
        >
          {results.map((d, i) => (
            <li
              key={d.url}
              id={`dealer-search-option-${i}`}
              role="option"
              aria-selected={i === activeIndex}
            >
              <a
                href={d.url}
                tabIndex={-1}
                className={`block px-5 py-2.5 transition-colors hover:bg-[#f0f0f0] ${
                  i === activeIndex ? 'bg-[#f0f0f0]' : ''
                }`}
              >
                <span className="font-semibold text-[#093b66]">{d.name}</span>{' '}
                <span className="text-sm text-[#595959]">
                  {d.city}, {d.state}
                </span>
              </a>
            </li>
          ))}
        </ul>
      )}
      {showEmpty && (
        <p className="absolute mt-2 w-full rounded-lg border border-[#c6c6c6] bg-white px-5 py-3 text-sm text-[#1a1a1a] shadow-lg">
          No dealers match “{query}”. Try browsing the list below.
        </p>
      )}
    </div>
  );
}
