// Dependency-free SVG charts (§6.2): a line chart for time series and a
// horizontal bar chart for grouped totals. ~150 lines, no library.
const NS = 'http://www.w3.org/2000/svg';

function el(name, attrs, parent) {
  const node = document.createElementNS(NS, name);
  Object.entries(attrs || {}).forEach(([k, v]) => node.setAttribute(k, v));
  if (parent) parent.appendChild(node);
  return node;
}

const fmt = (v) => (Math.abs(v) >= 1000 ? (v / 1000).toFixed(1) + 'k' : String(Math.round(v * 100) / 100));

// lineChart(host, points) — points: [{label: string, value: number}]
export function lineChart(host, points, opts = {}) {
  host.replaceChildren();
  const W = opts.width || host.clientWidth || 560;
  const H = opts.height || 220;
  const pad = { l: 48, r: 12, t: 12, b: 28 };
  const svg = el('svg', { viewBox: `0 0 ${W} ${H}`, width: '100%', role: 'img',
    'aria-label': opts.label || 'line chart' }, host);
  if (!points.length) {
    const t = el('text', { x: W / 2, y: H / 2, 'text-anchor': 'middle', fill: 'var(--muted)' }, svg);
    t.textContent = 'No data in this period';
    return;
  }
  const max = Math.max(...points.map((p) => p.value), 1);
  const x = (i) => pad.l + (i * (W - pad.l - pad.r)) / Math.max(points.length - 1, 1);
  const y = (v) => H - pad.b - (v / max) * (H - pad.t - pad.b);

  // gridlines + y labels
  for (let g = 0; g <= 4; g++) {
    const v = (max * g) / 4;
    el('line', { x1: pad.l, x2: W - pad.r, y1: y(v), y2: y(v),
      stroke: 'var(--border)', 'stroke-width': 1 }, svg);
    const t = el('text', { x: pad.l - 6, y: y(v) + 4, 'text-anchor': 'end',
      'font-size': 11, fill: 'var(--muted)' }, svg);
    t.textContent = fmt(v);
  }
  // x labels (sparse)
  const step = Math.ceil(points.length / 8);
  points.forEach((p, i) => {
    if (i % step !== 0 && i !== points.length - 1) return;
    const t = el('text', { x: x(i), y: H - 8, 'text-anchor': 'middle',
      'font-size': 11, fill: 'var(--muted)' }, svg);
    t.textContent = p.label;
  });

  const d = points.map((p, i) => `${i ? 'L' : 'M'}${x(i).toFixed(1)},${y(p.value).toFixed(1)}`).join(' ');
  // area fill
  el('path', {
    d: `${d} L${x(points.length - 1)},${y(0)} L${x(0)},${y(0)} Z`,
    fill: 'var(--accent)', opacity: 0.15,
  }, svg);
  el('path', { d, fill: 'none', stroke: 'var(--accent)', 'stroke-width': 2 }, svg);
  points.forEach((p, i) => {
    const c = el('circle', { cx: x(i), cy: y(p.value), r: 3, fill: 'var(--accent)' }, svg);
    const title = el('title', {}, c);
    title.textContent = `${p.label}: ${p.value}`;
  });
}

// barChart(host, rows) — rows: [{label, value}], horizontal bars
export function barChart(host, rows, opts = {}) {
  host.replaceChildren();
  const W = opts.width || host.clientWidth || 560;
  const rowH = 26;
  const pad = { l: 140, r: 48, t: 6, b: 6 };
  const H = pad.t + pad.b + Math.max(rows.length, 1) * rowH;
  const svg = el('svg', { viewBox: `0 0 ${W} ${H}`, width: '100%', role: 'img',
    'aria-label': opts.label || 'bar chart' }, host);
  if (!rows.length) {
    const t = el('text', { x: W / 2, y: H / 2 + 4, 'text-anchor': 'middle', fill: 'var(--muted)' }, svg);
    t.textContent = 'No data in this period';
    return;
  }
  const max = Math.max(...rows.map((r) => r.value), 1);
  rows.forEach((r, i) => {
    const yPos = pad.t + i * rowH;
    const label = el('text', { x: pad.l - 8, y: yPos + rowH / 2 + 4,
      'text-anchor': 'end', 'font-size': 12, fill: 'var(--text)' }, svg);
    label.textContent = r.label.length > 18 ? r.label.slice(0, 17) + '…' : r.label;
    const wBar = ((W - pad.l - pad.r) * r.value) / max;
    const rect = el('rect', { x: pad.l, y: yPos + 4, width: Math.max(wBar, 2),
      height: rowH - 8, fill: 'var(--accent)', rx: 2 }, svg);
    const title = el('title', {}, rect);
    title.textContent = `${r.label}: ${r.value}`;
    const val = el('text', { x: pad.l + Math.max(wBar, 2) + 6, y: yPos + rowH / 2 + 4,
      'font-size': 12, fill: 'var(--muted)' }, svg);
    val.textContent = fmt(r.value);
  });
}
