// -----------------------------------------------------------------------------
// Lou-Ka — Agrégateur de logements à louer (province de Québec)
// Auteur : Simon-Pierre Boucher — contact@spboucher.ai
// pages/Home.tsx : accueil — héro, statistiques, filtres avancés, grille
//   Filtres : ville, quartier, taille, loyer min/max, dispo, animaux, meublé,
//   superficie, gestionnaire, recherche — avec pastilles de filtres actifs.
// -----------------------------------------------------------------------------
import { Suspense, lazy, useEffect, useMemo, useState } from "react";
import { useSearchParams } from "react-router-dom";
import {
  Facets, Listing, ListingFilters, Stats,
  fetchFacets, fetchListings, fetchSources, fetchStats, isoInDays,
  registerSourceNames, sourceName,
} from "../api";
import ListingCard from "../components/ListingCard";

// La carte (MapLibre, ~220 ko) n'est chargée que si l'utilisateur l'ouvre
const MapView = lazy(() => import("../components/MapView"));

const UNIT_TYPES = ["1½", "2½", "3½", "4½", "5½", "Loft", "Studio"];
const PRICE_STEPS = [600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 2500, 3000];
const AREA_STEPS = [400, 600, 800, 1000, 1200];

/** Choix « Disponibilité » → paramètre API available_by (date ISO) */
const DISPO_CHOICES: { key: string; label: string; days: number | null }[] = [
  { key: "", label: "Peu importe", days: null },
  { key: "now", label: "Maintenant", days: 0 },
  { key: "30", label: "D'ici 1 mois", days: 30 },
  { key: "60", label: "D'ici 2 mois", days: 60 },
  { key: "90", label: "D'ici 3 mois", days: 90 },
];

