// -----------------------------------------------------------------------------
// Immo-Ka — Agrégateur de propriétés à vendre (province de Québec)
// Auteur : Simon-Pierre Boucher — contact@spboucher.ai
// pages/Stats.tsx : statistiques du marché agrégé (totaux + répartitions)
//   Les répartitions sont calculées à partir de /api/facets et /api/listings
//   (échantillon trié par prix) — le backend n'expose pas d'agrégats détaillés.
// -----------------------------------------------------------------------------
import { useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import {
  Facets, Listing, Stats, VpBanniere,
  fetchFacets, fetchListings, fetchSources, fetchStats,
  registerSourceNames, sourceName,
} from "../api";

// --- Survalorisation vs Vrai-Prix : jauge divergente par bannière ------------
const VP_SCALE = 30;   // la jauge couvre −30 % … +30 %
const pctPos = (d: number) => `${((Math.max(-VP_SCALE, Math.min(VP_SCALE, d)) + VP_SCALE) / (2 * VP_SCALE)) * 100}%`;

function VpGauge({ b }: { b: VpBanniere }) {
  const tone = b.median_delta_pct > 10 ? "vp-sur" : b.median_delta_pct < 0 ? "vp-sous" : "vp-juste";
  return (
    <div className="vpg-row">
      <div className="vpg-name">
        {b.banniere}
        <em>{b.n.toLocaleString("fr-CA")} annonces estimées</em>
      </div>
      <div className="vpg-track">
        <span className="vpg-zero" />
        <span
          className="vpg-band"
          style={{ left: pctPos(Math.min(b.p25, b.p75)), width: `calc(${pctPos(Math.max(b.p25, b.p75))} - ${pctPos(Math.min(b.p25, b.p75))})` }}
        />
        <span className={`vpg-median ${tone}`} style={{ left: pctPos(b.median_delta_pct) }} />
      </div>
      <div className={`vpg-value ${tone}`}>
        {b.median_delta_pct > 0 ? "+" : ""}{b.median_delta_pct.toLocaleString("fr-CA")} %
      </div>
      <div className="vpg-split" title={`${b.pct_sous5} % sous l'estimation · ${b.pct_juste} % dans l'estimation · ${b.pct_sur10} % à +10 % et plus`}>
        <span className="vps-sous" style={{ width: `${b.pct_sous5}%` }} />
        <span className="vps-juste" style={{ width: `${b.pct_juste}%` }} />
        <span className="vps-sur" style={{ width: `${b.pct_sur10}%` }} />
      </div>
    </div>
  );
}

function Bars({ rows, unit }: { rows: { key: string; n: number; href?: string }[]; unit?: string }) {
  const max = Math.max(1, ...rows.map((r) => r.n));
  return (
    <div className="hbars">
      {rows.map((r) => (
        <div className="hbar-row" key={r.key}>
          <div className="hbar-label">{r.href ? <Link to={r.href}>{r.key}</Link> : r.key}</div>
          <div className="hbar-track"><span className="hbar-fill" style={{ width: `${(r.n / max) * 100}%` }} /></div>
          <div className="hbar-value">{r.n.toLocaleString("fr-CA")}{unit ? <em> {unit}</em> : ""}</div>
        </div>
      ))}
    </div>
  );
}

export default function StatsPage() {
  const [stats, setStats] = useState<Stats | null>(null);
  const [facets, setFacets] = useState<Facets | null>(null);
  const [sample, setSample] = useState<Listing[] | null>(null);

  useEffect(() => {
    fetchSources().then((r) => registerSourceNames(r.sources)).catch(() => {});
    fetchStats().then(setStats).catch(() => {});
    fetchFacets().then(setFacets).catch(() => {});
    fetchListings({ sort: "price_asc" }, 2000, 0).then((r) => setSample(r.listings)).catch(() => {});
  }, []);

  const byType = useMemo(() => {
    if (!sample) return [];
    const m = new Map<string, number>();
    for (const l of sample) if (l.property_type) m.set(l.property_type, (m.get(l.property_type) ?? 0) + 1);
    return [...m.entries()].map(([key, n]) => ({ key, n, href: `/?property_type=${encodeURIComponent(key)}` }))
      .sort((a, b) => b.n - a.n).slice(0, 12);
  }, [sample]);

  const byCity = useMemo(() => {
    if (!sample) return [];
    const m = new Map<string, number>();
    for (const l of sample) if (l.city) m.set(l.city, (m.get(l.city) ?? 0) + 1);
    return [...m.entries()].map(([key, n]) => ({ key, n, href: `/?city=${encodeURIComponent(key)}` }))
      .sort((a, b) => b.n - a.n).slice(0, 15);
  }, [sample]);

  const bySource = useMemo(() => {
    if (!facets) return [];
    return facets.sources.map((s) => ({ key: sourceName(s.source), n: s.n, href: `/?source=${encodeURIComponent(s.source)}` }))
      .sort((a, b) => b.n - a.n).slice(0, 15);
  }, [facets]);

  const tiles = [
    { v: stats ? stats.total.toLocaleString("fr-CA") : "…", k: "Propriétés à vendre", hero: true },
    { v: stats ? String(stats.sources) : "…", k: "Agences agrégées" },
    { v: stats ? stats.cities.toLocaleString("fr-CA") : "…", k: "Villes couvertes" },
    { v: stats?.avg_price != null ? `${Math.round(stats.avg_price).toLocaleString("fr-CA")} $` : "…", k: "Prix moyen demandé" },
    { v: stats?.min_price != null ? `${Math.round(stats.min_price).toLocaleString("fr-CA")} $` : "…", k: "Prix minimum" },
    { v: stats?.max_price != null ? `${Math.round(stats.max_price).toLocaleString("fr-CA")} $` : "…", k: "Prix maximum" },
  ];

  return (
    <div className="container stats-page">
      <span className="kicker">Le marché agrégé</span>
      <h1 className="stats-title">Statistiques</h1>
      <p className="sub">
        Portrait en direct des propriétés à vendre agrégées par Immo-Ka à travers toutes les
        agences connectées. Répartitions calculées sur un échantillon des annonces actives.
      </p>

      <div className="tiles">
        {tiles.map((t) => (
          <div className={`tile ${t.hero ? "hero-tile" : ""}`} key={t.k}>
            <div className="tile-v">{t.v}</div>
            <div className="tile-k">{t.k}</div>
          </div>
        ))}
      </div>

      <div className="viz-grid">
        <div className="viz-card">
          <h2>Par type de propriété</h2>
          <div className="viz-sub">Échantillon des annonces actives</div>
          {byType.length ? <Bars rows={byType} /> : <p className="fine">Chargement…</p>}
        </div>
        <div className="viz-card">
          <h2>Par agence</h2>
          <div className="viz-sub">Annonces actives (après déduplication)</div>
          {bySource.length ? <Bars rows={bySource} /> : <p className="fine">Chargement…</p>}
        </div>
      </div>

      {stats?.vraiprix?.bannieres && stats.vraiprix.bannieres.length > 0 && (
        <div className="viz-card">
          <h2>Prix demandé vs valeur Vrai-Prix</h2>
          <div className="viz-sub">
            Écart médian entre le prix demandé et l'estimation indépendante Vrai-Prix, par bannière.
            La bande grise couvre la moitié centrale des annonces (P25–P75) ; le trait est la médiane.
          </div>
          <div className="vpg-axis">
            <div><span>−{VP_SCALE} %</span><span>estimation Vrai-Prix</span><span>+{VP_SCALE} %</span></div>
          </div>
          {stats.vraiprix.ensemble && <VpGauge b={stats.vraiprix.ensemble} />}
          <div className="vpg-sep" />
          {stats.vraiprix.bannieres.map((b) => <VpGauge b={b} key={b.banniere} />)}
          <div className="vpg-legend">
            <span><i className="vps-sous" /> sous l'estimation (≤ −5 %)</span>
            <span><i className="vps-juste" /> dans l'estimation</span>
            <span><i className="vps-sur" /> survalorisé (≥ +10 %)</span>
          </div>
        </div>
      )}

      <div className="viz-card">
        <h2>Par ville</h2>
        <div className="viz-sub">Top 15 · échantillon des annonces actives</div>
        {byCity.length ? <Bars rows={byCity} /> : <p className="fine">Chargement…</p>}
      </div>

      {stats?.recent_syncs && stats.recent_syncs.length > 0 && (
        <div className="viz-card">
          <h2>Synchronisations récentes</h2>
          <div className="viz-sub">Journal du moteur d'agrégation</div>
          <div className="viz-table">
            <table>
              <thead><tr><th>Agence</th><th>Trouvées</th><th>Ajoutées</th><th>MàJ</th><th>Retirées</th><th>Quand</th></tr></thead>
              <tbody>
                {stats.recent_syncs.slice(0, 15).map((s, i) => (
                  <tr key={i}>
                    <td>{sourceName(s.source)}</td>
                    <td>{s.found}</td><td>{s.added}</td><td>{s.updated}</td><td>{s.removed}</td>
                    <td style={{ color: "var(--ink-3)" }}>{new Date(s.ts * 1000).toLocaleString("fr-CA")}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      <p className="stats-foot">Mise à jour automatique — chaque fiche renvoie à l'annonce originale de l'agence.</p>
    </div>
  );
}
