/* ============================================================================
   FSC charts — primitivos SVG responsivos, sem libs. window.FSCCharts.*
   ============================================================================ */
const { useRef, useState, useLayoutEffect, useEffect, useCallback } = React;

const PALETTE = ['var(--cat-1)', 'var(--cat-2)', 'var(--cat-3)', 'var(--cat-4)', 'var(--cat-5)', 'var(--cat-6)', 'var(--cat-7)', 'var(--cat-8)'];
const INK = 'var(--ink-900)';
const GRID = 'var(--line)';
const MUTED = 'var(--ink-500)';

// medir largura do container (responsivo)
function useMeasure() {
  const ref = useRef(null);
  const [w, setW] = useState(640);
  useLayoutEffect(() => {
    if (!ref.current) return;
    const ro = new ResizeObserver((entries) => {
      const cw = entries[0].contentRect.width;
      if (cw > 0) setW(cw);
    });
    ro.observe(ref.current);
    return () => ro.disconnect();
  }, []);
  return [ref, w];
}

function niceMax(v) {
  if (v <= 0) return 1;
  const pow = Math.pow(10, Math.floor(Math.log10(v)));
  const n = v / pow;
  const step = n <= 1 ? 1 : n <= 2 ? 2 : n <= 5 ? 5 : 10;
  return step * pow;
}

function Tooltip({ x, y, children, w }) {
  const left = Math.min(Math.max(x, 4), w - 4);
  const flip = x > w * 0.62;
  return (
    <div style={{
      position: 'absolute', left, top: y, transform: `translate(${flip ? '-100%' : '0'}, -50%)`,
      marginLeft: flip ? -10 : 10, pointerEvents: 'none', zIndex: 5,
      background: 'var(--ink-900)', color: 'var(--text-on-dark)', borderRadius: 'var(--radius-md)',
      padding: '8px 10px', font: '500 12px/1.45 var(--font-sans)', boxShadow: 'var(--shadow-lg)',
      whiteSpace: 'nowrap',
    }}>{children}</div>
  );
}

/* ---------------- LineChart (1..n séries) ---------------- */
function LineChart({ series, labels, height = 240, yFormat = (v) => v, area = false, valueLabel }) {
  const [ref, W] = useMeasure();
  const [hover, setHover] = useState(null);
  const padL = 54, padR = 12, padT = 14, padB = 26;
  const innerW = Math.max(10, W - padL - padR);
  const innerH = height - padT - padB;
  const n = labels.length;
  const allVals = series.flatMap((s) => s.values);
  const rawMax = Math.max(1, ...allVals);
  const rawMin = Math.min(0, ...allVals);
  const top = niceMax(rawMax);
  const bot = rawMin < 0 ? -niceMax(-rawMin) : 0;
  const X = (i) => padL + (n <= 1 ? innerW / 2 : (i / (n - 1)) * innerW);
  const Y = (v) => padT + innerH - ((v - bot) / (top - bot)) * innerH;
  const ticks = 4;
  const gridVals = Array.from({ length: ticks + 1 }, (_, i) => bot + ((top - bot) * i) / ticks);

  const linePath = (vals) => vals.map((v, i) => `${i === 0 ? 'M' : 'L'}${X(i)},${Y(v)}`).join(' ');
  const areaPath = (vals) => `${linePath(vals)} L${X(n - 1)},${Y(bot)} L${X(0)},${Y(bot)} Z`;

  const labelEvery = Math.ceil(n / Math.max(1, Math.floor(innerW / 64)));

  const onMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const px = e.clientX - rect.left;
    let i = Math.round(((px - padL) / innerW) * (n - 1));
    i = Math.max(0, Math.min(n - 1, i));
    setHover(i);
  };

  return (
    <div ref={ref} style={{ position: 'relative', width: '100%' }}>
      <svg width={W} height={height} onMouseMove={onMove} onMouseLeave={() => setHover(null)} style={{ display: 'block' }}>
        {gridVals.map((g, i) => (
          <g key={i}>
            <line x1={padL} x2={W - padR} y1={Y(g)} y2={Y(g)} stroke={GRID} strokeWidth="1" />
            <text x={padL - 8} y={Y(g) + 3.5} textAnchor="end" fontSize="10.5" fill={MUTED} fontFamily="var(--font-mono)">{yFormat(g)}</text>
          </g>
        ))}
        {area && series.map((s, si) => (
          <path key={'a' + si} d={areaPath(s.values)} fill={s.color} opacity="0.08" />
        ))}
        {series.map((s, si) => (
          <path key={si} d={linePath(s.values)} fill="none" stroke={s.color} strokeWidth="2.25" strokeLinejoin="round" strokeLinecap="round" />
        ))}
        {hover != null && <line x1={X(hover)} x2={X(hover)} y1={padT} y2={padT + innerH} stroke="var(--ink-300)" strokeWidth="1" strokeDasharray="3 3" />}
        {hover != null && series.map((s, si) => (
          <circle key={'h' + si} cx={X(hover)} cy={Y(s.values[hover])} r="3.5" fill="var(--surface)" stroke={s.color} strokeWidth="2" />
        ))}
        {labels.map((lb, i) => {
          const reg = i % labelEvery === 0 && (n - 1 - i) >= labelEvery * 0.55;
          if (!(reg || i === n - 1)) return null;
          return <text key={i} x={X(i)} y={height - 8} textAnchor="middle" fontSize="10.5" fill={MUTED} fontFamily="var(--font-sans)">{lb}</text>;
        })}
      </svg>
      {hover != null && (
        <Tooltip x={X(hover)} y={padT + 8} w={W}>
          <div style={{ fontWeight: 600, marginBottom: 4 }}>{labels[hover]}</div>
          {series.map((s, si) => (
            <div key={si} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ width: 8, height: 8, borderRadius: 2, background: s.color, display: 'inline-block' }} />
              <span style={{ opacity: 0.8 }}>{s.name}</span>
              <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)' }}>{yFormat(s.values[hover])}</span>
            </div>
          ))}
        </Tooltip>
      )}
    </div>
  );
}

