// ===== Elejemais — Reusable charts (custom SVG) =====
// Available on window.Charts.{name}

const { useEffect, useRef, useState, useMemo } = React;

function useAnim(target, duration = 900) {
  // Initialize at target so content is never hidden if rAF doesn't progress.
  const [v, setV] = useState(target);
  const startedRef = useRef(false);
  useEffect(() => {
    if (startedRef.current) { setV(target); return; }
    startedRef.current = true;
    setV(0);
    let raf, t0;
    // Safety fallback — guarantees final value even if rAF stalls.
    const fallback = setTimeout(() => setV(target), duration + 200);
    const tick = (t) => {
      if (!t0) t0 = t;
      const p = Math.min(1, (t - t0) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setV(target * eased);
      if (p < 1) raf = requestAnimationFrame(tick);
      else clearTimeout(fallback);
    };
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); clearTimeout(fallback); };
  }, [target]);
  return v;
}

/* ---------- Big stat card ---------- */
function StatCard({ eyebrow, value, delta, deltaLabel, suffix, footer, accent, sparkData }) {
  const animated = useAnim(value);
  const display = Math.round(animated);
  const positive = (delta || 0) >= 0;
  return (
    <div className="card stat-card slideup" style={{ padding: "20px 22px 18px" }}>
      <div className="row" style={{ justifyContent: "space-between" }}>
        <div className="eyebrow">{eyebrow}</div>
        {delta !== undefined && (
          <span className={`badge ${positive ? "badge--accent" : "badge--warm"}`}>
            {positive ? <Icon.ArrowUp size={11} /> : <Icon.ArrowDown size={11} />}
            {Math.abs(delta)}% {deltaLabel || ""}
          </span>
        )}
      </div>
      <div className="row" style={{ alignItems: "baseline", gap: 8, marginTop: 14 }}>
        <div className="fig" style={{ color: accent || "var(--ink)" }}>
          {window.fmt(display)}
        </div>
        {suffix && <div className="serif" style={{ fontSize: 22, color: "var(--muted)" }}>{suffix}</div>}
      </div>
      {sparkData && <Spark data={sparkData} color={accent || "var(--accent)"} />}
      {footer && <div className="dim" style={{ fontSize: 12.5, marginTop: 10 }}>{footer}</div>}
    </div>
  );
}

/* ---------- Sparkline ---------- */
function Spark({ data, color = "var(--accent)", height = 36 }) {
  if (!data || data.length < 2) return null;
  const w = 220, h = height;
  const max = Math.max(...data);
  const min = Math.min(...data);
  const path = data.map((v, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - ((v - min) / (max - min || 1)) * (h - 4) - 2;
    return `${i === 0 ? "M" : "L"}${x},${y}`;
  }).join(" ");
  const area = `${path} L${w},${h} L0,${h} Z`;
  const id = useMemo(() => "sp" + Math.random().toString(36).slice(2, 7), []);
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} style={{ marginTop: 10, display: "block" }}>
      <defs>
        <linearGradient id={id} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.18" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={area} fill={`url(#${id})`} />
      <path d={path} fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" />
    </svg>
  );
}

/* ---------- Progress bar — meta vs realidade ---------- */
function MetaBar({ atual, meta, metaSegura, color = "var(--accent)" }) {
  const pct = atual / metaSegura;
  const animPct = useAnim(pct);
  const metaPos = meta / metaSegura;
  return (
    <div>
      <div className="row" style={{ justifyContent: "space-between", marginBottom: 8 }}>
        <div className="row" style={{ gap: 10 }}>
          <span className="serif" style={{ fontSize: 32, lineHeight: 1, color }}>
            {window.fmt(atual)}
          </span>
          <span className="dim" style={{ fontSize: 13 }}>de {window.fmt(metaSegura)} (meta + 30%)</span>
        </div>
        <span className="badge badge--accent">{Math.round(pct * 100)}%</span>
      </div>
      <div style={{ position: "relative", height: 14, background: "var(--surface-2)", borderRadius: 999, overflow: "visible" }}>
        <div style={{
          width: `${Math.min(1, animPct) * 100}%`,
          height: "100%",
          background: `linear-gradient(90deg, ${color}, ${color})`,
          borderRadius: 999,
          transition: "width 600ms ease"
        }} />
        {/* Meta marker */}
        <div style={{
          position: "absolute",
          left: `${metaPos * 100}%`,
          top: -6,
          bottom: -6,
          width: 2,
          background: "var(--ink)",
          opacity: 0.6,
        }} />
        <div style={{
          position: "absolute",
          left: `calc(${metaPos * 100}% - 32px)`,
          top: -22,
          fontSize: 11,
          color: "var(--muted)",
          background: "var(--surface)",
          padding: "1px 6px",
          border: "1px solid var(--line)",
          borderRadius: 4,
        }}>
          meta {window.fmt(meta)}
        </div>
      </div>
      <div className="row" style={{ marginTop: 18, gap: 24 }}>
        <Legend dot="var(--ink)" label={`Meta legal: ${window.fmt(meta)} votos`} />
        <Legend dot={color} label="Apoiadores cadastrados" />
        <Legend dot="var(--muted-2)" label={`Folga: ${window.fmt(metaSegura - meta)} (+30%)`} />
      </div>
    </div>
  );
}

function Legend({ dot, label }) {
  return (
    <div className="row" style={{ gap: 6, fontSize: 12, color: "var(--muted)" }}>
      <span style={{ width: 8, height: 8, borderRadius: 4, background: dot, display: "inline-block" }} />
      {label}
    </div>
  );
}

