// Shared chart primitives — kept generic so each dashboard can re-skin them.
// All accept a `stroke`, `fill`, etc. so the visual language stays per-direction.

// Pass an explicit `domain: [lo, hi]` to plot on a fixed scale (e.g. [0, 1] for
// a percentage) instead of auto-scaling to the data's own min/max — auto-scale
// makes a steady series look like it's sitting on the floor.
function Spark({ data, w = 80, h = 22, stroke = 'currentColor', fill = 'none', strokeWidth = 1.25, showDots = false, domain = null }) {
  if (!data || data.length === 0) return null;
  const min = domain ? domain[0] : Math.min(...data);
  const max = domain ? domain[1] : Math.max(...data);
  const span = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * (w - 2) + 1;
    const y = h - 1 - ((v - min) / span) * (h - 2);
    return [x, y];
  });
  const d = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(2)} ${y.toFixed(2)}`).join(' ');
  const area = `${d} L${(w - 1).toFixed(2)} ${h - 1} L1 ${h - 1} Z`;
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} style={{ overflow: 'visible' }}>
      {fill !== 'none' && <path d={area} fill={fill} />}
      <path d={d} fill="none" stroke={stroke} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" />
      {showDots && pts.map(([x, y], i) => (
        <circle key={i} cx={x} cy={y} r={i === pts.length - 1 ? 2.4 : 1.2} fill={stroke} />
      ))}
    </svg>
  );
}

function Bars({ data, w = 80, h = 22, fill = 'currentColor', gap = 2 }) {
  if (!data || data.length === 0) return null;
  const max = Math.max(...data) || 1;
  const bw = (w - gap * (data.length - 1)) / data.length;
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      {data.map((v, i) => {
        const bh = (v / max) * h;
        return <rect key={i} x={i * (bw + gap)} y={h - bh} width={bw} height={bh} fill={fill} />;
      })}
    </svg>
  );
}

// Concentric ring — used by Garden + Atlas focus modes.
function Ring({ pct = 0, size = 56, stroke = 6, color = 'currentColor', track = 'rgba(0,0,0,0.08)', children }) {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const dash = c * Math.max(0, Math.min(1, pct));
  return (
    <div style={{ position: 'relative', width: size, height: size, display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
      <svg width={size} height={size} style={{ position: 'absolute', inset: 0, transform: 'rotate(-90deg)' }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={track} strokeWidth={stroke} />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={color} strokeWidth={stroke} strokeLinecap="round"
          strokeDasharray={`${dash} ${c}`} />
      </svg>
      <div style={{ position: 'relative', fontVariantNumeric: 'tabular-nums' }}>{children}</div>
    </div>
  );
}

// Horizontal progress — minimal, no labels.
function ProgBar({ pct = 0, h = 4, color = 'currentColor', track = 'rgba(0,0,0,0.08)', radius = 999 }) {
  return (
    <div style={{ width: '100%', height: h, background: track, borderRadius: radius, overflow: 'hidden' }}>
      <div style={{ width: `${Math.max(0, Math.min(1, pct)) * 100}%`, height: '100%', background: color, borderRadius: radius }} />
    </div>
  );
}

// Heatmap row — last N days, shaded by value 0..1
function Heatrow({ data, cell = 14, gap = 3, radius = 3, color = 'currentColor', track = 'rgba(0,0,0,0.06)' }) {
  return (
    <div style={{ display: 'flex', gap }}>
      {data.map((v, i) => (
        <div key={i} style={{
          width: cell, height: cell, borderRadius: radius,
          background: track,
          position: 'relative',
        }}>
          <div style={{
            position: 'absolute', inset: 0, borderRadius: radius,
            background: color,
            opacity: Math.max(0.05, Math.min(1, v)),
          }} />
        </div>
      ))}
    </div>
  );
}

// Quiet date formatting
function fmtDate(d) {
  const opts = { weekday: 'long', month: 'long', day: 'numeric' };
  return d.toLocaleDateString('en-US', opts);
}
function fmtTime(d) {
  return d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' }).toLowerCase();
}

Object.assign(window, { Spark, Bars, Ring, ProgBar, Heatrow, fmtDate, fmtTime });