/* ---------------- BarsChart (séries empilháveis ou simples) ---------------- */
function BarsChart({ labels, series, height = 240, yFormat = (v) => v, stacked = false }) {
  const [ref, W] = useMeasure();
  const [hover, setHover] = useState(null);
  const padL = 54, padR = 12, padT = 14, padB = 26;
  const innerW = Math.max(10, W - padL - padR);
  const innerH = height - padT - padB;
  const n = labels.length;
  const colW = innerW / n;
  const totals = labels.map((_, i) => stacked ? series.reduce((s, ser) => s + ser.values[i], 0) : Math.max(...series.map((ser) => ser.values[i])));
  const top = niceMax(Math.max(1, ...totals));
  const Y = (v) => padT + innerH - (v / top) * innerH;
  const ticks = 4;
  const gridVals = Array.from({ length: ticks + 1 }, (_, i) => (top * i) / ticks);
  const groupW = colW * 0.62;
  const subW = stacked ? groupW : groupW / series.length;
  const labelEvery = Math.ceil(n / Math.max(1, Math.floor(innerW / 56)));

  return (
    <div ref={ref} style={{ position: 'relative', width: '100%' }}>
      <svg width={W} height={height} style={{ display: 'block' }}>
        {gridVals.map((g, i) => (
          <g key={i}>
            <line x1={padL} x2={W - padR} y1={Y(g)} y2={Y(g)} stroke={GRID} strokeWidth="1" />
            <text x={padL - 8} y={Y(g) + 3.5} textAnchor="end" fontSize="10.5" fill={MUTED} fontFamily="var(--font-mono)">{yFormat(g)}</text>
          </g>
        ))}
        {labels.map((lb, i) => {
          const cx = padL + colW * i + colW / 2;
          let stackBase = 0;
          return (
            <g key={i} onMouseEnter={() => setHover(i)} onMouseLeave={() => setHover(null)}>
              <rect x={padL + colW * i} y={padT} width={colW} height={innerH} fill={hover === i ? 'var(--sand-50)' : 'transparent'} />
              {series.map((ser, si) => {
                const v = ser.values[i];
                if (stacked) {
                  const y = Y(stackBase + v); const h = Y(stackBase) - Y(stackBase + v); stackBase += v;
                  return <rect key={si} x={cx - subW / 2} y={y} width={subW} height={Math.max(0, h)} fill={ser.color} rx="2" />;
                }
                const x = cx - groupW / 2 + si * subW;
                return <rect key={si} x={x} y={Y(v)} width={subW * 0.86} height={Math.max(0, padT + innerH - Y(v))} fill={ser.color} rx="2" />;
              })}
              {(i % labelEvery === 0 && (n - 1 - i) >= labelEvery * 0.55) || i === n - 1 ? (
                <text x={cx} y={height - 8} textAnchor="middle" fontSize="10.5" fill={MUTED} fontFamily="var(--font-sans)">{lb}</text>
              ) : null}
            </g>
          );
        })}
      </svg>
      {hover != null && (
        <Tooltip x={padL + colW * hover + colW / 2} y={padT + 8} w={W}>
          <div style={{ fontWeight: 600, marginBottom: 4 }}>{labels[hover]}</div>
          {series.map((s, si) => (
            <div key={si} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ width: 8, height: 8, borderRadius: 2, background: s.color, display: 'inline-block' }} />
              <span style={{ opacity: 0.8 }}>{s.name}</span>
              <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)' }}>{yFormat(s.values[hover])}</span>
            </div>
          ))}
        </Tooltip>
      )}
    </div>
  );
}