/* ---------- Line chart (growth) ---------- */
function LineChart({ data, keys, colors, height = 220 }) {
  if (!data || data.length < 2) return null;
  const w = 700, h = height, padL = 36, padB = 26, padT = 12, padR = 12;
  const xs = data.length;
  const allValues = data.flatMap(d => keys.map(k => d[k]));
  const max = Math.max(...allValues);
  const yScale = (v) => padT + (h - padT - padB) * (1 - v / max);
  const xScale = (i) => padL + (i / (xs - 1)) * (w - padL - padR);
  const grid = [0, 0.25, 0.5, 0.75, 1].map(p => Math.round(max * p));
  const anim = useAnim(1, 1200);

  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} style={{ display: "block" }}>
      {grid.map((g, i) => {
        const y = yScale(g);
        return (
          <g key={i}>
            <line x1={padL} x2={w - padR} y1={y} y2={y} stroke="var(--line)" strokeDasharray="2 4" />
            <text x={padL - 8} y={y + 4} fontSize="10" textAnchor="end" fill="var(--muted)">
              {g >= 1000 ? `${(g / 1000).toFixed(1)}k` : g}
            </text>
          </g>
        );
      })}
      {data.map((d, i) => (
        <text key={i} x={xScale(i)} y={h - 6} fontSize="10.5" textAnchor="middle" fill="var(--muted)">{d.mes}</text>
      ))}
      {keys.map((k, ki) => {
        const color = colors[ki];
        const path = data.map((d, i) =>
          `${i === 0 ? "M" : "L"}${xScale(i)},${yScale(d[k])}`
        ).join(" ");
        const area = `${path} L${xScale(xs - 1)},${h - padB} L${xScale(0)},${h - padB} Z`;
        const gid = `lg${ki}`;
        const len = 2000;
        return (
          <g key={k}>
            <defs>
              <linearGradient id={gid} x1="0" x2="0" y1="0" y2="1">
                <stop offset="0%" stopColor={color} stopOpacity={ki === 0 ? 0.18 : 0.08} />
                <stop offset="100%" stopColor={color} stopOpacity="0" />
              </linearGradient>
            </defs>
            <path d={area} fill={`url(#${gid})`} />
            <path d={path} fill="none" stroke={color} strokeWidth="2"
              strokeDasharray={len}
              strokeDashoffset={len * (1 - anim)}
            />
            {data.map((d, i) => (
              <circle key={i} cx={xScale(i)} cy={yScale(d[k])} r="3" fill="var(--surface)" stroke={color} strokeWidth="1.6" />
            ))}
          </g>
        );
      })}
    </svg>
  );
}

/* ---------- Horizontal bar ranking ---------- */
function RankBars({ data, total, valueKey = "apoio", labelKey = "nome" }) {
  const max = Math.max(...data.map(d => d[valueKey]));
  return (
    <div className="col" style={{ gap: 10 }}>
      {data.map((d, i) => {
        const pct = d[valueKey] / max;
        return (
          <div key={i}>
            <div className="row" style={{ justifyContent: "space-between", marginBottom: 4, fontSize: 12.5 }}>
              <span style={{ fontWeight: 500 }}>
                <span className="dim mono" style={{ marginRight: 8 }}>{String(i + 1).padStart(2, "0")}</span>
                {d[labelKey]}
              </span>
              <span className="dim mono">{window.fmt(d[valueKey])}</span>
            </div>
            <div style={{ height: 6, background: "var(--surface-2)", borderRadius: 999, overflow: "hidden" }}>
              <div style={{
                width: `${pct * 100}%`,
                height: "100%",
                background: d.cor || "var(--accent)",
                transition: "width 700ms cubic-bezier(.2,.7,.2,1)",
              }} />
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ---------- Donut for distribution ---------- */
function Donut({ data, size = 180, label = "Total" }) {
  const total = data.reduce((s, d) => s + d.value, 0);
  let acc = 0;
  const r = size / 2 - 14;
  const cx = size / 2, cy = size / 2;
  const anim = useAnim(1, 900);
  return (
    <div className="row" style={{ gap: 22, alignItems: "center" }}>
      <svg viewBox={`0 0 ${size} ${size}`} width={size} height={size}>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--line)" strokeWidth="14" />
        {data.map((d, i) => {
          const frac = (d.value / total) * anim;
          const len = 2 * Math.PI * r;
          const offset = -acc * len;
          acc += d.value / total;
          return (
            <circle
              key={i}
              cx={cx} cy={cy} r={r}
              fill="none"
              stroke={d.color}
              strokeWidth="14"
              strokeDasharray={`${frac * len} ${len}`}
              strokeDashoffset={offset}
              transform={`rotate(-90 ${cx} ${cy})`}
              strokeLinecap="butt"
            />
          );
        })}
        <text x={cx} y={cy - 4} textAnchor="middle" fontSize="11" fill="var(--muted)">{label}</text>
        <text x={cx} y={cy + 18} textAnchor="middle" fontSize="24" fontFamily="var(--display)" fill="var(--ink)">
          {window.fmt(total)}
        </text>
      </svg>
      <div className="col" style={{ gap: 8, flex: 1 }}>
        {data.map((d, i) => (
          <div key={i} className="row" style={{ justifyContent: "space-between", fontSize: 12.5 }}>
            <span className="row" style={{ gap: 8 }}>
              <span style={{ width: 9, height: 9, borderRadius: 2, background: d.color }} />
              {d.label}
            </span>
            <span className="mono dim">{Math.round((d.value / total) * 100)}%</span>
          </div>
        ))}
      </div>
    </div>
  );
}

window.Charts = { StatCard, Spark, MetaBar, LineChart, RankBars, Donut };
