/* ELEV8 ATS - lightweight, dependency-free chart primitives (SVG + CSS).
   Themed with the product --ui tokens. Exposed as window.E8Charts.
   Sparkline · AreaTrend · Donut · FunnelBars · BarRow · Heatmap */

let E8_CID = 0;
const cid = (p) => p + '_' + (++E8_CID);

/* ---------- Sparkline: tiny area+line trend for metric cards ---------- */
function Sparkline({ data, w = 84, h = 26, tone = 'up', pad = 3 }) {
  if (!data || data.length < 2) return null;
  const max = Math.max.apply(null, data), min = Math.min.apply(null, data);
  const rng = (max - min) || 1;
  const pts = data.map((v, i) => [pad + (i / (data.length - 1)) * (w - pad * 2), h - pad - ((v - min) / rng) * (h - pad * 2)]);
  const line = pts.map((p, i) => (i ? 'L' : 'M') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' ');
  const area = line + ' L ' + (w - pad) + ' ' + h + ' L ' + pad + ' ' + h + ' Z';
  const color = tone === 'down' ? 'var(--ui-danger)' : tone === 'flat' ? 'var(--ui-text-tertiary)' : 'var(--ui-success)';
  const g = cid('spk');
  const last = pts[pts.length - 1];
  return (
    <svg viewBox={'0 0 ' + w + ' ' + h} width={w} height={h} preserveAspectRatio="none" style={{ display: 'block', overflow: 'visible' }}>
      <defs>
        <linearGradient id={g} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" style={{ stopColor: color }} stopOpacity="0.20" />
          <stop offset="100%" style={{ stopColor: color }} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={area} style={{ fill: 'url(#' + g + ')' }} />
      <path d={line} style={{ fill: 'none', stroke: color }} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={last[0]} cy={last[1]} r="2" style={{ fill: color }} />
    </svg>
  );
}

/* Catmull-Rom -> cubic bezier: a smooth line through the points (premium feel vs straight segments). */
function smoothLine(pts) {
  if (pts.length < 3) return pts.map((p, i) => (i ? 'L' : 'M') + p.x.toFixed(1) + ' ' + p.y.toFixed(1)).join(' ');
  let d = 'M ' + pts[0].x.toFixed(1) + ' ' + pts[0].y.toFixed(1);
  for (let i = 0; i < pts.length - 1; i++) {
    const p0 = pts[i - 1] || pts[i], p1 = pts[i], p2 = pts[i + 1], p3 = pts[i + 2] || p2;
    const c1x = p1.x + (p2.x - p0.x) / 6, c1y = p1.y + (p2.y - p0.y) / 6;
    const c2x = p2.x - (p3.x - p1.x) / 6, c2y = p2.y - (p3.y - p1.y) / 6;
    d += ' C ' + c1x.toFixed(1) + ' ' + c1y.toFixed(1) + ' ' + c2x.toFixed(1) + ' ' + c2y.toFixed(1) + ' ' + p2.x.toFixed(1) + ' ' + p2.y.toFixed(1);
  }
  return d;
}

/* ---------- AreaTrend: a full-width gradient trend chart. Labels + value render as crisp HTML overlays
   (the SVG stretches with preserveAspectRatio=none, which would distort/clip in-SVG text). ---------- */