/* ---------------- Donut ---------------- */
function Donut({ data, size = 200, thickness = 26, centerTop, centerBottom, onSlice }) {
  const [hover, setHover] = useState(null);
  const total = data.reduce((s, d) => s + d.value, 0) || 1;
  const r = size / 2 - thickness / 2 - 2;
  const cx = size / 2, cy = size / 2;
  let a0 = -Math.PI / 2;
  const arcs = data.map((d, i) => {
    const frac = d.value / total;
    const a1 = a0 + frac * Math.PI * 2;
    const large = a1 - a0 > Math.PI ? 1 : 0;
    const x0 = cx + r * Math.cos(a0), y0 = cy + r * Math.sin(a0);
    const x1 = cx + r * Math.cos(a1), y1 = cy + r * Math.sin(a1);
    const path = `M${x0},${y0} A${r},${r} 0 ${large} 1 ${x1},${y1}`;
    const seg = { path, color: d.color || PALETTE[i % PALETTE.length], d, i };
    a0 = a1;
    return seg;
  });
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      <svg width={size} height={size}>
        {arcs.map((s) => (
          <path key={s.i} d={s.path} fill="none" stroke={s.color} strokeWidth={hover === s.i ? thickness + 5 : thickness}
            strokeLinecap="butt" opacity={hover == null || hover === s.i ? 1 : 0.4}
            style={{ cursor: onSlice ? 'pointer' : 'default', transition: 'stroke-width .15s, opacity .15s' }}
            onMouseEnter={() => setHover(s.i)} onMouseLeave={() => setHover(null)}
            onClick={() => onSlice && onSlice(s.d)} />
        ))}
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', pointerEvents: 'none' }}>
        {hover != null ? (
          <>
            <span style={{ fontSize: 11, color: 'var(--text-muted)', maxWidth: size - thickness * 2, fontWeight: 500 }}>{arcs[hover].d.label}</span>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 16, fontWeight: 600, color: 'var(--text-primary)' }}>{Math.round(arcs[hover].d.value / total * 100)}%</span>
          </>
        ) : (
          <>
            <span style={{ fontSize: 11, color: 'var(--text-muted)', fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase' }}>{centerTop}</span>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 17, fontWeight: 600, color: 'var(--text-primary)' }}>{centerBottom}</span>
          </>
        )}
      </div>
    </div>
  );
}

