// -----------------------------------------------------------------------------
// Auto-Ka — Agrégateur de voitures usagées à vendre (province de Québec)
// Auteur : Simon-Pierre Boucher — contact@spboucher.ai
// Charts.tsx : graphiques SVG maison — histogramme, barres horizontales, donut.
//   Marques fines, bouts arrondis, étiquettes directes sélectives, infobulle
//   au survol, vue tableau repliable (accessibilité). Palette catégorielle
//   validée (contraste + daltonisme) : #d94f1e #1f6fb5 #1c7a4d #b58500
//   #7d4fc9 #a05a2c.
// -----------------------------------------------------------------------------
import { ReactNode, useState } from "react";

export const CAT_COLORS = ["#d94f1e", "#1f6fb5", "#1c7a4d", "#b58500", "#7d4fc9", "#a05a2c"];

export interface Datum {
  label: string;
  n: number;
  extra?: string;
}

const fmt = (n: number) => Math.round(n).toLocaleString("fr-CA");

function DataTable({ rows, valueLabel }: { rows: Datum[]; valueLabel: string }) {
  return (
    <details className="chart-data">
      <summary>Voir les données</summary>
      <table>
        <thead>
          <tr><th>Catégorie</th><th>{valueLabel}</th></tr>
        </thead>
        <tbody>
          {rows.map((r) => (
            <tr key={r.label}>
              <td>{r.label}</td>
              <td>{fmt(r.n)}{r.extra ? ` · ${r.extra}` : ""}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </details>
  );
}

function Tip({ x, y, children }: { x: number; y: number; children: ReactNode }) {
  return (
    <div className="chart-tip" style={{ left: x, top: y }}>
      {children}
    </div>
  );
}

/** Histogramme vertical — magnitude d'une distribution, une seule teinte. */
export function VBars({ data, color = "#d94f1e", valueLabel = "véhicules", height = 190 }:
  { data: Datum[]; color?: string; valueLabel?: string; height?: number }) {
  const [tip, setTip] = useState<{ x: number; y: number; d: Datum } | null>(null);
  if (!data.length) return null;
  const max = Math.max(...data.map((d) => d.n), 1);
  const W = 720, PAD = 6, LBL = 28;
  const bw = (W - PAD * (data.length - 1)) / data.length;
  const plotH = height - LBL - 18;
  return (
    <div className="chart-wrap" onMouseLeave={() => setTip(null)}>
      <svg viewBox={`0 0 ${W} ${height}`} className="chart vbars" role="img"
           aria-label={`Histogramme : ${valueLabel} par classe`}>
        {data.map((d, i) => {
          const h = Math.max(3, (d.n / max) * plotH);
          const x = i * (bw + PAD);
          const y = 18 + (plotH - h);
          const show = d.n === max || i === 0 || i === data.length - 1;
          return (
            <g key={d.label}>
              <rect
                x={x} y={y} width={bw} height={h} rx={4} fill={color}
                className="mark"
                onMouseEnter={(e) => {
                  const r = (e.currentTarget.closest(".chart-wrap") as HTMLElement).getBoundingClientRect();
                  setTip({ x: e.clientX - r.left, y: e.clientY - r.top - 10, d });
                }}
              />
              {show && (
                <text x={x + bw / 2} y={y - 5} textAnchor="middle" className="c-val">
                  {fmt(d.n)}
                </text>
              )}
              <text x={x + bw / 2} y={height - 4} textAnchor="middle" className="c-lbl">
                {d.label}
              </text>
            </g>
          );
        })}
      </svg>
      {tip && <Tip x={tip.x} y={tip.y}><b>{tip.d.label}</b> — {fmt(tip.d.n)} {valueLabel}{tip.d.extra ? ` · ${tip.d.extra}` : ""}</Tip>}
      <DataTable rows={data} valueLabel={valueLabel} />
    </div>
  );
}

/** Barres horizontales — classement d'une même mesure, une seule teinte. */
export function HBars({ data, color = "#d94f1e", valueLabel = "véhicules" }:
  { data: Datum[]; color?: string; valueLabel?: string }) {
  const [tip, setTip] = useState<{ x: number; y: number; d: Datum } | null>(null);
  if (!data.length) return null;
  const max = Math.max(...data.map((d) => d.n), 1);
  const W = 720, ROW = 26, LBL = 150;
  const H = data.length * ROW;
  return (
    <div className="chart-wrap" onMouseLeave={() => setTip(null)}>
      <svg viewBox={`0 0 ${W} ${H}`} className="chart hbars" role="img"
           aria-label={`Barres : ${valueLabel} par catégorie`}>
        {data.map((d, i) => {
          const w = Math.max(4, (d.n / max) * (W - LBL - 120));
          const y = i * ROW + 4;
          return (
            <g key={d.label}>
              <text x={LBL - 8} y={y + 13} textAnchor="end" className="c-cat">
                {d.label.length > 22 ? d.label.slice(0, 21) + "…" : d.label}
              </text>
              <rect
                x={LBL} y={y} width={w} height={ROW - 10} rx={4} fill={color}
                className="mark"
                onMouseEnter={(e) => {
                  const r = (e.currentTarget.closest(".chart-wrap") as HTMLElement).getBoundingClientRect();
                  setTip({ x: e.clientX - r.left, y: e.clientY - r.top - 10, d });
                }}
              />
              <text x={LBL + w + 7} y={y + 12} className="c-val">
                {fmt(d.n)}{d.extra ? `  ·  ${d.extra}` : ""}
              </text>
            </g>
          );
        })}
      </svg>
      {tip && <Tip x={tip.x} y={tip.y}><b>{tip.d.label}</b> — {fmt(tip.d.n)} {valueLabel}{tip.d.extra ? ` · ${tip.d.extra}` : ""}</Tip>}
      <DataTable rows={data} valueLabel={valueLabel} />
    </div>
  );
}

/** Donut — parts d'un tout (≤ 6 catégories + « Autres »), palette validée. */
export function Donut({ data, valueLabel = "véhicules" }:
  { data: Datum[]; valueLabel?: string }) {
  const [tip, setTip] = useState<{ x: number; y: number; d: Datum; pct: number } | null>(null);
  if (!data.length) return null;
  const top = data.slice(0, 5);
  const rest = data.slice(5).reduce((s, d) => s + d.n, 0);
  const parts: Datum[] = rest > 0 ? [...top, { label: "Autres", n: rest }] : top;
  const total = parts.reduce((s, d) => s + d.n, 0) || 1;
  const R = 80, r = 46, CX = 110, CY = 100;
  let angle = -Math.PI / 2;
  const arcs = parts.map((d, i) => {
    const span = (d.n / total) * Math.PI * 2;
    const a0 = angle, a1 = angle + span;
    angle = a1;
    const large = span > Math.PI ? 1 : 0;
    const p = (a: number, rad: number) =>
      `${CX + rad * Math.cos(a)},${CY + rad * Math.sin(a)}`;
    return {
      d,
      pct: (d.n / total) * 100,
      color: CAT_COLORS[i % CAT_COLORS.length],
      path: `M ${p(a0, R)} A ${R} ${R} 0 ${large} 1 ${p(a1, R)} L ${p(a1, r)} A ${r} ${r} 0 ${large} 0 ${p(a0, r)} Z`,
    };
  });
  return (
    <div className="chart-wrap donut-wrap" onMouseLeave={() => setTip(null)}>
      <svg viewBox="0 0 220 200" className="chart donut" role="img"
           aria-label={`Répartition : ${valueLabel} par catégorie`}>
        {arcs.map((a) => (
          <path
            key={a.d.label} d={a.path} fill={a.color} stroke="var(--surface)"
            strokeWidth={2} className="mark"
            onMouseEnter={(e) => {
              const rr = (e.currentTarget.closest(".chart-wrap") as HTMLElement).getBoundingClientRect();
              setTip({ x: e.clientX - rr.left, y: e.clientY - rr.top - 10, d: a.d, pct: a.pct });
            }}
          />
        ))}
        <text x={CX} y={CY - 2} textAnchor="middle" className="donut-total">{fmt(total)}</text>
        <text x={CX} y={CY + 14} textAnchor="middle" className="c-lbl">{valueLabel}</text>
      </svg>
      <div className="donut-legend">
        {arcs.map((a) => (
          <div key={a.d.label} className="dl-row">
            <span className="dl-swatch" style={{ background: a.color }} />
            <span className="dl-name">{a.d.label}</span>
            <span className="dl-val">{a.pct.toFixed(1)} %</span>
          </div>
        ))}
      </div>
      {tip && <Tip x={tip.x} y={tip.y}><b>{tip.d.label}</b> — {fmt(tip.d.n)} {valueLabel} ({tip.pct.toFixed(1)} %)</Tip>}
      <DataTable rows={parts} valueLabel={valueLabel} />
    </div>
  );
}
