import { useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { SEARCH_MIN_CHARS } from '@siop/shared';
import { useGlobalSearch } from '@/api/recherche';
import { StatutOT } from '@/components/chips-ot';
import { IcoRecherche } from '@/components/nav-icons';

interface Resultat {
  cle: string;
  route: string;
  contenu: React.ReactNode;
}

/** La recherche de la topbar, enfin active (recette R3) : ⌘K pour saisir,
 *  résultats groupés (OT / ascenseurs / sites), déjà filtrés par la matrice
 *  côté API — flèches + Entrée pour naviguer. */
export function RechercheGlobale() {
  const navigate = useNavigate();
  const [saisie, setSaisie] = useState('');
  const [q, setQ] = useState('');
  const [ouverte, setOuverte] = useState(false);
  const [actif, setActif] = useState(0);
  const champ = useRef<HTMLInputElement>(null);

  // Débounce : on n'interroge l'API que 200 ms après la dernière frappe.
  useEffect(() => {
    const t = setTimeout(() => setQ(saisie), 200);
    return () => clearTimeout(t);
  }, [saisie]);

  // ⌘K / Ctrl+K : focus depuis n'importe où.
  useEffect(() => {
    const surTouche = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        champ.current?.focus();
        champ.current?.select();
      }
    };
    window.addEventListener('keydown', surTouche);
    return () => window.removeEventListener('keydown', surTouche);
  }, []);

  const { data } = useGlobalSearch(q);

  const resultats = useMemo<Resultat[]>(() => {
    if (!data) return [];
    return [
      ...data.workOrders.map((w) => ({
        cle: `ot-${w.id}`,
        route: `/ot/${w.id}`,
        contenu: (
          <>
            <span className="ref num">{w.reference}</span>
            <span className="titre">{w.title}</span>
            <span className="fin"><StatutOT statut={w.status} /></span>
          </>
        ),
      })),
      ...data.assets.map((a) => ({
        cle: `asc-${a.id}`,
        route: `/ascenseurs/${a.id}`,
        contenu: (
          <>
            <span className="ref num">{a.reference}</span>
            <span className="titre">
              {a.brand}
              {a.model ? ` ${a.model}` : ''}
            </span>
            <span className="fin">{a.siteName}</span>
          </>
        ),
      })),
      ...data.sites.map((s) => ({
        cle: `site-${s.id}`,
        route: `/sites/${s.id}`,
        contenu: (
          <>
            <span className="titre"><b>{s.name}</b></span>
            <span className="fin">{s.city ?? ''}</span>
          </>
        ),
      })),
    ];
  }, [data]);

  const groupes = useMemo(() => {
    if (!data) return [];
    const g: { libelle: string; debut: number; nombre: number }[] = [];
    if (data.workOrders.length) g.push({ libelle: 'Ordres de travail', debut: 0, nombre: data.workOrders.length });
    if (data.assets.length) g.push({ libelle: 'Ascenseurs', debut: data.workOrders.length, nombre: data.assets.length });
    if (data.sites.length) {
      g.push({
        libelle: 'Sites',
        debut: data.workOrders.length + data.assets.length,
        nombre: data.sites.length,
      });
    }
    return g;
  }, [data]);

  const visible = ouverte && q.trim().length >= SEARCH_MIN_CHARS;

  const aller = (r: Resultat | undefined) => {
    if (!r) return;
    setOuverte(false);
    setSaisie('');
    navigate(r.route);
  };

  return (
    <div className="recherche" data-active>
      <IcoRecherche />
      <input
        ref={champ}
        type="search"
        placeholder="Rechercher un OT, un ascenseur, un site…"
        aria-label="Recherche globale"
        value={saisie}
        onChange={(e) => {
          setSaisie(e.target.value);
          setOuverte(true);
          setActif(0);
        }}
        onFocus={() => setOuverte(true)}
        onBlur={() => setOuverte(false)}
        onKeyDown={(e) => {
          if (e.key === 'Escape') {
            setOuverte(false);
            champ.current?.blur();
          }
          if (!visible || !resultats.length) return;
          if (e.key === 'ArrowDown') {
            e.preventDefault();
            setActif((a) => Math.min(a + 1, resultats.length - 1));
          }
          if (e.key === 'ArrowUp') {
            e.preventDefault();
            setActif((a) => Math.max(a - 1, 0));
          }
          if (e.key === 'Enter') {
            e.preventDefault();
            aller(resultats[actif]);
          }
        }}
      />
      <kbd>⌘K</kbd>
      {visible ? (
        <div className="resultats" role="listbox" aria-label="Résultats">
          {groupes.map((g) => (
            <div key={g.libelle}>
              <div className="groupe-resultats">{g.libelle}</div>
              {resultats.slice(g.debut, g.debut + g.nombre).map((r, i) => (
                <button
                  key={r.cle}
                  type="button"
                  role="option"
                  aria-selected={g.debut + i === actif}
                  className="resultat"
                  data-actif={g.debut + i === actif || undefined}
                  onMouseEnter={() => setActif(g.debut + i)}
                  onMouseDown={(e) => {
                    e.preventDefault(); // avant le blur du champ
                    aller(r);
                  }}
                >
                  {r.contenu}
                </button>
              ))}
            </div>
          ))}
          {!resultats.length ? (
            <div className="groupe-resultats">Aucun résultat pour « {q.trim()} »</div>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}