/* ---------------- HBars (ranking horizontal) ---------------- */
function HBars({ data, valueFormat = (v) => v, max, onRow }) {
  const m = max || Math.max(1, ...data.map((d) => d.value));
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {data.map((d, i) => (
        <div key={i} onClick={() => onRow && onRow(d)} style={{ cursor: onRow ? 'pointer' : 'default' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4, fontSize: 13 }}>
            <span style={{ color: 'var(--text-secondary)', fontWeight: 500 }}>{d.label}</span>
            <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 600, color: 'var(--text-primary)' }}>{valueFormat(d.value)}</span>
          </div>
          <div style={{ height: 8, background: 'var(--sand-50)', borderRadius: 999, overflow: 'hidden' }}>
            <div style={{ width: `${(d.value / m) * 100}%`, height: '100%', background: d.color || PALETTE[i % PALETTE.length], borderRadius: 999, transition: 'width .4s var(--ease-out)' }} />
          </div>
        </div>
      ))}
    </div>
  );
}

/* ---------------- Heatmap ---------------- */
function Heatmap({ rows, cols, matrix, valueFormat = (v) => v, colFormat = (c) => c }) {
  const [hover, setHover] = useState(null);
  const flat = matrix.flat();
  const max = Math.max(1, ...flat);
  const colShow = Math.ceil(cols.length / Math.max(1, Math.floor(cols.length / 14 + 1)));
  const colorFor = (v) => {
    if (v <= 0) return 'var(--sand-50)';
    const t = Math.pow(v / max, 0.7);
    return `color-mix(in oklab, var(--clay-600) ${Math.round(t * 100)}%, var(--sand-50))`;
  };
  return (
    <div style={{ position: 'relative', overflowX: 'auto' }}>
      <div style={{ display: 'grid', gridTemplateColumns: `minmax(120px, 1.4fr) repeat(${cols.length}, minmax(20px, 1fr))`, gap: 3, minWidth: 520 }}>
        <div />
        {cols.map((c, i) => (
          <div key={i} style={{ fontSize: 9.5, color: 'var(--text-muted)', textAlign: 'center', fontFamily: 'var(--font-mono)', whiteSpace: 'nowrap' }}>
            {i % colShow === 0 ? colFormat(c) : ''}
          </div>
        ))}
        {rows.map((rlabel, ri) => (
          <React.Fragment key={ri}>
            <div style={{ fontSize: 12, color: 'var(--text-secondary)', display: 'flex', alignItems: 'center', paddingRight: 6, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{rlabel}</div>
            {cols.map((c, ci) => (
              <div key={ci} title={`${rlabel} · ${colFormat(c)}: ${valueFormat(matrix[ri][ci])}`}
                onMouseEnter={() => setHover({ ri, ci })} onMouseLeave={() => setHover(null)}
                style={{ aspectRatio: '1', borderRadius: 3, background: colorFor(matrix[ri][ci]), minHeight: 18, outline: hover && hover.ri === ri && hover.ci === ci ? '1.5px solid var(--ink-900)' : 'none' }} />
            ))}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

/* ---------------- Legend ---------------- */
function Legend({ items, columns }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: columns ? `repeat(${columns}, auto)` : 'repeat(auto-fit, minmax(80px, max-content))', gap: '6px 16px' }}>
      {items.map((it, i) => (
        <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 12.5, color: 'var(--text-secondary)' }}>
          <span style={{ width: 10, height: 10, borderRadius: 3, background: it.color, flexShrink: 0 }} />
          <span style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.label}</span>
          {it.value != null && <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontWeight: 600, color: 'var(--text-primary)' }}>{it.value}</span>}
        </div>
      ))}
    </div>
  );
}

/* ---------------- Sparkline ---------------- */
function Sparkline({ values, width = 80, height = 26, color = INK }) {
  const max = Math.max(...values), min = Math.min(...values);
  const range = max - min || 1;
  const pts = values.map((v, i) => `${(i / (values.length - 1)) * width},${height - ((v - min) / range) * height}`).join(' ');
  return (
    <svg width={width} height={height} style={{ display: 'block' }}>
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.6" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
}

window.FSCCharts = { LineChart, BarsChart, Donut, HBars, Heatmap, Legend, Sparkline, PALETTE, useMeasure };
