/* global React, Icon */
// ============================================================================
// AUDIT CONSOLIDÉ — cross-cycle health view per project (SAT + DVT)
// ----------------------------------------------------------------------------
// Combines SAT (M&E System Assessment) and DVT (Data Verification) into a
// single dashboard per project: latest scores, score-evolution trend, top
// priority actions across both tools, full audit history.
// All data is pulled live from the existing hooks; nothing new is persisted.
// ============================================================================
const { useState: useStateAD, useEffect: useEffectAD, useMemo: useMemoAD } = React;

// Reuse the same SAT scoring helper (defined in screens-audit.jsx via
// computeScores). We re-implement a slimmer variant here for self-containment.
function ad_satScores(norms, responses) {
  const respByNorm = new Map();
  (responses || []).forEach((r) => respByNorm.set(r.norm_id, r));
  const perDomain = {};
  (norms || []).forEach((n) => {
    const r = respByNorm.get(n.id);
    const d = n.domain_code;
    if (!perDomain[d]) perDomain[d] = { total: 0, max: 0 };
    if (r && r.rating && r.rating !== "na" && r.value != null) {
      perDomain[d].total += Number(r.value) || 0;
      perDomain[d].max   += Number(n.max_value) || 0;
    }
  });
  let total = 0, max = 0;
  Object.values(perDomain).forEach((d) => { total += d.total; max += d.max; });
  Object.keys(perDomain).forEach((k) => {
    perDomain[k].pct = perDomain[k].max > 0 ? perDomain[k].total / perDomain[k].max : 0;
  });
  return { perDomain, total: { total, max, pct: max > 0 ? total / max : 0 } };
}

function ad_variancePct(verified, reported) {
  const v = Number(verified), r = Number(reported);
  if (!isFinite(v) || !isFinite(r) || v === 0) return null;
  return ((r - v) / v) * 100;
}
function ad_avgVar(row) {
  const vals = [
    ad_variancePct(row.m1_verified, row.m1_reported),
    ad_variancePct(row.m2_verified, row.m2_reported),
    ad_variancePct(row.m3_verified, row.m3_reported),
  ].filter((v) => v != null);
  if (vals.length === 0) return null;
  return vals.reduce((s, x) => s + x, 0) / vals.length;
}

const AD_COLORS = {
  ok:      { fg: "#15803d", bg: "#dcfce7", border: "#86efac" },
  amber:   { fg: "#a16207", bg: "#fef3c7", border: "#fcd34d" },
  bad:     { fg: "#b91c1c", bg: "#fee2e2", border: "#fca5a5" },
  neutral: { fg: "#374151", bg: "#f3f4f6", border: "#d1d5db" },
  accent:  { fg: "#1e3a8a", bg: "#e0e7ff", border: "#a5b4fc" },
};
const satStatus = (p) => p >= 0.7 ? "ok" : p >= 0.6 ? "amber" : "bad";
const dvtStatus = (v) => v == null ? "neutral" : Math.abs(v) <= 5 ? "ok" : Math.abs(v) <= 10 ? "amber" : "bad";