export default function Home() {
  const [listings, setListings] = useState<Listing[] | null>(null);
  const [total, setTotal] = useState(0);
  const [facets, setFacets] = useState<Facets | null>(null);
  const [sectors, setSectors] = useState<string[]>([]);
  const [stats, setStats] = useState<Stats | null>(null);
  const [error, setError] = useState<string | null>(null);

  // filtres (pré-remplis depuis l'URL, ex. /?city=Montréal — liens de la page Stats)
  const [params] = useSearchParams();
  const [q, setQ] = useState(params.get("q") ?? "");
  const [city, setCity] = useState(params.get("city") ?? "");
  const [sector, setSector] = useState(params.get("sector") ?? "");
  const [source, setSource] = useState(params.get("source") ?? "");
  const [priceMin, setPriceMin] = useState(params.get("price_min") ?? "");
  const [priceMax, setPriceMax] = useState(params.get("price_max") ?? "");
  const [unitType, setUnitType] = useState(params.get("unit_type") ?? "");
  const [dispo, setDispo] = useState(params.get("dispo") ?? "");
  const [pets, setPets] = useState(params.get("pets") ?? "");
  const [furnished, setFurnished] = useState(params.get("furnished") ?? "");
  const [areaMin, setAreaMin] = useState(params.get("area_min") ?? "");
  // feuille de filtres mobile (bottom sheet) + panneau avancé desktop
  const [sheetOpen, setSheetOpen] = useState(false);
  const [advOpen, setAdvOpen] = useState(false);
  const activeFilters = [q, city, sector, source, priceMin, priceMax, unitType,
    dispo, pets, furnished, areaMin].filter(Boolean).length;
  const advCount = [dispo, pets, furnished, areaMin, source].filter(Boolean).length;
  // vue liste ou carte (mémorisée dans l'URL : /?view=carte)
  const [view, setView] = useState<"liste" | "carte">(
    params.get("view") === "carte" ? "carte" : "liste");
  useEffect(() => {
    // suivre l'URL quand on navigue via le menu (« Carte » -> /?view=carte)
    setView(params.get("view") === "carte" ? "carte" : "liste");
  }, [params]);

  const filters: ListingFilters = useMemo(() => {
    const d = DISPO_CHOICES.find((c) => c.key === dispo);
    return {
      q, city, sector, source, unit_type: unitType,
      price_min: priceMin, price_max: priceMax,
      pets, furnished, area_min: areaMin,
      available_by: d?.days != null ? isoInDays(d.days) : "",
    };
  }, [q, city, sector, source, unitType, priceMin, priceMax, pets, furnished, areaMin, dispo]);

  useEffect(() => {
    fetchSources().then((r) => registerSourceNames(r.sources)).catch(() => {});
    fetchFacets().then(setFacets).catch(() => {});
    fetchStats().then(setStats).catch(() => {});
  }, []);

  // quartiers dépendants de la ville choisie
  useEffect(() => {
    fetchFacets(city || undefined)
      .then((f) => setSectors(f.sectors))
      .catch(() => setSectors([]));
  }, [city]);

  useEffect(() => {
    let cancelled = false;
    setListings(null);
    setError(null);
    fetchListings(filters)
      .then((r) => {
        if (!cancelled) {
          setListings(r.listings);
          setTotal(r.total);
        }
      })
      .catch((e) => !cancelled && setError(String(e)));
    return () => {
      cancelled = true;
    };
  }, [filters]);

  const availableTypes = useMemo(() => {
    const set = new Set(facets?.unit_types ?? []);
    return UNIT_TYPES.filter((t) => set.size === 0 || set.has(t));
  }, [facets]);

  const resetAll = () => {
    setQ(""); setCity(""); setSector(""); setSource("");
    setPriceMin(""); setPriceMax(""); setUnitType("");
    setDispo(""); setPets(""); setFurnished(""); setAreaMin("");
  };

  // pastilles « filtres actifs » — libellé + action de retrait
  const pills: { label: string; clear: () => void }[] = [];
  if (q) pills.push({ label: `« ${q} »`, clear: () => setQ("") });
  if (city) pills.push({ label: city, clear: () => { setCity(""); setSector(""); } });
  if (sector) pills.push({ label: sector, clear: () => setSector("") });
  if (unitType) pills.push({ label: unitType, clear: () => setUnitType("") });
  if (priceMin) pills.push({ label: `≥ ${priceMin} $`, clear: () => setPriceMin("") });
  if (priceMax) pills.push({ label: `≤ ${priceMax} $`, clear: () => setPriceMax("") });
  if (dispo) pills.push({
    label: `Dispo : ${DISPO_CHOICES.find((c) => c.key === dispo)?.label ?? dispo}`,
    clear: () => setDispo(""),
  });
  if (pets) pills.push({ label: "Animaux acceptés", clear: () => setPets("") });
  if (furnished) pills.push({
    label: furnished === "1" ? "Meublé" : "Non meublé",
    clear: () => setFurnished(""),
  });
  if (areaMin) pills.push({ label: `≥ ${areaMin} pi²`, clear: () => setAreaMin("") });
  if (source) pills.push({ label: sourceName(source), clear: () => setSource("") });

  return (
    <div className="container">
      <section className="hero">
        <span className="kicker">Agrégateur — Québec · Lévis · Montréal</span>
        <h1>
          Tous les logements <span className="outline">à louer</span>,<br />
          <span className="hl">un seul</span> endroit.
        </h1>
        <p className="lede">
          Lou-Ka rassemble les appartements affichés par les gestionnaires immobiliers du
          Québec — Québec, Lévis et le Grand Montréal — mis à jour automatiquement, avec
          toutes les photos et un lien direct vers l'annonce 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> logements actifs</span>
              <span className="stat-chip"><b>{stats.quebec ?? 0}</b> à Québec</span>
              <span className="stat-chip"><b>{stats.levis ?? 0}</b> à Lévis</span>
              {(stats.montreal ?? 0) > 0 && (
                <span className="stat-chip"><b>{stats.montreal}</b> Grand Montréal</span>
              )}
              {(stats.autres ?? 0) > 0 && (
                <span className="stat-chip"><b>{stats.autres}</b> ailleurs au Québec</span>
              )}
              {stats.avg_price != null && (
                <span className="stat-chip">
                  loyer moyen <b>{Math.round(stats.avg_price)} $</b>
                </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, ville, quartier, loyer, + 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="Adresse, quartier, rue…" 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>Ville</span>
            <select value={city} onChange={(e) => { setCity(e.target.value); setSector(""); }}>
              <option value="">Toutes</option>
              {(facets?.cities ?? ["Québec", "Lévis"]).map((c) => (
                <option key={c} value={c}>{c}</option>
              ))}
            </select>
          </label>
          <label className="f-ctl">
            <span>Quartier</span>
            <select value={sector} onChange={(e) => setSector(e.target.value)}>
              <option value="">Tous</option>
              {sectors.map((s) => (
                <option key={s} value={s}>{s}</option>
              ))}
            </select>
          </label>
          <div className="f-ctl">
            <span>Loyer</span>
            <div className="range-pair">
              <select aria-label="Loyer minimum" value={priceMin}
                onChange={(e) => setPriceMin(e.target.value)}>
                <option value="">Min</option>
                {PRICE_STEPS.map((p) => (
                  <option key={p} value={p} disabled={!!priceMax && p >= Number(priceMax)}>
                    {p} $
                  </option>
                ))}
              </select>
              <span className="range-sep">—</span>
              <select aria-label="Loyer maximum" value={priceMax}
                onChange={(e) => setPriceMax(e.target.value)}>
                <option value="">Max</option>
                {PRICE_STEPS.map((p) => (
                  <option key={p} value={p} disabled={!!priceMin && p <= Number(priceMin)}>
                    {p} $
                  </option>
                ))}
              </select>
            </div>
          </div>
          <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>Disponibilité</label>
              <div className="seg" role="group">
                {DISPO_CHOICES.map((c) => (
                  <button key={c.key} className={dispo === c.key ? "on" : ""}
                    onClick={() => setDispo(c.key)}>
                    {c.label}
                  </button>
                ))}
              </div>
            </div>
            <div className="f-group">
              <label>Meublé</label>
              <div className="seg" role="group">
                {[["", "Peu importe"], ["1", "Oui"], ["0", "Non"]].map(([v, l]) => (
                  <button key={v} className={furnished === v ? "on" : ""}
                    onClick={() => setFurnished(v)}>
                    {l}
                  </button>
                ))}
              </div>
            </div>
            <div className="f-group">
              <label>Animaux</label>
              <div className="seg" role="group">
                {[["", "Peu importe"], ["oui", "🐾 Acceptés"]].map(([v, l]) => (
                  <button key={v} className={pets === v ? "on" : ""}
                    onClick={() => setPets(v)}>
                    {l}
                  </button>
                ))}
              </div>
            </div>
            <div className="f-group">
              <label>Superficie minimale</label>
              <div className="seg" role="group">
                <button className={areaMin === "" ? "on" : ""} onClick={() => setAreaMin("")}>
                  Peu importe
                </button>
                {AREA_STEPS.map((a) => (
                  <button key={a} className={areaMin === String(a) ? "on" : ""}
                    onClick={() => setAreaMin(String(a))}>
                    {a}+
                  </button>
                ))}
              </div>
            </div>
            <div className="f-group">
              <label>Gestionnaire</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 {listings ? `(${total})` : ""}
        </button>
      </section>

      <div className="chips" role="group" aria-label="Filtres rapides">
        {availableTypes.map((t) => (
          <button
            key={t}
            className={`chip ${unitType === t ? "on" : ""}`}
            onClick={() => setUnitType(unitType === t ? "" : t)}
          >
            {t}
          </button>
        ))}
        <span className="chip-sep" aria-hidden="true" />
        <button
          className={`chip ${dispo === "now" ? "on" : ""}`}
          onClick={() => setDispo(dispo === "now" ? "" : "now")}
        >
          ⚡ Dispo maintenant
        </button>
        <button
          className={`chip ${pets === "oui" ? "on" : ""}`}
          onClick={() => setPets(pets === "oui" ? "" : "oui")}
        >
          🐾 Animaux ok
        </button>
        <button
          className={`chip ${furnished === "1" ? "on" : ""}`}
          onClick={() => setFurnished(furnished === "1" ? "" : "1")}
        >
          🛋 Meublé
        </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>Logements disponibles</h2>
        <div className="results-tools">
          {listings && <span>{total} résultat{total > 1 ? "s" : ""}</span>}
          <div className="view-toggle" role="tablist" aria-label="Mode d'affichage">
            <button
              role="tab" aria-selected={view === "liste"}
              className={view === "liste" ? "on" : ""}
              onClick={() => setView("liste")}
            >
              ☰ Liste
            </button>
            <button
              role="tab" aria-selected={view === "carte"}
              className={view === "carte" ? "on" : ""}
              onClick={() => setView("carte")}
            >
              ◈ Carte
            </button>
          </div>
        </div>
      </div>

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

      {!error && view === "liste" && listings === 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 && view === "liste" && listings !== null && listings.length === 0 && (
        <div className="notice">
          <div className="big">🔍</div>
          <h2>Aucun logement 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 && view === "carte" && (
        <div className="map-split">
          <div className="map-list" aria-label="Résultats en liste">
            {(listings ?? []).map((l) => (
              <ListingCard key={l.uid} l={l} />
            ))}
          </div>
          <Suspense fallback={<div className="mapview map-loading">Chargement de la carte…</div>}>
            <MapView filters={filters} />
          </Suspense>
        </div>
      )}

      {!error && view === "liste" && listings !== null && listings.length > 0 && (
        <div className="grid">
          {listings.map((l) => (
            <ListingCard key={l.uid} l={l} />
          ))}
        </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>
  );
}
