// -----------------------------------------------------------------------------
// Forma-Ka — Agrégateur de formations (province de Québec)
// Auteur : Simon-Pierre Boucher — contact@spboucher.ai
// pages/Home.tsx : accueil — héro, statistiques, filtres avancés, grille
//   Filtres : recherche, type, domaine, mode, ville, prix, gratuit, langue,
//   niveau, source, tri — avec pastilles de filtres actifs.
// -----------------------------------------------------------------------------
import { useEffect, useMemo, useState } from "react";
import { useSearchParams } from "react-router-dom";
import {
  Facets, Formation, FormationFilters, Stats,
  fetchFacets, fetchFormations, fetchSources, fetchStats,
  registerSourceNames, sourceName,
} from "../api";
import FormationCard from "../components/FormationCard";

const PRICE_STEPS = [100, 250, 500, 750, 1000, 1500, 2000, 3000, 5000];
const PAGE_SIZE = 12;

/** Numéros de pages à afficher : 1 … autour de la courante … dernière. */
function pageNumbers(current: number, total: number): (number | "…")[] {
  if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);
  const around = [current - 1, current, current + 1]
    .filter((p) => p > 1 && p < total);
  const out: (number | "…")[] = [1];
  if (around[0] > 2) out.push("…");
  out.push(...around);
  if (around[around.length - 1] < total - 1) out.push("…");
  out.push(total);
  return out;
}

const SORTS: { key: string; label: string }[] = [
  { key: "recent", label: "Nouveautés" },
  { key: "start", label: "Prochaines dates" },
  { key: "price", label: "Prix croissant" },
  { key: "title", label: "A → Z" },
];