// ----------------------------------------------------------------------------
function AuditDashboard({ t, lang, setRoute }) {
  const { projects } = window.melr.useProjects();
  const { domains, norms, loading: catLoading } = window.melr.useSatCatalog();
  const [projectId, setProjectId] = useStateAD("");

  useEffectAD(() => {
    if (!projectId && projects && projects.length > 0) setProjectId(projects[0].uuid);
  }, [projects]);

  const { data: satEvals } = window.melr.useSatEvaluations(projectId);
  const { data: dvtAudits } = window.melr.useDvtAudits(projectId);

  // Pick latest SAT cycle (sort by cycle string desc)
  const latestSat = useMemoAD(() => {
    if (!satEvals || satEvals.length === 0) return null;
    return [...satEvals].sort((a, b) => String(b.cycle).localeCompare(String(a.cycle)))[0];
  }, [satEvals]);
  const { data: latestSatResp }  = window.melr.useSatResponses(latestSat ? latestSat.id : null);
  const { data: latestSatPlan }  = window.melr.useSatActionPlan(latestSat ? latestSat.id : null);
  const satScores = useMemoAD(() => ad_satScores(norms, latestSatResp), [norms, latestSatResp]);

  // Pick latest DVT audit (sort by cycle, then updated_at)
  const latestDvt = useMemoAD(() => {
    if (!dvtAudits || dvtAudits.length === 0) return null;
    return [...dvtAudits].sort((a, b) => {
      const c = String(b.cycle).localeCompare(String(a.cycle));
      if (c !== 0) return c;
      return String(b.updated_at || "").localeCompare(String(a.updated_at || ""));
    })[0];
  }, [dvtAudits]);
  const { data: latestDvtVerif }    = window.melr.useDvtVerifications(latestDvt ? latestDvt.id : null);
  const { data: latestDvtImprov }   = window.melr.useDvtImprovements(latestDvt ? latestDvt.id : null);
  const dvtEnriched = useMemoAD(() => (latestDvtVerif || []).map((r) => ({
    ...r,
    avg_var: ad_avgVar(r),
  })), [latestDvtVerif]);
  const dvtAggregates = useMemoAD(() => {
    const measured = dvtEnriched.filter((r) => r.avg_var != null);
    const over5 = measured.filter((r) => Math.abs(r.avg_var) > 5);
    const meanAbs = measured.length > 0
      ? measured.reduce((s, r) => s + Math.abs(r.avg_var), 0) / measured.length
      : 0;
    return { measuredCount: measured.length, over5pctCount: over5.length, meanAbsVariance: meanAbs };
  }, [dvtEnriched]);

  // ----- Cross-cycle aggregation: scores for ALL SAT cycles + DVT audits -----
  // One round-trip per kind (responses across all evals / verifications across
  // all audits) using `.in('evaluation_id', allIds)`. Grouped client-side.
  const [allSatResponses, setAllSatResponses] = useStateAD({});  // { evalId → responses[] }
  const [allDvtVerifs, setAllDvtVerifs]       = useStateAD({});  // { auditId → verifs[] }

  useEffectAD(() => {
    let cancelled = false;
    if (!satEvals || satEvals.length === 0) { setAllSatResponses({}); return; }
    const ids = satEvals.map((e) => e.id);
    (async () => {
      try {
        const sb = window.melr.supabase;
        if (!sb) return;
        const r = await sb.from("sat_responses")
          .select("evaluation_id, norm_id, rating, value")
          .in("evaluation_id", ids);
        if (cancelled || r.error) return;
        const grouped = {};
        (r.data || []).forEach((row) => {
          if (!grouped[row.evaluation_id]) grouped[row.evaluation_id] = [];
          grouped[row.evaluation_id].push(row);
        });
        setAllSatResponses(grouped);
      } catch (e) { console.error("[audit-dashboard] sat-all:", e); }
    })();
    return () => { cancelled = true; };
  }, [satEvals]);

  useEffectAD(() => {
    let cancelled = false;
    if (!dvtAudits || dvtAudits.length === 0) { setAllDvtVerifs({}); return; }
    const ids = dvtAudits.map((a) => a.id);
    (async () => {
      try {
        const sb = window.melr.supabase;
        if (!sb) return;
        const r = await sb.from("dvt_verifications")
          .select("audit_id, position, m1_verified, m1_reported, m2_verified, m2_reported, m3_verified, m3_reported")
          .in("audit_id", ids);
        if (cancelled || r.error) return;
        const grouped = {};
        (r.data || []).forEach((row) => {
          if (!grouped[row.audit_id]) grouped[row.audit_id] = [];
          grouped[row.audit_id].push(row);
        });
        setAllDvtVerifs(grouped);
      } catch (e) { console.error("[audit-dashboard] dvt-all:", e); }
    })();
    return () => { cancelled = true; };
  }, [dvtAudits]);

  // Per-SAT-cycle scores (overall and per-domain) — ordered ascending by cycle
  const satTrend = useMemoAD(() => {
    if (!satEvals || satEvals.length === 0 || !norms || norms.length === 0) return [];
    return [...satEvals]
      .sort((a, b) => String(a.cycle).localeCompare(String(b.cycle)))
      .map((e) => {
        const resp = allSatResponses[e.id] || [];
        const sc = ad_satScores(norms, resp);
        return { id: e.id, cycle: e.cycle, scores: sc, updated_at: e.updated_at };
      });
  }, [satEvals, allSatResponses, norms]);

  // Per-DVT-audit aggregates — ordered ascending
  const dvtTrend = useMemoAD(() => {
    if (!dvtAudits || dvtAudits.length === 0) return [];
    return [...dvtAudits]
      .sort((a, b) => {
        const c = String(a.cycle).localeCompare(String(b.cycle));
        if (c !== 0) return c;
        return String(a.updated_at || "").localeCompare(String(b.updated_at || ""));
      })
      .map((a) => {
        const verifs = allDvtVerifs[a.id] || [];
        const enriched = verifs.map((r) => ({ ...r, avg_var: ad_avgVar(r) }));
        const measured = enriched.filter((r) => r.avg_var != null);
        const over5 = measured.filter((r) => Math.abs(r.avg_var) > 5);
        const meanAbs = measured.length > 0
          ? measured.reduce((s, r) => s + Math.abs(r.avg_var), 0) / measured.length : 0;
        const siteLbl = a.sites && a.sites.code ? a.sites.code : (a.site_name || "—");
        return { id: a.id, cycle: a.cycle, siteLbl, measuredCount: measured.length, over5pctCount: over5.length, meanAbsVariance: meanAbs, updated_at: a.updated_at };
      });
  }, [dvtAudits, allDvtVerifs]);

  // SAT trend delta vs previous cycle (for the KPI tile arrow)
  const satTrendDelta = useMemoAD(() => {
    if (satTrend.length < 2) return null;
    const last = satTrend[satTrend.length - 1].scores.total.pct;
    const prev = satTrend[satTrend.length - 2].scores.total.pct;
    return { last, prev, delta: last - prev };
  }, [satTrend]);

  const proj = (projects || []).find((p) => p.uuid === projectId);
  const today = new Date().toLocaleDateString(lang === "fr" ? "fr-FR" : "en-US");

  // Combine priority actions from both tools
  const consolidatedActions = useMemoAD(() => {
    const acts = [];
    // SAT priority recommendations from latest cycle responses
    (latestSatResp || []).filter((r) => r.is_priority).forEach((r) => {
      const norm = (norms || []).find((n) => n.id === r.norm_id);
      acts.push({
        source: "SAT",
        ref: norm ? norm.domain_code + "." + norm.position : "?",
        text: r.observation || (norm ? norm.text_fr : "—"),
        owner: null, due_date: null, status: null, priority: 2,
        sourceCycle: latestSat ? latestSat.cycle : "—",
      });
    });
    // SAT action plan items
    (latestSatPlan || []).forEach((it) => {
      acts.push({
        source: "SAT",
        ref: (it.domain_code || "?") + "." + (it.norm_position || ""),
        text: it.text || "—",
        owner: it.owner, due_date: it.due_date, status: it.status,
        priority: it.priority || 2,
        sourceCycle: latestSat ? latestSat.cycle : "—",
      });
    });
    // DVT improvements from latest audit
    (latestDvtImprov || []).filter((i) => i.indicator_name || i.problem).forEach((i) => {
      acts.push({
        source: "DVT",
        ref: "#" + i.position,
        text: (i.problem ? i.problem + " — " : "") + (i.corrective_action || ""),
        owner: i.responsible, due_date: i.due_date, status: null,
        priority: 1,  // DVT improvements are always priority by definition (>5% variance)
        sourceCycle: latestDvt ? latestDvt.cycle : "—",
        indicator: i.indicator_name,
      });
    });
    // Sort: SAT/DVT priority first (1 > 2 > 3), then by due_date ascending
    acts.sort((a, b) => {
      const pd = (a.priority || 9) - (b.priority || 9);
      if (pd !== 0) return pd;
      const ad = a.due_date || "9999-99";
      const bd = b.due_date || "9999-99";
      return String(ad).localeCompare(String(bd));
    });
    return acts;
  }, [latestSatResp, latestSatPlan, latestDvtImprov, norms, latestSat, latestDvt]);

  const Tile = ({ label, value, sub, status, onClick }) => {
    const c = AD_COLORS[status || "neutral"];
    return (
      <div onClick={onClick} style={{
        border: "1px solid " + c.border, background: c.bg, color: c.fg,
        borderRadius: 6, padding: "12px 14px", minHeight: 80,
        cursor: onClick ? "pointer" : "default",
        transition: "transform .1s ease",
      }} onMouseEnter={(e) => { if (onClick) e.currentTarget.style.transform = "translateY(-1px)"; }}
         onMouseLeave={(e) => { if (onClick) e.currentTarget.style.transform = "none"; }}>
        <div style={{ fontSize: 10, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em", opacity: 0.8 }}>{label}</div>
        <div style={{ fontSize: 22, fontWeight: 700, fontFamily: "Consolas, monospace", marginTop: 4 }}>{value}</div>
        {sub && <div style={{ fontSize: 10.5, opacity: 0.75, marginTop: 3 }}>{sub}</div>}
      </div>
    );
  };

  return (
    <div className="page">
      <div className="page-header">
        <div className="page-eyebrow">{lang === "fr" ? "MODULE / AUDIT CONSOLIDÉ" : "MODULE / CONSOLIDATED AUDIT"}</div>
        <div className="page-header-row">
          <div>
            <h1 className="page-title">{lang === "fr" ? "Synthèse audits" : "Audit dashboard"}</h1>
            <div className="page-sub">
              {lang === "fr"
                ? "Vue unifiée SAT (système S&E) + DVT (qualité données) par projet · dernier cycle, évolution, actions prioritaires"
                : "Unified SAT (M&E system) + DVT (data quality) view per project · latest cycle, trends, priority actions"}
            </div>
          </div>
        </div>
      </div>

      <div className="page-body">
        {/* Project selector */}
        <div className="card" style={{ marginBottom: 14 }}>
          <div className="card-body" style={{ display: "flex", alignItems: "center", gap: 12, padding: "10px 14px" }}>
            <span className="text-faint" style={{ fontSize: 11.5, textTransform: "uppercase", letterSpacing: "0.04em" }}>
              {lang === "fr" ? "Projet" : "Project"}
            </span>
            <select value={projectId} onChange={(e) => setProjectId(e.target.value)}
              style={{ padding: "6px 10px", borderRadius: 6, border: "1px solid var(--line)", fontSize: 13, background: "var(--bg, white)", color: "var(--text)", minWidth: 320 }}>
              <option value="">{lang === "fr" ? "— choisir un projet —" : "— pick a project —"}</option>
              {(projects || []).map((p) => (
                <option key={p.uuid} value={p.uuid}>{p.id} — {lang === "fr" ? p.nameFr : p.nameEn}</option>
              ))}
            </select>
            {proj && (
              <span className="text-faint" style={{ fontSize: 11, marginLeft: "auto" }}>
                {lang === "fr" ? "Mis à jour le " : "Updated "} {today}
              </span>
            )}
          </div>
        </div>

        {!projectId ? (
          <div className="card"><div className="card-body" style={{ padding: 50, textAlign: "center", color: "var(--text-faint)" }}>
            {lang === "fr" ? "Sélectionnez un projet pour voir la synthèse audits." : "Pick a project to see the audit dashboard."}
          </div></div>
        ) : (
          <>
            {/* KPI tiles row (5 tiles when a SAT trend is computable) */}
            <div className="grid" style={{ gridTemplateColumns: satTrendDelta ? "repeat(5, 1fr)" : "repeat(4, 1fr)", gap: 12, marginBottom: 14, display: "grid" }}>
              <Tile
                label={lang === "fr" ? "Cycles SAT" : "SAT cycles"}
                value={satEvals.length}
                sub={latestSat ? lang === "fr" ? "Dernier : " + latestSat.cycle : "Latest: " + latestSat.cycle : "—"}
                status="accent"
                onClick={() => setRoute("audit_system")}
              />
              <Tile
                label={lang === "fr" ? "Dernier score SAT" : "Latest SAT score"}
                value={latestSat ? Math.round(satScores.total.pct * 100) + "%" : "—"}
                sub={satScores.total.max > 0 ? satScores.total.total + " / " + satScores.total.max : (lang === "fr" ? "Aucune donnée" : "No data")}
                status={latestSat && satScores.total.max > 0 ? satStatus(satScores.total.pct) : "neutral"}
                onClick={() => setRoute("audit_system")}
              />
              {satTrendDelta && (
                <Tile
                  label={lang === "fr" ? "Tendance SAT" : "SAT trend"}
                  value={(satTrendDelta.delta > 0 ? "↗ +" : satTrendDelta.delta < 0 ? "↘ " : "→ ") + (satTrendDelta.delta * 100).toFixed(1) + " pts"}
                  sub={(satTrendDelta.delta > 0 ? (lang === "fr" ? "progression" : "improvement")
                        : satTrendDelta.delta < 0 ? (lang === "fr" ? "régression" : "decline")
                        : (lang === "fr" ? "stable" : "stable")) + " · vs " + satTrend[satTrend.length - 2].cycle}
                  status={satTrendDelta.delta > 0.02 ? "ok" : satTrendDelta.delta < -0.02 ? "bad" : "amber"}
                  onClick={() => setRoute("audit_system")}
                />
              )}
              <Tile
                label={lang === "fr" ? "Audits DVT" : "DVT audits"}
                value={dvtAudits.length}
                sub={latestDvt ? lang === "fr" ? "Dernier : " + latestDvt.cycle : "Latest: " + latestDvt.cycle : "—"}
                status="accent"
                onClick={() => setRoute("audit_data")}
              />
              <Tile
                label={lang === "fr" ? "Variance DVT moy." : "DVT mean |variance|"}
                value={dvtAggregates.measuredCount > 0 ? dvtAggregates.meanAbsVariance.toFixed(1) + "%" : "—"}
                sub={dvtAggregates.measuredCount > 0
                  ? dvtAggregates.over5pctCount + " " + (lang === "fr" ? "hors seuil" : "off-target")
                  : (lang === "fr" ? "Aucune donnée" : "No data")}
                status={dvtAggregates.measuredCount > 0 ? dvtStatus(dvtAggregates.meanAbsVariance) : "neutral"}
                onClick={() => setRoute("audit_data")}
              />
            </div>

            <div className="grid cols-2" style={{ gap: 14 }}>
              {/* SAT card */}
              <div className="card">
                <div className="card-head">
                  <div className="card-title">{lang === "fr" ? "Audit système S&E (SAT)" : "M&E System Audit (SAT)"}</div>
                  {latestSat && (
                    <>
                      <span className="tag-mono" style={{ marginLeft: 8 }}>{latestSat.cycle}</span>
                      <span className={"pill " + (satScores.total.max > 0 ? satStatus(satScores.total.pct) : "")}
                        style={{ marginLeft: 6 }}>
                        {satScores.total.max > 0 ? Math.round(satScores.total.pct * 100) + "%" : "—"}
                      </span>
                    </>
                  )}
                  <button className="btn sm ghost" style={{ marginLeft: "auto" }} onClick={() => setRoute("audit_system")}>
                    {lang === "fr" ? "Détail →" : "Detail →"}
                  </button>
                </div>
                <div className="card-body" style={{ padding: latestSat ? "0" : "20px" }}>
                  {!latestSat && (
                    <div style={{ textAlign: "center", color: "var(--text-faint)", padding: 30 }}>
                      {lang === "fr" ? "Aucun cycle SAT pour ce projet." : "No SAT cycle for this project."}
                    </div>
                  )}
                  {latestSat && (
                    <div style={{ display: "grid", gridTemplateColumns: "180px 1fr", gap: 16, padding: 14 }}>
                      <AdSatRadar domains={domains} scores={satScores} />
                      <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
                        {(domains || []).map((d) => {
                          const sc = satScores.perDomain[d.code] || { total: 0, max: 0, pct: 0 };
                          const st = sc.max > 0 ? satStatus(sc.pct) : "neutral";
                          return (
                            <div key={d.code} style={{ display: "grid", gridTemplateColumns: "auto 1fr 60px", gap: 8, alignItems: "center", fontSize: 11.5 }}>
                              <span className="tag-mono" style={{ fontWeight: 600 }}>{d.code}</span>
                              <div className={"progress-bar " + (sc.pct >= 0.7 ? "green" : sc.pct >= 0.6 ? "amber" : "red")} style={{ height: 6 }}>
                                <div className="fill" style={{ width: (sc.pct * 100).toFixed(0) + "%" }}></div>
                              </div>
                              <span style={{
                                textAlign: "right", fontFamily: "Consolas, monospace",
                                color: AD_COLORS[st].fg, fontWeight: 600,
                              }}>
                                {sc.max > 0 ? Math.round(sc.pct * 100) + "%" : "—"}
                              </span>
                            </div>
                          );
                        })}
                      </div>
                    </div>
                  )}
                </div>
              </div>

              {/* DVT card */}
              <div className="card">
                <div className="card-head">
                  <div className="card-title">{lang === "fr" ? "Audit des données (DVT)" : "Data Audit (DVT)"}</div>
                  {latestDvt && (
                    <>
                      <span className="tag-mono" style={{ marginLeft: 8 }}>{latestDvt.cycle}</span>
                      <span className={"pill " + dvtStatus(dvtAggregates.meanAbsVariance)}
                        style={{ marginLeft: 6 }}>
                        {dvtAggregates.measuredCount > 0
                          ? dvtAggregates.meanAbsVariance.toFixed(1) + "%"
                          : "—"}
                      </span>
                    </>
                  )}
                  <button className="btn sm ghost" style={{ marginLeft: "auto" }} onClick={() => setRoute("audit_data")}>
                    {lang === "fr" ? "Détail →" : "Detail →"}
                  </button>
                </div>
                <div className="card-body">
                  {!latestDvt && (
                    <div style={{ textAlign: "center", color: "var(--text-faint)", padding: 30 }}>
                      {lang === "fr" ? "Aucun audit DVT pour ce projet." : "No DVT audit for this project."}
                    </div>
                  )}
                  {latestDvt && (
                    <>
                      <div style={{ marginBottom: 8, fontSize: 11.5, color: "var(--text-muted)" }}>
                        <strong>{lang === "fr" ? "Site :" : "Site:"}</strong>{" "}
                        {latestDvt.sites && latestDvt.sites.code
                          ? latestDvt.sites.code + " — " + latestDvt.sites.name
                          : latestDvt.site_name || "—"}
                      </div>
                      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginBottom: 10 }}>
                        <div>
                          <div className="text-faint" style={{ fontSize: 10, textTransform: "uppercase" }}>
                            {lang === "fr" ? "Indicateurs vérifiés" : "Indicators verified"}
                          </div>
                          <div style={{ fontSize: 18, fontWeight: 600, fontFamily: "Consolas, monospace" }}>
                            {dvtAggregates.measuredCount}
                          </div>
                        </div>
                        <div>
                          <div className="text-faint" style={{ fontSize: 10, textTransform: "uppercase" }}>
                            {lang === "fr" ? "Hors seuil ±5%" : "Off ±5%"}
                          </div>
                          <div style={{ fontSize: 18, fontWeight: 600, fontFamily: "Consolas, monospace", color: dvtAggregates.over5pctCount > 0 ? "#b91c1c" : "#15803d" }}>
                            {dvtAggregates.over5pctCount}
                          </div>
                        </div>
                        <div>
                          <div className="text-faint" style={{ fontSize: 10, textTransform: "uppercase" }}>
                            {lang === "fr" ? "Plan d'action" : "Action plan"}
                          </div>
                          <div style={{ fontSize: 18, fontWeight: 600, fontFamily: "Consolas, monospace" }}>
                            {(latestDvtImprov || []).filter((i) => i.indicator_name || i.problem).length}
                          </div>
                        </div>
                      </div>
                      {/* Top variance indicators */}
                      {dvtEnriched.filter((r) => r.avg_var != null && Math.abs(r.avg_var) > 5).length > 0 && (
                        <>
                          <div className="text-faint" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: 4 }}>
                            {lang === "fr" ? "Indicateurs hors seuil" : "Off-threshold indicators"}
                          </div>
                          <div style={{ display: "flex", flexDirection: "column", gap: 4, maxHeight: 160, overflowY: "auto" }}>
                            {dvtEnriched
                              .filter((r) => r.avg_var != null && Math.abs(r.avg_var) > 5)
                              .sort((a, b) => Math.abs(b.avg_var) - Math.abs(a.avg_var))
                              .map((r) => {
                                const st = dvtStatus(r.avg_var);
                                return (
                                  <div key={r.id} style={{
                                    padding: "5px 8px", borderRadius: 4,
                                    background: AD_COLORS[st].bg, color: AD_COLORS[st].fg,
                                    fontSize: 11, display: "flex", alignItems: "center", gap: 8,
                                  }}>
                                    <span className="tag-mono">#{r.position}</span>
                                    <span style={{ flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                                      {r.indicator_name || (lang === "fr" ? "(sans nom)" : "(unnamed)")}
                                    </span>
                                    <span style={{ fontWeight: 600, fontFamily: "Consolas, monospace" }}>
                                      {(r.avg_var > 0 ? "+" : "") + r.avg_var.toFixed(1) + "%"}
                                    </span>
                                  </div>
                                );
                              })}
                          </div>
                        </>
                      )}
                    </>
                  )}
                </div>
              </div>
            </div>

            {/* Aggregate SAT radar (avg per domain across cycles) + DVT trend */}
            {(satTrend.length >= 2 || dvtTrend.length >= 2) && (
              <>
                <div style={{ height: 14 }} />
                <div className="grid cols-2" style={{ gap: 14 }}>
                  {satTrend.length >= 2 && (
                    <div className="card">
                      <div className="card-head">
                        <div className="card-title">{lang === "fr" ? "Profil moyen SAT — par domaine" : "SAT average profile — per domain"}</div>
                        <span className="pill">{satTrend.length} {lang === "fr" ? "cycles" : "cycles"}</span>
                      </div>
                      <div className="card-body">
                        <SatAggregateRadar domains={domains} trend={satTrend} latestScores={satScores} lang={lang} />
                      </div>
                    </div>
                  )}
                  {dvtTrend.length >= 2 && (
                    <div className="card">
                      <div className="card-head">
                        <div className="card-title">{lang === "fr" ? "Évolution DVT — variance moyenne" : "DVT trend — mean variance"}</div>
                        <span className="pill">{dvtTrend.length} {lang === "fr" ? "audits" : "audits"}</span>
                      </div>
                      <div className="card-body">
                        <DvtTrendChart trend={dvtTrend} lang={lang} />
                      </div>
                    </div>
                  )}
                </div>
              </>
            )}

            {/* Consolidated priority actions */}
            <div style={{ height: 14 }} />
            <div className="card">
              <div className="card-head">
                <div className="card-title">
                  {lang === "fr" ? "Actions prioritaires consolidées" : "Consolidated priority actions"}
                </div>
                <span className="pill">{consolidatedActions.length}</span>
                <span className="text-faint" style={{ marginLeft: "auto", fontSize: 11 }}>
                  {lang === "fr"
                    ? "Recommandations marquées prioritaires (SAT) + plan d'amélioration (DVT)"
                    : "Priority-flagged recos (SAT) + improvement plan (DVT)"}
                </span>
              </div>
              <div className="card-body flush" style={{ maxHeight: 480, overflowY: "auto" }}>
                {consolidatedActions.length === 0 && (
                  <div style={{ padding: 22, textAlign: "center", color: "var(--text-faint)", fontSize: 13 }}>
                    {lang === "fr"
                      ? "Aucune action consolidée. Marquez des recos comme prioritaires dans SAT et/ou complétez le plan DVT."
                      : "No consolidated action. Flag priority recos in SAT and/or fill the DVT plan."}
                  </div>
                )}
                {consolidatedActions.map((a, i) => {
                  const overdue = a.due_date && a.due_date < new Date().toISOString().slice(0, 10);
                  return (
                    <div key={i} style={{
                      padding: "10px 14px", borderBottom: "1px solid var(--line-faint)",
                      display: "grid", gridTemplateColumns: "auto auto 1fr auto auto auto", gap: 10, alignItems: "center",
                    }}>
                      <span className={"pill " + (a.source === "SAT" ? "accent" : "amber")}>{a.source}</span>
                      <span className="tag-mono" style={{ fontSize: 11 }}>{a.ref}</span>
                      <div>
                        <div style={{ fontSize: 12.5 }}>{a.text || "—"}</div>
                        {a.indicator && <div className="text-faint" style={{ fontSize: 10.5, marginTop: 2 }}>{a.indicator}</div>}
                      </div>
                      <span className="text-faint" style={{ fontSize: 11 }}>{a.owner || "—"}</span>
                      <span className={overdue ? "pill red dot" : ""} style={{ fontSize: 11, fontFamily: "Consolas, monospace", color: overdue ? "#b91c1c" : "var(--text-faint)" }}>{a.due_date || "—"}</span>
                      {a.status && <span className={"pill " + (a.status === "done" ? "green" : a.status === "cancelled" ? "" : "amber")}>
                        {a.status === "done" ? (lang === "fr" ? "Fait" : "Done")
                         : a.status === "cancelled" ? (lang === "fr" ? "Annulé" : "Cancelled")
                         : (lang === "fr" ? "En cours" : "Pending")}
                      </span>}
                      {!a.status && <span></span>}
                    </div>
                  );
                })}
              </div>
            </div>

            {/* Audit history */}
            <div style={{ height: 14 }} />
            <div className="grid cols-2" style={{ gap: 14 }}>
              <div className="card">
                <div className="card-head">
                  <div className="card-title">{lang === "fr" ? "Historique SAT" : "SAT history"}</div>
                  <span className="pill">{satEvals.length}</span>
                </div>
                <div className="card-body flush">
                  {satEvals.length === 0 && (
                    <div style={{ padding: 18, textAlign: "center", color: "var(--text-faint)", fontSize: 12 }}>
                      {lang === "fr" ? "Aucun cycle SAT." : "No SAT cycle."}
                    </div>
                  )}
                  {satEvals.map((e) => {
                    const trendEntry = satTrend.find((tt) => tt.id === e.id);
                    const pct = trendEntry ? trendEntry.scores.total.pct : 0;
                    const hasScore = trendEntry && trendEntry.scores.total.max > 0;
                    const st = hasScore ? satStatus(pct) : "neutral";
                    return (
                      <div key={e.id} style={{ padding: "8px 14px", borderBottom: "1px solid var(--line-faint)", display: "flex", alignItems: "center", gap: 8 }}>
                        <span className="tag-mono" style={{ fontWeight: 600 }}>{e.cycle}</span>
                        <span className="text-faint" style={{ fontSize: 11 }}>{e.state}</span>
                        {hasScore && (
                          <span className={"pill " + st} style={{ fontSize: 10.5 }}>
                            {Math.round(pct * 100)}%
                          </span>
                        )}
                        <span className="text-faint" style={{ fontSize: 11, marginLeft: "auto" }}>
                          {e.updated_at ? new Date(e.updated_at).toLocaleDateString(lang === "fr" ? "fr-FR" : "en-US") : "—"}
                        </span>
                      </div>
                    );
                  })}
                </div>
              </div>
              <div className="card">
                <div className="card-head">
                  <div className="card-title">{lang === "fr" ? "Historique DVT" : "DVT history"}</div>
                  <span className="pill">{dvtAudits.length}</span>
                </div>
                <div className="card-body flush">
                  {dvtAudits.length === 0 && (
                    <div style={{ padding: 18, textAlign: "center", color: "var(--text-faint)", fontSize: 12 }}>
                      {lang === "fr" ? "Aucun audit DVT." : "No DVT audit."}
                    </div>
                  )}
                  {dvtAudits.map((a) => {
                    const sn = a.sites && a.sites.code ? (a.sites.code + " — " + a.sites.name) : (a.site_name || "—");
                    const trendEntry = dvtTrend.find((tt) => tt.id === a.id);
                    const hasVar = trendEntry && trendEntry.measuredCount > 0;
                    const st = hasVar ? dvtStatus(trendEntry.meanAbsVariance) : "neutral";
                    return (
                      <div key={a.id} style={{ padding: "8px 14px", borderBottom: "1px solid var(--line-faint)", display: "flex", alignItems: "center", gap: 8 }}>
                        <span className="tag-mono" style={{ fontWeight: 600 }}>{a.cycle}</span>
                        <span className="text-faint" style={{ fontSize: 11, flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{sn}</span>
                        {hasVar && (
                          <span className={"pill " + st} style={{ fontSize: 10.5 }}>
                            {trendEntry.meanAbsVariance.toFixed(1)}%
                          </span>
                        )}
                        <span className="text-faint" style={{ fontSize: 11 }}>
                          {a.updated_at ? new Date(a.updated_at).toLocaleDateString(lang === "fr" ? "fr-FR" : "en-US") : "—"}
                        </span>
                      </div>
                    );
                  })}
                </div>
              </div>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// Compact 8-axis SAT radar (smaller than the one on the audit-system screen)
function AdSatRadar({ domains, scores }) {
  const cx = 90, cy = 90, R = 75;
  const N = (domains || []).length;
  if (N === 0) return null;
  const angle = (i) => (i / N) * Math.PI * 2 - Math.PI / 2;
  const point = (i, r) => [cx + Math.cos(angle(i)) * r, cy + Math.sin(angle(i)) * r];
  const pct = (i) => (scores.perDomain[domains[i].code] || {}).pct || 0;
  const polygon = domains.map((d, i) => point(i, pct(i) * R).join(",")).join(" ");
  return (
    <svg viewBox="0 0 180 180" style={{ width: "100%", maxWidth: 180, height: 180, display: "block" }}>
      {[0.25, 0.5, 0.75, 1].map((r, i) => (
        <polygon key={i} points={domains.map((_, j) => point(j, R * r).join(",")).join(" ")} fill="none" stroke="var(--line-faint)" />
      ))}
      {domains.map((_, i) => <line key={i} x1={cx} y1={cy} x2={point(i, R)[0]} y2={point(i, R)[1]} stroke="var(--line-faint)" />)}
      <polygon points={polygon} fill="var(--accent)" fillOpacity="0.15" stroke="var(--accent)" strokeWidth="1.6" />
      {domains.map((d, i) => {
        const [x, y] = point(i, R + 10);
        return <text key={i} x={x} y={y} fontSize="10" fill="var(--text)" textAnchor="middle" dominantBaseline="middle" fontWeight="600">{d.code}</text>;
      })}
      {domains.map((d, i) => {
        const [x, y] = point(i, pct(i) * R);
        return <circle key={i} cx={x} cy={y} r="2.5" fill="var(--accent)" />;
      })}
    </svg>
  );
}

// SAT aggregate radar — mean % per domain across all cycles, with the
// latest cycle overlaid as an outline so users can spot deltas at a glance.
function SatAggregateRadar({ domains, trend, latestScores, lang }) {
  if (!domains || domains.length === 0) return null;
  // Mean % per domain across all cycles that have data
  const mean = {};
  (domains || []).forEach((d) => {
    const vals = trend
      .map((t) => (t.scores.perDomain[d.code] || {}))
      .filter((sc) => sc.max > 0)
      .map((sc) => sc.pct);
    mean[d.code] = vals.length > 0 ? vals.reduce((s, v) => s + v, 0) / vals.length : 0;
  });
  const latest = {};
  (domains || []).forEach((d) => {
    const sc = (latestScores && latestScores.perDomain && latestScores.perDomain[d.code]) || {};
    latest[d.code] = sc.max > 0 ? sc.pct : 0;
  });

  const cx = 175, cy = 175, R = 130;
  const N = domains.length;
  const angle = (i) => (i / N) * Math.PI * 2 - Math.PI / 2;
  const pointAt = (i, r) => [cx + Math.cos(angle(i)) * r, cy + Math.sin(angle(i)) * r];
  const polyMean   = domains.map((d, i) => pointAt(i, mean[d.code]   * R).join(",")).join(" ");
  const polyLatest = domains.map((d, i) => pointAt(i, latest[d.code] * R).join(",")).join(" ");

  // Per-domain summary table (mean, latest, delta)
  const rows = domains.map((d) => {
    const m = mean[d.code], l = latest[d.code];
    const delta = l - m;
    return { code: d.code, mean: m, latest: l, delta };
  });

  return (
    <div style={{ display: "grid", gridTemplateColumns: "1.1fr 1fr", gap: 14, alignItems: "center" }}>
      <svg viewBox="0 0 350 360" style={{ width: "100%", maxWidth: 350, height: "auto", display: "block" }}>
        {/* Grid rings */}
        {[0.25, 0.5, 0.75, 1].map((r, i) => (
          <polygon key={i} points={domains.map((_, j) => pointAt(j, R * r).join(",")).join(" ")} fill="none" stroke="var(--line-faint)" />
        ))}
        {/* Spokes */}
        {domains.map((_, i) => <line key={i} x1={cx} y1={cy} x2={pointAt(i, R)[0]} y2={pointAt(i, R)[1]} stroke="var(--line-faint)" />)}
        {/* Threshold ring at 70 % */}
        <polygon points={domains.map((_, j) => pointAt(j, R * 0.7).join(",")).join(" ")}
          fill="none" stroke="#15803d" strokeDasharray="3 4" opacity="0.4" />
        {/* Latest cycle — outline only */}
        <polygon points={polyLatest} fill="none" stroke="#dc2626" strokeWidth="1.8" strokeDasharray="4 3" />
        {/* Mean — filled accent */}
        <polygon points={polyMean} fill="var(--accent)" fillOpacity="0.18" stroke="var(--accent)" strokeWidth="2" />
        {/* Vertex dots */}
        {domains.map((d, i) => {
          const [xm, ym] = pointAt(i, mean[d.code] * R);
          return <circle key={"m" + i} cx={xm} cy={ym} r="3" fill="var(--accent)" />;
        })}
        {domains.map((d, i) => {
          const [xl, yl] = pointAt(i, latest[d.code] * R);
          return <circle key={"l" + i} cx={xl} cy={yl} r="2.5" fill="#dc2626" />;
        })}
        {/* Domain labels */}
        {domains.map((d, i) => {
          const [x, y] = pointAt(i, R + 18);
          return <text key={i} x={x} y={y} fontSize="12" fontWeight="700" fill="var(--text)" textAnchor="middle" dominantBaseline="middle">{d.code}</text>;
        })}
        {/* Legend */}
        <g transform="translate(20, 340)">
          <rect x="0" y="0" width="14" height="10" fill="var(--accent)" fillOpacity="0.5" stroke="var(--accent)" />
          <text x="20" y="9" fontSize="10" fill="var(--text-muted)">{lang === "fr" ? "Moyenne historique" : "Historical mean"}</text>
          <line x1="160" y1="5" x2="174" y2="5" stroke="#dc2626" strokeWidth="2" strokeDasharray="4 3" />
          <text x="180" y="9" fontSize="10" fill="var(--text-muted)">{lang === "fr" ? "Dernier cycle" : "Latest cycle"}</text>
        </g>
      </svg>
      {/* Per-domain table: mean | latest | delta */}
      <div style={{ display: "flex", flexDirection: "column", gap: 3, fontSize: 11 }}>
        <div style={{ display: "grid", gridTemplateColumns: "auto 1fr 1fr 1fr", gap: 6, fontWeight: 600, color: "var(--text-faint)", fontSize: 9.5, textTransform: "uppercase", letterSpacing: "0.04em", padding: "0 4px 4px" }}>
          <span></span>
          <span style={{ textAlign: "right" }}>{lang === "fr" ? "Moy." : "Mean"}</span>
          <span style={{ textAlign: "right" }}>{lang === "fr" ? "Dernier" : "Latest"}</span>
          <span style={{ textAlign: "right" }}>Δ</span>
        </div>
        {rows.map((r) => {
          const stMean   = r.mean   >= 0.7 ? "ok" : r.mean   >= 0.6 ? "amber" : "bad";
          const stLatest = r.latest >= 0.7 ? "ok" : r.latest >= 0.6 ? "amber" : "bad";
          const stDelta  = r.delta > 0.02 ? "ok" : r.delta < -0.02 ? "bad" : "neutral";
          return (
            <div key={r.code} style={{
              display: "grid", gridTemplateColumns: "24px 1fr 1fr 1fr", gap: 6,
              alignItems: "center", padding: "4px 4px",
              borderBottom: "1px solid var(--line-faint)",
            }}>
              <span className="tag-mono" style={{ fontWeight: 700 }}>{r.code}</span>
              <span style={{ textAlign: "right", color: AD_COLORS[stMean].fg, fontFamily: "Consolas, monospace", fontWeight: 600 }}>
                {Math.round(r.mean * 100)}%
              </span>
              <span style={{ textAlign: "right", color: AD_COLORS[stLatest].fg, fontFamily: "Consolas, monospace", fontWeight: 600 }}>
                {Math.round(r.latest * 100)}%
              </span>
              <span style={{ textAlign: "right", fontFamily: "Consolas, monospace", color: AD_COLORS[stDelta].fg, fontWeight: 600 }}>
                {r.delta > 0 ? "↗ +" : r.delta < 0 ? "↘ " : "→ "}{Math.abs(r.delta * 100).toFixed(0)}
              </span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// DVT trend chart — mean |variance| across all audits (sorted ascending)
function DvtTrendChart({ trend, lang }) {
  const W = 600, H = 200, padL = 40, padR = 20, padT = 16, padB = 32;
  const valid = trend.filter((t) => t.measuredCount > 0);
  if (valid.length < 2) {
    return <div className="text-faint" style={{ padding: 20, textAlign: "center", fontSize: 12 }}>
      {lang === "fr" ? "Au moins 2 audits renseignés requis." : "At least 2 scored audits required."}
    </div>;
  }
  const maxY = Math.max(20, Math.ceil(Math.max(...valid.map((t) => t.meanAbsVariance)) * 1.2));
  const xs = (i) => padL + (i / (valid.length - 1)) * (W - padL - padR);
  const ys = (v) => padT + (1 - v / maxY) * (H - padT - padB);
  const linePath = valid.map((d, i) => (i === 0 ? "M" : "L") + xs(i) + "," + ys(d.meanAbsVariance)).join(" ");
  // Ticks
  const ticks = [];
  for (let v = 0; v <= maxY; v += Math.max(5, Math.round(maxY / 4))) ticks.push(v);
  return (
    <svg viewBox={`0 0 ${W} ${H}`} style={{ width: "100%" }}>
      {ticks.map((g) => (
        <g key={g}>
          <line x1={padL} y1={ys(g)} x2={W - padR} y2={ys(g)} stroke="var(--line-faint)" strokeDasharray="2 3" />
          <text x={padL - 6} y={ys(g) + 3} textAnchor="end" fontSize="9" fill="var(--text-faint)" fontFamily="var(--font-mono)">{g}%</text>
        </g>
      ))}
      <line x1={padL} y1={ys(5)} x2={W - padR} y2={ys(5)} stroke="#15803d" strokeDasharray="3 4" opacity="0.5" />
      <line x1={padL} y1={ys(10)} x2={W - padR} y2={ys(10)} stroke="#b91c1c" strokeDasharray="3 4" opacity="0.4" />
      <path d={linePath} fill="none" stroke="#dc2626" strokeWidth="2" />
      {valid.map((d, i) => {
        const st = d.meanAbsVariance <= 5 ? "#15803d" : d.meanAbsVariance <= 10 ? "#a16207" : "#b91c1c";
        return (
          <g key={i}>
            <circle cx={xs(i)} cy={ys(d.meanAbsVariance)} r="3.5" fill={st} stroke="white" strokeWidth="1.5" />
            <text x={xs(i)} y={ys(d.meanAbsVariance) - 8} textAnchor="middle" fontSize="9.5" fill="var(--text)" fontWeight="600">{d.meanAbsVariance.toFixed(1)}%</text>
            <text x={xs(i)} y={H - 18} textAnchor="middle" fontSize="9" fill="var(--text-faint)">{d.cycle}</text>
            <text x={xs(i)} y={H - 6} textAnchor="middle" fontSize="8.5" fill="var(--text-faint)" fontFamily="var(--font-mono)">{d.siteLbl.slice(0, 10)}</text>
          </g>
        );
      })}
    </svg>
  );
}

window.AuditDashboard = AuditDashboard;
