// -----------------------------------------------------------------------------
// Lou-Ka — Agrégateur de logements à louer (province de Québec)
// Auteur : Simon-Pierre Boucher — contact@spboucher.ai
// pages/Stats.tsx : observatoire du marché — 5 onglets (Vue d'ensemble, Loyers,
//   Régions & villes, Offre, Gestionnaires), tuiles héro, histogramme,
//   barres mono-série, baisses de prix, santé des sources. Rapport PDF global.
// -----------------------------------------------------------------------------
import { useEffect, useMemo, useState } from "react";
import { Link, useSearchParams } from "react-router-dom";
import {
  API_BASE, DetailedStats, GroupStat,
  fetchDetailedStats, fetchSources, registerSourceNames, sourceName,
} from "../api";

const fmt = (n: number | null | undefined) =>
  n == null ? "—" : n.toLocaleString("fr-CA");
const fmt$ = (n: number | null | undefined) => (n == null ? "—" : `${fmt(n)} $`);

const ONGLETS = [
  { id: "ensemble", label: "Vue d'ensemble", icon: "◎" },
  { id: "loyers", label: "Loyers", icon: "＄" },
  { id: "regions", label: "Régions & villes", icon: "◈" },
  { id: "offre", label: "L'offre", icon: "🏠" },
  { id: "gestionnaires", label: "Gestionnaires", icon: "🗂" },
] as const;
type OngletId = (typeof ONGLETS)[number]["id"];

// ---- infobulle partagée ------------------------------------------------------
interface Tip { x: number; y: number; title: string; lines: string[]; }

function useTooltip() {
  const [tip, setTip] = useState<Tip | null>(null);
  const show = (e: React.MouseEvent, title: string, lines: string[]) =>
    setTip({ x: e.clientX, y: e.clientY, title, lines });
  const hide = () => setTip(null);
  const node = tip && (
    <div className="viz-tip" role="status"
         style={{ left: Math.min(tip.x + 14, window.innerWidth - 190), top: tip.y + 14 }}>
      <div className="viz-tip-title">{tip.title}</div>
      {tip.lines.map((l) => <div key={l}>{l}</div>)}
    </div>
  );
  return { show, hide, node };
}

// ---- barres horizontales (une série) ----------------------------------------
function HBars({ data, unit, tip }: {
  data: { label: string; count: number; avg: number | null; href?: string }[];
  unit: string;
  tip: ReturnType<typeof useTooltip>;
}) {
  const max = Math.max(...data.map((d) => d.count), 1);
  return (
    <div className="hbars">
      {data.map((d) => (
        <div className="hbar-row" key={d.label}
             onMouseMove={(e) => tip.show(e, d.label, [
               `${fmt(d.count)} ${unit}`,
               d.avg != null ? `loyer moyen ${fmt$(d.avg)}` : "loyer non affiché"])}
             onMouseLeave={tip.hide}>
          <span className="hbar-label" title={d.label}>
            {d.href ? <Link to={d.href}>{d.label}</Link> : d.label}
          </span>
          <span className="hbar-track">
            <span className="hbar-fill" style={{ width: `${(d.count / max) * 100}%` }} />
          </span>
          <span className="hbar-value">
            {fmt(d.count)}{d.avg != null && <em> · {fmt$(d.avg)}</em>}
          </span>
        </div>
      ))}
    </div>
  );
}

// ---- barres de pourcentage (inclusions) ---------------------------------------
function PctBars({ data }: { data: { label: string; pct: number | null }[] }) {
  return (
    <div className="hbars">
      {data.filter((d) => d.pct != null).map((d) => (
        <div className="hbar-row" key={d.label}>
          <span className="hbar-label">{d.label}</span>
          <span className="hbar-track">
            <span className="hbar-fill" style={{ width: `${Math.min(100, d.pct!)}%` }} />
          </span>
          <span className="hbar-value">{d.pct!.toLocaleString("fr-CA")} %</span>
        </div>
      ))}
    </div>
  );
}