export default function Home() {
  const [formations, setFormations] = useState<Formation[] | null>(null);
  const [total, setTotal] = useState(0);
  const [facets, setFacets] = useState<Facets | null>(null);
  const [stats, setStats] = useState<Stats | null>(null);
  const [error, setError] = useState<string | null>(null);

  // filtres (pré-remplis depuis l'URL, ex. /?training_type=Séminaire)
  const [params] = useSearchParams();
  const [q, setQ] = useState(params.get("q") ?? "");
  const [type, setType] = useState(params.get("training_type") ?? "");
  const [category, setCategory] = useState(params.get("category") ?? "");
  const [mode, setMode] = useState(params.get("mode") ?? "");
  const [city, setCity] = useState(params.get("city") ?? "");
  const [language, setLanguage] = useState(params.get("language") ?? "");
  const [level, setLevel] = useState(params.get("level") ?? "");
  const [source, setSource] = useState(params.get("source") ?? "");
  const [free, setFree] = useState(params.get("free") ?? "");
  const [priceMax, setPriceMax] = useState(params.get("price_max") ?? "");
  const [sort, setSort] = useState(params.get("sort") ?? "recent");
  const [page, setPage] = useState(1);
  // feuille de filtres mobile (bottom sheet) + panneau avancé desktop
  const [sheetOpen, setSheetOpen] = useState(false);
  const [advOpen, setAdvOpen] = useState(false);
  const activeFilters = [q, type, category, mode, city, language, level,
    source, free, priceMax].filter(Boolean).length;
  const advCount = [language, level, source, priceMax].filter(Boolean).length;

  const filters: FormationFilters = useMemo(() => ({
    q, training_type: type, category, mode, city, language, level,
    source, free, price_max: priceMax, sort,
  }), [q, type, category, mode, city, language, level, source, free, priceMax, sort]);

  // tout changement de filtre/tri ramène à la première page
  useEffect(() => { setPage(1); }, [filters]);

  // re-rendu quand le registre des noms de sources est chargé
  const [, setSourcesReady] = useState(false);
  useEffect(() => {
    fetchSources()
      .then((r) => { registerSourceNames(r.sources); setSourcesReady(true); })
      .catch(() => {});
    fetchFacets().then(setFacets).catch(() => {});
    fetchStats().then(setStats).catch(() => {});
  }, []);

  useEffect(() => {
    let cancelled = false;
    setFormations(null);
    setError(null);
    fetchFormations({
      ...filters,
      limit: String(PAGE_SIZE),
      offset: String((page - 1) * PAGE_SIZE),
    })
      .then((r) => {
        if (!cancelled) {
          setFormations(r.formations);
          setTotal(r.total);
        }
      })
      .catch((e) => !cancelled && setError(String(e)));
    return () => {
      cancelled = true;
    };
  }, [filters, page]);

  const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
  const goto = (p: number) => {
    setPage(Math.min(Math.max(1, p), totalPages));
    // remonter en haut des résultats, pas de la page
    document.querySelector(".results-head")?.scrollIntoView({ behavior: "smooth" });
  };

  const resetAll = () => {
    setQ(""); setType(""); setCategory(""); setMode(""); setCity("");
    setLanguage(""); setLevel(""); setSource(""); setFree(""); setPriceMax("");
  };

  // pastilles « filtres actifs » — libellé + action de retrait
  const pills: { label: string; clear: () => void }[] = [];
  if (q) pills.push({ label: `« ${q} »`, clear: () => setQ("") });
  if (type) pills.push({ label: type, clear: () => setType("") });
  if (category) pills.push({ label: category, clear: () => setCategory("") });
  if (mode) pills.push({ label: mode, clear: () => setMode("") });
  if (city) pills.push({ label: city, clear: () => setCity("") });
  if (free) pills.push({ label: "Gratuites", clear: () => setFree("") });
  if (priceMax) pills.push({ label: `≤ ${priceMax} $`, clear: () => setPriceMax("") });
  if (language) pills.push({ label: language === "fr" ? "Français" : language === "en" ? "Anglais" : language, clear: () => setLanguage("") });
  if (level) pills.push({ label: level, clear: () => setLevel("") });
  if (source) pills.push({ label: sourceName(source), clear: () => setSource("") });

  const types = facets?.types ?? [];

  return (
    <div className="container">
      <section className="hero">
        <span className="kicker">Agrégateur — toutes les formations du Québec</span>
        <h1>
          Toutes les <span className="outline">formations</span>,<br />
          <span className="hl">un seul</span> endroit.
        </h1>
        <p className="lede">
          Forma-Ka rassemble les cours en ligne, cours universitaires et collégiaux,
          séminaires, ateliers et certifications offerts au Québec — mis à jour
          automatiquement, avec tous les détails et un lien direct vers la formation
          originale.
        </p>
        <div className="stat-row">
          <span className="stat-chip"><span className="pulse" /> Données synchronisées en continu</span>
          {stats && (
            <>
              <span className="stat-chip"><b>{stats.total}</b> formations actives</span>
              {(stats.gratuites ?? 0) > 0 && (
                <span className="stat-chip"><b>{stats.gratuites}</b> gratuites</span>
              )}
              {(stats.en_ligne ?? 0) > 0 && (
                <span className="stat-chip"><b>{stats.en_ligne}</b> en ligne</span>
              )}
              <span className="stat-chip"><b>{stats.sources}</b> établissements</span>
            </>
          )}
        </div>
      </section>

      {sheetOpen && (
        <div className="sheet-backdrop" onClick={() => setSheetOpen(false)} aria-hidden="true" />
      )}
      <section className={`filterbar ${sheetOpen ? "open" : ""}`} aria-label="Filtres">
        <div className="sheet-head">
          <span>Filtres</span>
          <button className="sheet-close" onClick={() => setSheetOpen(false)} aria-label="Fermer les filtres">
            ✕
          </button>
        </div>

        {/* — rangée principale : recherche, domaine, mode, ville, + filtres — */}
        <div className="f-primary">
          <div className="f-search">
            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" aria-hidden="true">
              <circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" />
            </svg>
            <input
              id="f-q" placeholder="Sujet, sigle, compétence…" value={q}
              onChange={(e) => setQ(e.target.value)}
              aria-label="Recherche"
            />
            {q && (
              <button className="f-clear" onClick={() => setQ("")} aria-label="Effacer la recherche">✕</button>
            )}
          </div>
          <label className="f-ctl">
            <span>Domaine</span>
            <select value={category} onChange={(e) => setCategory(e.target.value)}>
              <option value="">Tous</option>
              {(facets?.categories ?? []).map((c) => (
                <option key={c.category} value={c.category}>{c.category} ({c.n})</option>
              ))}
            </select>
          </label>
          <label className="f-ctl">
            <span>Mode</span>
            <select value={mode} onChange={(e) => setMode(e.target.value)}>
              <option value="">Tous</option>
              {(facets?.modes ?? ["en ligne", "présentiel", "hybride", "asynchrone"]).map((m) => (
                <option key={m} value={m}>{m}</option>
              ))}
            </select>
          </label>
          <label className="f-ctl">
            <span>Ville</span>
            <select value={city} onChange={(e) => setCity(e.target.value)}>
              <option value="">Toutes</option>
              {(facets?.cities ?? []).map((c) => (
                <option key={c} value={c}>{c}</option>
              ))}
            </select>
          </label>
          <button
            className={`f-more ${advOpen || advCount > 0 ? "on" : ""}`}
            onClick={() => setAdvOpen(!advOpen)}
            aria-expanded={advOpen}
          >
            Plus de filtres{advCount > 0 ? ` · ${advCount}` : ""} {advOpen ? "▴" : "▾"}
          </button>
        </div>

        {/* — panneau avancé : segments & sélecteurs — */}
        {(advOpen || sheetOpen) && (
          <div className="f-adv">
            <div className="f-group">
              <label>Prix</label>
              <div className="seg" role="group">
                <button className={free === "" && !priceMax ? "on" : ""}
                  onClick={() => { setFree(""); setPriceMax(""); }}>
                  Peu importe
                </button>
                <button className={free === "1" ? "on" : ""}
                  onClick={() => { setFree(free === "1" ? "" : "1"); setPriceMax(""); }}>
                  Gratuites
                </button>
              </div>
            </div>
            <div className="f-group">
              <label>Prix maximum</label>
              <select className="f-native" value={priceMax}
                onChange={(e) => { setPriceMax(e.target.value); setFree(""); }}>
                <option value="">Aucun</option>
                {PRICE_STEPS.map((p) => (
                  <option key={p} value={p}>≤ {p.toLocaleString("fr-CA")} $</option>
                ))}
              </select>
            </div>
            <div className="f-group">
              <label>Langue</label>
              <div className="seg" role="group">
                {[["", "Peu importe"], ["fr", "Français"], ["en", "Anglais"]].map(([v, l]) => (
                  <button key={v} className={language === v ? "on" : ""}
                    onClick={() => setLanguage(v)}>
                    {l}
                  </button>
                ))}
              </div>
            </div>
            <div className="f-group">
              <label>Niveau</label>
              <div className="seg" role="group">
                <button className={level === "" ? "on" : ""} onClick={() => setLevel("")}>
                  Peu importe
                </button>
                {(facets?.levels ?? []).map((l) => (
                  <button key={l} className={level === l ? "on" : ""}
                    onClick={() => setLevel(l)}>
                    {l}
                  </button>
                ))}
              </div>
            </div>
            <div className="f-group">
              <label>Établissement</label>
              <select className="f-native" value={source} onChange={(e) => setSource(e.target.value)}>
                <option value="">Tous</option>
                {(facets?.sources ?? []).map((s) => (
                  <option key={s.source} value={s.source}>
                    {sourceName(s.source)} ({s.n})
                  </option>
                ))}
              </select>
            </div>
            <div className="f-group f-group-end">
              <button className="btn btn-ghost" onClick={resetAll} disabled={activeFilters === 0}>
                Tout réinitialiser{activeFilters > 0 ? ` (${activeFilters})` : ""}
              </button>
            </div>
          </div>
        )}

        <button className="btn btn-primary sheet-apply" onClick={() => setSheetOpen(false)}>
          Voir les résultats {formations ? `(${total})` : ""}
        </button>
      </section>

      <div className="chips" role="group" aria-label="Filtres rapides — type de formation">
        {types.slice(0, 8).map(({ t, n }) => (
          <button
            key={t}
            className={`chip ${type === t ? "on" : ""}`}
            onClick={() => setType(type === t ? "" : t)}
            title={`${n} formations`}
          >
            {t}
          </button>
        ))}
        <span className="chip-sep" aria-hidden="true" />
        <button
          className={`chip ${free === "1" ? "on" : ""}`}
          onClick={() => setFree(free === "1" ? "" : "1")}
        >
          🆓 Gratuites
        </button>
        <button
          className={`chip ${mode === "en ligne" ? "on" : ""}`}
          onClick={() => setMode(mode === "en ligne" ? "" : "en ligne")}
        >
          💻 En ligne
        </button>
      </div>

      {pills.length > 0 && (
        <div className="pills" aria-label="Filtres actifs">
          {pills.map((p) => (
            <button key={p.label} className="pill" onClick={p.clear}
              aria-label={`Retirer le filtre ${p.label}`}>
              {p.label} <span className="pill-x">✕</span>
            </button>
          ))}
          <button className="pill pill-clear" onClick={resetAll}>
            Tout effacer
          </button>
        </div>
      )}

      <div className="results-head">
        <h2>Formations offertes</h2>
        <div className="results-tools">
          {formations && <span>{total} résultat{total > 1 ? "s" : ""}</span>}
          <div className="view-toggle" role="tablist" aria-label="Tri">
            {SORTS.map((s) => (
              <button
                key={s.key}
                role="tab" aria-selected={sort === s.key}
                className={sort === s.key ? "on" : ""}
                onClick={() => setSort(s.key)}
              >
                {s.label}
              </button>
            ))}
          </div>
        </div>
      </div>

      {error && (
        <div className="notice">
          <div className="big">⚠️</div>
          <h2>Impossible de charger les formations</h2>
          <p>{error}</p>
          <button className="btn btn-primary" onClick={() => window.location.reload()}>
            Réessayer
          </button>
        </div>
      )}

      {!error && formations === null && (
        <div className="grid" aria-busy="true">
          {Array.from({ length: 8 }).map((_, i) => (
            <div className="skel" key={i}>
              <div className="sk-img" />
              <div className="sk-line" />
              <div className="sk-line short" />
            </div>
          ))}
        </div>
      )}

      {!error && formations !== null && formations.length === 0 && (
        <div className="notice">
          <div className="big">🔍</div>
          <h2>Aucune formation ne correspond</h2>
          <p>
            Essayez d'élargir vos critères
            {activeFilters > 0 && (
              <> — ou <button className="link-btn" onClick={resetAll}>retirez les {activeFilters} filtres actifs</button></>
            )}.
          </p>
        </div>
      )}

      {!error && formations !== null && formations.length > 0 && (
        <>
          <div className="grid">
            {formations.map((f) => (
              <FormationCard key={f.uid} f={f} />
            ))}
          </div>

          {totalPages > 1 && (
            <nav className="pagination" aria-label="Pagination des résultats">
              <button
                className="page-btn page-prev"
                onClick={() => goto(page - 1)}
                disabled={page <= 1}
                aria-label="Page précédente"
              >
                ← Précédent
              </button>
              {pageNumbers(page, totalPages).map((p, i) =>
                p === "…" ? (
                  <span key={`e${i}`} className="page-ellipsis" aria-hidden="true">…</span>
                ) : (
                  <button
                    key={p}
                    className={`page-btn ${p === page ? "on" : ""}`}
                    onClick={() => goto(p)}
                    aria-current={p === page ? "page" : undefined}
                  >
                    {p}
                  </button>
                )
              )}
              <button
                className="page-btn page-next"
                onClick={() => goto(page + 1)}
                disabled={page >= totalPages}
                aria-label="Page suivante"
              >
                Suivant →
              </button>
            </nav>
          )}
          <div className="fine" style={{ textAlign: "center", marginTop: 8 }}>
            Page {page} de {totalPages} — {total.toLocaleString("fr-CA")} formations
          </div>
        </>
      )}

      {/* Bouton flottant mobile — ouvre la feuille de filtres */}
      <button
        className="fab"
        onClick={() => setSheetOpen(true)}
        aria-label="Ouvrir les filtres"
      >
        ⚙ Filtres{activeFilters > 0 ? ` · ${activeFilters}` : ""}
      </button>
    </div>
  );
}