function AreaTrend({ series, labels, color = 'var(--ui-accent)', height = 150, suffix = '', showValue = true }) {
  const w = 640, pad = { t: 10, r: 8, b: labels ? 18 : 8, l: 8 };
  const max = Math.max.apply(null, series), min = Math.min.apply(null, series);
  const rng = (max - min) || 1;
  const innerW = w - pad.l - pad.r, innerH = height - pad.t - pad.b;
  const x = (i) => pad.l + (i / (series.length - 1)) * innerW;
  const y = (v) => pad.t + innerH - ((v - min) / rng) * innerH;
  const pts = series.map((v, i) => ({ x: x(i), y: y(v) }));
  const line = smoothLine(pts);
  const area = line + ' L ' + x(series.length - 1).toFixed(1) + ' ' + (pad.t + innerH).toFixed(1) + ' L ' + pad.l.toFixed(1) + ' ' + (pad.t + innerH).toFixed(1) + ' Z';
  const g = cid('area');
  const lastI = series.length - 1;
  const dotLeft = (x(lastI) / w) * 100, dotTop = (y(series[lastI]) / height) * 100;
  return (
    <div className="e8-areatrend" style={{ position: 'relative', width: '100%', height: height }}>
      <svg viewBox={'0 0 ' + w + ' ' + height} width="100%" height={height} preserveAspectRatio="none" style={{ display: 'block' }} role="img" aria-label={'Trend chart, latest value ' + series[lastI] + suffix}>
        <defs>
          <linearGradient id={g} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" style={{ stopColor: color }} stopOpacity="0.20" />
            <stop offset="100%" style={{ stopColor: color }} stopOpacity="0.02" />
          </linearGradient>
        </defs>
        <line x1={pad.l} y1={pad.t + innerH} x2={w - pad.r} y2={pad.t + innerH} style={{ stroke: 'var(--ui-border)' }} strokeWidth="1" vectorEffect="non-scaling-stroke" />
        <path d={area} style={{ fill: 'url(#' + g + ')' }} />
        <path d={line} style={{ fill: 'none', stroke: color }} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" vectorEffect="non-scaling-stroke" />
      </svg>
      <span className="e8-areatrend-dot" style={{ left: dotLeft + '%', top: dotTop + '%', '--dotc': color }} />
      {showValue ? <span className="e8-areatrend-val">{series[lastI] + suffix}</span> : null}
      {labels ? (
        <div className="e8-areatrend-x">
          {labels.map((l, i) => <span key={i} className="e8-areatrend-xl">{(i % 2 === 0 || i === labels.length - 1) ? l : ''}</span>)}
        </div>
      ) : null}
    </div>
  );
}