function DataTable({ rows, unit }: { rows: GroupStat[]; unit: string }) {
  return (
    <details className="viz-table">
      <summary>Voir les données</summary>
      <table>
        <thead>
          <tr><th>Catégorie</th><th>{unit}</th><th>Loyer moyen</th><th>À partir de</th></tr>
        </thead>
        <tbody>
          {rows.map((r) => (
            <tr key={r.key}>
              <td>{r.key}</td><td>{fmt(r.count)}</td>
              <td>{fmt$(r.avg_price)}</td><td>{fmt$(r.min_price)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </details>
  );
}

function Tile({ v, k, hero }: { v: string; k: string; hero?: boolean }) {
  return (
    <div className={`tile ${hero ? "hero-tile" : ""}`}>
      <div className="tile-v">{v}</div>
      <div className="tile-k">{k}</div>
    </div>
  );
}

// ---- page --------------------------------------------------------------------
export default function StatsPage() {
  const [d, setD] = useState<DetailedStats | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [params, setParams] = useSearchParams();
  const onglet = (params.get("onglet") as OngletId) || "ensemble";
  const tip = useTooltip();

  useEffect(() => {
    fetchSources().then((r) => registerSourceNames(r.sources)).catch(() => {});
    fetchDetailedStats().then(setD).catch((e) => setError(String(e)));
  }, []);

  const histMax = useMemo(
    () => Math.max(...(d?.histogram.map((h) => h.count) ?? [1]), 1), [d]);

  if (error)
    return (
      <div className="notice container">
        <div className="big">⚠️</div>
        <h2>Statistiques indisponibles</h2>
        <p>{error}</p>
      </div>
    );

  if (!d)
    return (
      <div className="container stats-page" aria-busy="true">
        <div className="skel" style={{ height: 120, marginTop: 40 }} />
        <div className="skel" style={{ height: 300, marginTop: 20 }} />
      </div>
    );

  const t = d.totals;
  const o = d.offre;
  const fold = (rest: GroupStat[]): GroupStat | null =>
    rest.length === 0 ? null : {
      key: `Autres (${rest.length})`,
      count: rest.reduce((s, r) => s + r.count, 0),
      avg_price: null, min_price: null,
    };

  const histogramme = (
    <section className="viz-card">
      <h2>Distribution des loyers</h2>
      <p className="viz-sub">{fmt(t.with_price)} annonces avec prix affiché — classes de 200 $</p>
      <div className="histo" role="img" aria-label="Histogramme des loyers mensuels">
        {d.histogram.map((h) => (
          <div className="histo-col" key={`${h.lo}`}
               onMouseMove={(e) => tip.show(e,
                 h.hi ? `${fmt(h.lo)} – ${fmt(h.hi)} $` : `${fmt(h.lo)} $ et plus`,
                 [`${fmt(h.count)} logements`,
                  `${((h.count / Math.max(t.with_price, 1)) * 100).toFixed(1)} % du parc`])}
               onMouseLeave={tip.hide}>
            <div className="histo-bar-zone">
              <div className="histo-bar" style={{ height: `${(h.count / histMax) * 100}%` }} />
            </div>
            <div className="histo-x">
              {h.lo % 400 === 0 ? (h.lo >= 1000 ? `${h.lo / 1000}k` : h.lo) : ""}
            </div>
          </div>
        ))}
      </div>
    </section>
  );

  return (
    <div className="container stats-page">
      {tip.node}
      <span className="kicker">Observatoire — marché locatif québécois</span>
      <h1 className="stats-title">Le marché, en chiffres</h1>
      <p className="sub">
        Calculé en direct sur les {fmt(t.total)} annonces actives de {fmt(t.sources)} gestionnaires,
        dans {fmt(t.cities)} villes et {fmt(t.regions)} régions.
      </p>
      <p>
        <a className="btn btn-primary" href={`${API_BASE}/api/stats/rapport.pdf`} download>
          📊 Télécharger le rapport global (PDF)
        </a>
      </p>

      {/* barre d'onglets */}
      <nav className="onglets" role="tablist" aria-label="Sections des statistiques">
        {ONGLETS.map((g) => (
          <button key={g.id} role="tab" aria-selected={onglet === g.id}
                  className={`onglet ${onglet === g.id ? "on" : ""}`}
                  onClick={() => setParams(g.id === "ensemble" ? {} : { onglet: g.id })}>
            <span aria-hidden="true">{g.icon}</span> {g.label}
          </button>
        ))}
      </nav>

      {/* ============ Vue d'ensemble ============ */}
      {onglet === "ensemble" && (
        <>
          <div className="tiles">
            <Tile hero v={fmt(t.total)} k="logements actifs" />
            <Tile v={fmt$(t.median)} k="loyer médian" />
            <Tile v={fmt$(t.avg)} k="loyer moyen" />
            <Tile v={fmt(t.dispo_now)} k="libres maintenant" />
            <Tile v={t.superficie_moyenne ? `${fmt(t.superficie_moyenne)} pi²` : "—"} k="superficie moyenne" />
            <Tile v={t.gps_pct != null ? `${t.gps_pct} %` : "—"} k="géolocalisées" />
          </div>
          <section className="viz-card">
            <h2>Couverture par région</h2>
            <p className="viz-sub">annonces actives · loyer moyen régional</p>
            <HBars tip={tip} unit="logements"
                   data={d.by_region.map((r) => ({ label: r.key, count: r.count, avg: r.avg_price }))} />
            <DataTable rows={d.by_region} unit="Logements" />
          </section>
          {histogramme}
        </>
      )}

      {/* ============ Loyers ============ */}
      {onglet === "loyers" && (
        <>
          <div className="tiles">
            <Tile hero v={fmt$(t.median)} k="loyer médian" />
            <Tile v={fmt$(t.avg)} k="loyer moyen" />
            <Tile v={fmt$(t.min)} k="loyer le plus bas" />
            <Tile v={fmt$(t.max)} k="loyer le plus élevé" />
          </div>
          {histogramme}
          <div className="viz-grid">
            <section className="viz-card">
              <h2>Par taille de logement</h2>
              <p className="viz-sub">nombre d'annonces · loyer moyen</p>
              <HBars tip={tip} unit="logements"
                     data={d.by_type.slice(0, 9).map((r) => ({
                       label: r.key, count: r.count, avg: r.avg_price,
                       href: `/?unit_type=${encodeURIComponent(r.key)}` }))} />
              <DataTable rows={d.by_type} unit="Logements" />
            </section>
            <section className="viz-card">
              <h2>Prix au pied carré</h2>
              <p className="viz-sub">loyer ÷ superficie, par taille (annonces publiant les deux)</p>
              <div className="hbars">
                {o.prix_pi2.map((r) => {
                  const max = Math.max(...o.prix_pi2.map((x) => x.val), 0.01);
                  return (
                    <div className="hbar-row" key={r.key}>
                      <span className="hbar-label">{r.key}</span>
                      <span className="hbar-track">
                        <span className="hbar-fill" style={{ width: `${(r.val / max) * 100}%` }} />
                      </span>
                      <span className="hbar-value">
                        {r.val.toLocaleString("fr-CA")} $/pi²<em> · {r.count}</em>
                      </span>
                    </div>
                  );
                })}
              </div>
            </section>
          </div>
          {d.baisses.length > 0 && (
            <section className="viz-card">
              <h2>Baisses de prix récentes 📉</h2>
              <p className="viz-sub">30 derniers jours — leviers de négociation</p>
              <ul className="baisses">
                {d.baisses.map((b) => (
                  <li key={b.uid}>
                    <Link to={`/logement/${encodeURIComponent(b.uid)}`}>
                      {b.title || b.uid}
                    </Link>
                    <span className="baisse-ville">{b.city}</span>
                    <span className="baisse-prix">
                      <s>{fmt$(b.avant)}</s> → <b>{fmt$(b.apres)}</b>
                      <em className="baisse-pct">{b.pct.toLocaleString("fr-CA")} %</em>
                    </span>
                  </li>
                ))}
              </ul>
            </section>
          )}
        </>
      )}

      {/* ============ Régions & villes ============ */}
      {onglet === "regions" && (
        <>
          <section className="viz-card">
            <h2>Par région</h2>
            <p className="viz-sub">annonces · gestionnaires · loyer moyen</p>
            <HBars tip={tip} unit="logements"
                   data={d.by_region.map((r) => ({ label: r.key, count: r.count, avg: r.avg_price }))} />
            <details className="viz-table" open>
              <summary>Voir les données</summary>
              <table>
                <thead><tr><th>Région</th><th>Annonces</th><th>Sources</th><th>Loyer moyen</th></tr></thead>
                <tbody>
                  {d.by_region.map((r) => (
                    <tr key={r.key}>
                      <td>{r.key}</td><td>{fmt(r.count)}</td>
                      <td>{r.sources ?? "—"}</td><td>{fmt$(r.avg_price)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </details>
          </section>
          <section className="viz-card">
            <h2>Par ville</h2>
            <p className="viz-sub">top 20 — nombre d'annonces · loyer moyen</p>
            <HBars tip={tip} unit="logements"
                   data={[...d.by_city.slice(0, 20).map((r) => ({
                     label: r.key, count: r.count, avg: r.avg_price,
                     href: `/?city=${encodeURIComponent(r.key)}` })),
                     ...(fold(d.by_city.slice(20))
                       ? [{ label: fold(d.by_city.slice(20))!.key,
                            count: fold(d.by_city.slice(20))!.count, avg: null }] : [])]} />
            <DataTable rows={d.by_city} unit="Logements" />
          </section>
        </>
      )}

      {/* ============ L'offre ============ */}
      {onglet === "offre" && (
        <>
          <div className="tiles">
            <Tile hero v={fmt(o.dispo_now)} k="libres maintenant" />
            <Tile v={fmt(o.dispo_date)} k="libres à date future" />
            <Tile v={o.superficie_moyenne ? `${fmt(o.superficie_moyenne)} pi²` : "—"} k="superficie moyenne" />
            <Tile v={o.pets_oui_pct != null ? `${o.pets_oui_pct} %` : "—"}
                  k={`acceptent les animaux (sur ${fmt(o.pets_connu)} précisées)`} />
          </div>
          <section className="viz-card">
            <h2>Inclusions et caractéristiques</h2>
            <p className="viz-sub">part du parc dont la source confirme l'inclusion — le reste est inconnu, pas absent</p>
            <PctBars data={[
              { label: "Balcon", pct: o.balcon_pct },
              { label: "Stationnement", pct: o.stationnement_pct },
              { label: "Climatisation", pct: o.clim_pct },
              { label: "Internet inclus", pct: o.internet_pct },
              { label: "Eau chaude incluse", pct: o.eau_chaude_pct },
              { label: "Chauffage inclus", pct: o.chauffage_pct },
              { label: "Électricité incluse", pct: o.electricite_pct },
              { label: "Meublé", pct: o.furnished_pct },
            ].sort((a, b) => (b.pct ?? 0) - (a.pct ?? 0))} />
          </section>
          <section className="viz-card">
            <h2>Par taille de logement</h2>
            <HBars tip={tip} unit="logements"
                   data={d.by_type.slice(0, 9).map((r) => ({
                     label: r.key, count: r.count, avg: r.avg_price,
                     href: `/?unit_type=${encodeURIComponent(r.key)}` }))} />
          </section>
        </>
      )}

      {/* ============ Gestionnaires ============ */}
      {onglet === "gestionnaires" && (
        <>
          <div className="tiles">
            <Tile hero v={fmt(t.sources)} k="gestionnaires connectés" />
            <Tile v={fmt(d.sante.sources_sync_24h)} k="synchronisés (24 h)" />
            <Tile v={fmt(d.sante.alertes_24h.length)} k="alertes (24 h)" />
          </div>
          <section className="viz-card">
            <h2>Par gestionnaire immobilier</h2>
            <p className="viz-sub">top 20 — nombre d'annonces · loyer moyen</p>
            <HBars tip={tip} unit="logements"
                   data={[...d.by_source.slice(0, 20).map((r) => ({
                     label: sourceName(r.key), count: r.count, avg: r.avg_price,
                     href: `/?source=${encodeURIComponent(r.key)}` })),
                     ...(fold(d.by_source.slice(20))
                       ? [{ label: fold(d.by_source.slice(20))!.key,
                            count: fold(d.by_source.slice(20))!.count, avg: null }] : [])]} />
            <DataTable rows={d.by_source.map((r) => ({ ...r, key: sourceName(r.key) }))}
                       unit="Logements" />
          </section>
          {d.sante.alertes_24h.length > 0 && (
            <section className="viz-card">
              <h2>Alertes de synchronisation (24 h)</h2>
              <ul className="alertes">
                {d.sante.alertes_24h.map((a, i) => (
                  <li key={i}><b>{sourceName(a.source)}</b> — {a.message}</li>
                ))}
              </ul>
            </section>
          )}
          <p className="stats-foot">
            <Link to="/sources">Voir le registre complet des sources →</Link>
          </p>
        </>
      )}

      <p className="stats-foot">
        Données recalculées à chaque synchronisation (horaire). Les catégories
        renvoient vers les logements filtrés correspondants.
      </p>
    </div>
  );
}
