/* ============================================================
   charts.jsx — gráficos SVG livianos (barras, donut, sparkline)
   ============================================================ */

/* ---- barras agrupadas: ingresos vs gastos por mes ---- */
function GroupedBars({ data, onHover }) {
  const W = 620, H = 250, padL = 8, padR = 8, padT = 16, padB = 26;
  const max = Math.max(...data.flatMap(d => [d.ingreso, d.gasto])) * 1.12;
  const innerW = W - padL - padR;
  const innerH = H - padT - padB;
  const groupW = innerW / data.length;
  const barW = Math.min(26, groupW * 0.3);
  const gap = 6;
  const y = v => padT + innerH - (v / max) * innerH;
  const gridLines = 4;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: 'block' }} preserveAspectRatio="xMidYMid meet">
      {Array.from({ length: gridLines + 1 }).map((_, i) => {
        const gy = padT + (innerH / gridLines) * i;
        const val = max * (1 - i / gridLines);
        return (
          <g key={i}>
            <line x1={padL} x2={W - padR} y1={gy} y2={gy} stroke="var(--border-soft)" strokeWidth="1" />
            <text x={padL + 2} y={gy - 4} fill="var(--text-4)" fontSize="9.5" fontFamily="var(--mono)">{fmtCompact(val)}</text>
          </g>
        );
      })}
      {data.map((d, i) => {
        const cx = padL + groupW * i + groupW / 2;
        const x1 = cx - barW - gap / 2;
        const x2 = cx + gap / 2;
        return (
          <g key={i}>
            <rect x={x1} y={y(d.ingreso)} width={barW} height={padT + innerH - y(d.ingreso)} rx="2.5"
              fill="var(--pos)" opacity="0.92"
              style={{ cursor: 'pointer' }}
              onMouseEnter={e => onHover(e, { signal: null, reason: `${d.m} · Ingreso: ${fmtARS(d.ingreso)}` })}
              onMouseMove={e => onHover(e, { signal: null, reason: `${d.m} · Ingreso: ${fmtARS(d.ingreso)}` })}
              onMouseLeave={() => onHover(null)} />
            <rect x={x2} y={y(d.gasto)} width={barW} height={padT + innerH - y(d.gasto)} rx="2.5"
              fill="var(--neg)" opacity="0.82"
              style={{ cursor: 'pointer' }}
              onMouseEnter={e => onHover(e, { signal: null, reason: `${d.m} · Gasto: ${fmtARS(d.gasto)}` })}
              onMouseMove={e => onHover(e, { signal: null, reason: `${d.m} · Gasto: ${fmtARS(d.gasto)}` })}
              onMouseLeave={() => onHover(null)} />
            <text x={cx} y={H - 8} fill="var(--text-3)" fontSize="11" textAnchor="middle" fontFamily="var(--sans)">{d.m}</text>
          </g>
        );
      })}
    </svg>
  );
}

/* ---- mini barras (gasto últimos N meses) ---- */
function MiniBars({ data, valueKey = 'gasto', accent = 'var(--neg)' }) {
  const max = Math.max(...data.map(d => d[valueKey]));
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', gap: 14, height: 110, padding: '4px 2px' }}>
      {data.map((d, i) => {
        const h = (d[valueKey] / max) * 100;
        const last = i === data.length - 1;
        return (
          <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>
            <div className="num" style={{ fontSize: 11, color: last ? 'var(--text)' : 'var(--text-3)', fontWeight: 600 }}>
              {fmtCompact(d[valueKey])}
            </div>
            <div style={{
              width: '100%', maxWidth: 46, height: `${h}%`, minHeight: 6,
              background: last ? accent : 'color-mix(in oklab, ' + accent + ' 38%, var(--surface-3))',
              borderRadius: '3px 3px 0 0', transition: 'height .4s cubic-bezier(.3,1,.4,1)'
            }} />
            <div style={{ fontSize: 11, color: 'var(--text-3)' }}>{d.m}</div>
          </div>
        );
      })}
    </div>
  );
}

/* ---- donut categorías ---- */
function Donut({ data, size = 168, thickness = 22, centerLabel, centerValue }) {
  const total = data.reduce((s, d) => s + d.amount, 0);
  const r = (size - thickness) / 2;
  const cx = size / 2, cy = size / 2;
  const circ = 2 * Math.PI * r;
  let offset = 0;
  return (
    <svg viewBox={`0 0 ${size} ${size}`} width={size} height={size}>
      <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--bg-2)" strokeWidth={thickness} />
      {data.map((d, i) => {
        const frac = d.amount / total;
        const len = frac * circ;
        const el = (
          <circle key={i} cx={cx} cy={cy} r={r} fill="none"
            stroke={d.color} strokeWidth={thickness}
            strokeDasharray={`${len} ${circ - len}`}
            strokeDashoffset={-offset}
            transform={`rotate(-90 ${cx} ${cy})`}
            style={{ transition: 'stroke-dasharray .5s' }} />
        );
        offset += len;
        return el;
      })}
      <text x={cx} y={cy - 4} textAnchor="middle" fill="var(--text-3)" fontSize="10.5" fontFamily="var(--sans)" style={{ textTransform: 'uppercase', letterSpacing: '0.08em' }}>{centerLabel}</text>
      <text x={cx} y={cy + 16} textAnchor="middle" fill="var(--text)" fontSize="17" fontFamily="var(--mono)" fontWeight="600">{centerValue}</text>
    </svg>
  );
}

/* ---- sparkline ---- */
function Sparkline({ points, color = 'var(--pos)', width = 90, height = 30 }) {
  const max = Math.max(...points), min = Math.min(...points);
  const range = max - min || 1;
  const step = width / (points.length - 1);
  const d = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${(i * step).toFixed(1)},${(height - ((p - min) / range) * height).toFixed(1)}`).join(' ');
  const last = points[points.length - 1];
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{ display: 'block' }}>
      <path d={d} fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={width} cy={height - ((last - min) / range) * height} r="2.2" fill={color} />
    </svg>
  );
}

Object.assign(window, { GroupedBars, MiniBars, Donut, Sparkline });