/* ---------- Donut: a single-value ring with a center label ---------- */
function Donut({ value, centerLabel, caption, color = 'var(--ui-accent)', size = 132 }) {
  const sw = 12, r = (size - sw) / 2 - 1, c = 2 * Math.PI * r, off = c * (1 - Math.max(0, Math.min(1, value)));
  const cxy = size / 2;
  return (
    <span style={{ display: 'inline-flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
      <span style={{ position: 'relative', width: size, height: size }}>
        <svg width={size} height={size} style={{ display: 'block' }} role="img" aria-label={(caption || 'Value') + ' ' + centerLabel}>
          <circle cx={cxy} cy={cxy} r={r} style={{ fill: 'none', stroke: 'var(--ui-fill)' }} strokeWidth={sw} />
          <circle cx={cxy} cy={cxy} r={r} style={{ fill: 'none', stroke: color, strokeDasharray: c, strokeDashoffset: off, transition: 'stroke-dashoffset 500ms ease-out' }} strokeWidth={sw} strokeLinecap="round" transform={'rotate(-90 ' + cxy + ' ' + cxy + ')'} />
        </svg>
        <span style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
          <span className="tnum" style={{ fontSize: 'var(--ui-text-3xl)', fontWeight: 600, lineHeight: 1 }}>{centerLabel}</span>
        </span>
      </span>
      {caption ? <span style={{ fontSize: 'var(--ui-text-xs)', color: 'var(--ui-text-tertiary)' }}>{caption}</span> : null}
    </span>
  );
}

/* ---------- FunnelBars: stage funnel with conversion ---------- */
function FunnelBars({ stages, color = 'var(--ui-daybreak)', onStage }) {
  const max = Math.max.apply(null, stages.map((s) => s[1])) || 1;
  const aria = 'Pipeline funnel: ' + stages.map((s) => s[0] + ' ' + s[1]).join(', ');
  const grid = { display: 'grid', gridTemplateColumns: '94px 1fr 92px', gap: 12, alignItems: 'center' };
  return (
    <div style={{ display: 'grid', gap: 7 }} role="img" aria-label={aria}>
      {stages.map(([label, n], i) => {
        const prev = i > 0 ? stages[i - 1][1] : null;
        const conv = prev ? Math.round((n / prev) * 100) : null;
        const inner = (
          <React.Fragment>
            <span style={{ fontSize: 'var(--ui-text-sm)', color: 'var(--ui-text-secondary)', textAlign: 'left' }}>{label}</span>
            <span style={{ height: 22, background: 'var(--ui-fill)', borderRadius: 5, overflow: 'hidden', display: 'flex' }}>
              <span style={{ width: Math.max((n / max) * 100, 3) + '%', background: color, borderRadius: 5, transition: 'width 400ms ease-out' }}></span>
            </span>
            <span className="tnum" style={{ fontSize: 'var(--ui-text-sm)', color: 'var(--ui-text-secondary)', textAlign: 'right' }}>
              {n.toLocaleString()}{conv !== null ? <span style={{ color: 'var(--ui-text-tertiary)' }}> · {conv}%</span> : null}
            </span>
          </React.Fragment>
        );
        return onStage
          ? <button key={label} type="button" onClick={() => onStage(label, i)} title={'View ' + label} style={{ ...grid, border: 0, background: 'none', padding: 2, margin: '0 -2px', cursor: 'pointer', font: 'inherit', borderRadius: 6 }}>{inner}</button>
          : <div key={label} style={grid}>{inner}</div>;
      })}
    </div>
  );
}

/* ---------- BarRow: horizontal bars (sources, leaderboard) ---------- */
function BarRow({ rows, color = 'var(--ui-accent)', renderLabel, max, onRow }) {
  const top = max || Math.max.apply(null, rows.map((r) => r[1])) || 1;
  const aria = rows.map((r) => r[0] + ' ' + r[1]).join(', ');
  const grid = { display: 'grid', gridTemplateColumns: '130px 1fr 36px', gap: 10, alignItems: 'center' };
  return (
    <div style={{ display: 'grid', gap: 8 }} role="img" aria-label={aria}>
      {rows.map(([label, n], i) => {
        const inner = (
          <React.Fragment>
            <span style={{ fontSize: 'var(--ui-text-sm)', color: 'var(--ui-text-secondary)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', textAlign: 'left' }}>{renderLabel ? renderLabel(label, i) : label}</span>
            <span style={{ height: 18, background: 'var(--ui-fill)', borderRadius: 5, overflow: 'hidden', display: 'flex' }}>
              <span style={{ width: Math.max((n / top) * 100, 3) + '%', background: typeof color === 'function' ? color(i) : color, borderRadius: 5, transition: 'width 400ms ease-out' }}></span>
            </span>
            <span className="tnum" style={{ fontSize: 'var(--ui-text-sm)', fontWeight: 500, textAlign: 'right' }}>{n}</span>
          </React.Fragment>
        );
        return onRow
          ? <button key={i} type="button" onClick={() => onRow(label, i)} style={{ ...grid, border: 0, background: 'none', padding: 2, margin: '0 -2px', cursor: 'pointer', font: 'inherit', borderRadius: 6 }}>{inner}</button>
          : <div key={i} style={grid}>{inner}</div>;
      })}
    </div>
  );
}

/* ---------- Heatmap: activity grid (rows × days) ---------- */
function Heatmap({ rows, days }) {
  const max = Math.max.apply(null, rows.flatMap((r) => r.cells)) || 1;
  const shade = (n) => n === 0 ? 'var(--ui-fill)' : null;
  return (
    <div className="e8-heatmap" style={{ gridTemplateColumns: '120px repeat(' + days.length + ', 1fr)' }}>
      <span></span>
      {days.map((d, i) => <span key={i} className="e8-heat-day">{d}</span>)}
      {rows.map((r) => (
        <React.Fragment key={r.who}>
          <span className="e8-heat-label">
            {r.ai ? <span className="material-symbols-outlined" style={{ fontSize: 13, color: 'var(--ui-daybreak-text)' }}>smart_toy</span> : null}
            {r.who}
          </span>
          {r.cells.map((n, i) => {
            const t = n / max;
            const bg = n === 0 ? 'var(--ui-fill)' : 'color-mix(in srgb, var(--ui-accent) ' + Math.round(18 + t * 72) + '%, white)';
            return <span key={i} className="e8-heat-cell" title={r.who + ' · ' + n + ' touches'} style={{ background: bg, color: t > 0.55 ? 'var(--ui-accent-text)' : 'var(--ui-text-tertiary)' }}>{n || ''}</span>;
          })}
        </React.Fragment>
      ))}
    </div>
  );
}

window.E8Charts = { Sparkline, AreaTrend, Donut, FunnelBars, BarRow, Heatmap };
