// WEBWORKS — shared visual atoms used across all three directions.
// Pure presentational; consume tokens from ww.css. Exported to window.

const TONE = {
  ok:   { fg: 'var(--ok-fg)',   solid: 'var(--ok-solid)',   bg: 'var(--ok-bg)',   border: 'var(--ok-border)' },
  warn: { fg: 'var(--warn-fg)', solid: 'var(--warn-solid)', bg: 'var(--warn-bg)', border: 'var(--warn-border)' },
  risk: { fg: 'var(--risk-fg)', solid: 'var(--risk-solid)', bg: 'var(--risk-bg)', border: 'var(--risk-border)' },
  info: { fg: 'var(--info-fg)', solid: 'var(--info-solid)', bg: 'var(--info-bg)', border: 'var(--info-border)' },
  neutral: { fg: 'var(--text-3)', solid: 'var(--text-4)', bg: 'var(--surface-3)', border: 'var(--border)' },
};

// ── Status pill (dot + label) ────────────────────────────────────
function Pill({ tone = 'neutral', children, dot = true, style }) {
  return (
    <span className={`ww-pill ${tone}`} style={style}>
      {dot && <span className="dot" />}{children}
    </span>
  );
}

function Tag({ children, style }) { return <span className="ww-tag" style={style}>{children}</span>; }

// ── Eyebrow + heading row ────────────────────────────────────────
function Eyebrow({ children, style }) { return <div className="ww-eyebrow" style={style}>{children}</div>; }

function SectionHead({ eyebrow, title, right, style }) {
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, marginBottom: 16, ...style }}>
      <div>
        {eyebrow && <Eyebrow style={{ marginBottom: 6 }}>{eyebrow}</Eyebrow>}
        <div className="ww-h" style={{ fontSize: 21, lineHeight: 1.1 }}>{title}</div>
      </div>
      {right}
    </div>
  );
}

// ── Progress track ───────────────────────────────────────────────
function Track({ value, tone = 'info', height = 6 }) {
  const t = TONE[tone] || TONE.info;
  return (
    <div className="ww-track" style={{ height }}>
      <span style={{ width: `${Math.max(value, value > 0 ? 3 : 0)}%`, background: t.solid }} />
    </div>
  );
}

// ── Donut ring (single value, 0–100) ─────────────────────────────
function Ring({ value, size = 96, stroke = 9, tone = 'ok', label, sub }) {
  const t = TONE[tone] || TONE.ok;
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const off = c * (1 - Math.max(0, Math.min(1, value / 100)));
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--surface-3)" strokeWidth={stroke} />
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={t.solid} strokeWidth={stroke}
          strokeLinecap="round" strokeDasharray={c} strokeDashoffset={off}
          style={{ transition: 'stroke-dashoffset .6s cubic-bezier(.2,.7,.3,1)' }} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        <div className="ww-h ww-tnum" style={{ fontSize: size * 0.27, lineHeight: 1 }}>{label}</div>
        {sub && <div style={{ fontSize: 10, color: 'var(--text-3)', fontFamily: 'var(--font-mono)', marginTop: 2, letterSpacing: '.04em' }}>{sub}</div>}
      </div>
    </div>
  );
}

// ── Segmented status donut (counts by tone) ──────────────────────
function SegRing({ segments, size = 120, stroke = 14, centerTop, centerBot }) {
  const total = segments.reduce((s, x) => s + x.value, 0) || 1;
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  let acc = 0;
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--surface-3)" strokeWidth={stroke} />
        {segments.map((seg, i) => {
          const frac = seg.value / total;
          const dash = `${c * frac} ${c * (1 - frac)}`;
          const off = -c * acc;
          acc += frac;
          return <circle key={i} cx={size/2} cy={size/2} r={r} fill="none"
            stroke={(TONE[seg.tone] || TONE.neutral).solid} strokeWidth={stroke}
            strokeDasharray={dash} strokeDashoffset={off} />;
        })}
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        <div className="ww-h ww-tnum" style={{ fontSize: size * 0.28, lineHeight: 1 }}>{centerTop}</div>
        {centerBot && <div style={{ fontSize: 10, color: 'var(--text-3)', fontFamily: 'var(--font-mono)', letterSpacing: '.06em', textTransform: 'uppercase', marginTop: 2 }}>{centerBot}</div>}
      </div>
    </div>
  );
}

// ── Sparkline (area + line) with last-point dot ──────────────────
function Sparkline({ data, width = 220, height = 56, tone = 'info', showDots = false }) {
  const t = TONE[tone] || TONE.info;
  const vals = data.map(d => (typeof d === 'number' ? d : d.v));
  const max = Math.max(...vals, 1);
  const n = vals.length;
  const pad = 4;
  const x = (i) => pad + (i * (width - pad * 2)) / (n - 1);
  const y = (v) => height - pad - (v / max) * (height - pad * 2);
  const line = vals.map((v, i) => `${i ? 'L' : 'M'}${x(i).toFixed(1)},${y(v).toFixed(1)}`).join(' ');
  const area = `${line} L${x(n-1).toFixed(1)},${height} L${x(0).toFixed(1)},${height} Z`;
  const gid = 'sg' + Math.random().toString(36).slice(2, 8);
  return (
    <svg width={width} height={height} style={{ display: 'block', overflow: 'visible' }}>
      <defs>
        <linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={t.solid} stopOpacity="0.22" />
          <stop offset="100%" stopColor={t.solid} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={area} fill={`url(#${gid})`} />
      <path d={line} fill="none" stroke={t.solid} strokeWidth="2" strokeLinejoin="round" strokeLinecap="round" />
      {showDots && vals.map((v, i) => (
        <circle key={i} cx={x(i)} cy={y(v)} r={i === n - 1 ? 3.5 : 2}
          fill={i === n - 1 ? t.solid : 'var(--surface)'} stroke={t.solid} strokeWidth="1.5" />
      ))}
    </svg>
  );
}

// ── Mini column chart (labeled) ──────────────────────────────────
function Columns({ data, width = 240, height = 90, tone = 'info' }) {
  const t = TONE[tone] || TONE.info;
  const max = Math.max(...data.map(d => d.v), 1);
  const gap = 6;
  const bw = (width - gap * (data.length - 1)) / data.length;
  return (
    <svg width={width} height={height} style={{ display: 'block', overflow: 'visible' }}>
      {data.map((d, i) => {
        const h = Math.max((d.v / max) * (height - 18), d.v > 0 ? 3 : 1.5);
        const xx = i * (bw + gap);
        const last = i === data.length - 1;
        return (
          <g key={i}>
            <rect x={xx} y={height - 18 - h} width={bw} height={h} rx="3"
              fill={d.v === 0 ? 'var(--surface-3)' : t.solid} opacity={last ? 1 : 0.55} />
            <text x={xx + bw / 2} y={height - 5} textAnchor="middle"
              fontSize="9" fontFamily="var(--font-mono)" fill="var(--text-4)">{d.d.slice(3)}</text>
          </g>
        );
      })}
    </svg>
  );
}

// ── Horizontal range bar (for spend ranges on a shared scale) ────
function RangeBar({ lo, hi, scaleMax, tone = 'info', height = 8 }) {
  const t = TONE[tone] || TONE.info;
  const L = (lo / scaleMax) * 100;
  const W = Math.max(((hi - lo) / scaleMax) * 100, 1.5);
  return (
    <div style={{ position: 'relative', height, borderRadius: 999, background: 'var(--surface-3)' }}>
      <div style={{ position: 'absolute', left: `${L}%`, width: `${W}%`, top: 0, bottom: 0,
        borderRadius: 999, background: t.solid, opacity: 0.85 }} />
    </div>
  );
}

// ── KPI stat block ───────────────────────────────────────────────
function Stat({ value, label, sub, tone }) {
  const t = tone ? (TONE[tone] || TONE.neutral) : null;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <div className="ww-h ww-tnum" style={{ fontSize: 34, lineHeight: 1, color: t ? t.fg : 'var(--text)', letterSpacing: '-0.02em' }}>
        {value}{sub && <span style={{ fontSize: 14, color: 'var(--text-3)', marginLeft: 4, letterSpacing: 0 }}>{sub}</span>}
      </div>
      <div style={{ fontSize: 11, color: 'var(--text-3)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '.07em' }}>{label}</div>
    </div>
  );
}

// ── Icons (stroke, inherit currentColor) ─────────────────────────
const Icon = {
  bolt:  (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M13 2 4 14h7l-1 8 9-12h-7z"/></svg>,
  check: (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6 9 17l-5-5"/></svg>,
  alert: (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 9v4m0 4h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/></svg>,
  clock: (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>,
  coins: (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><ellipse cx="12" cy="6" rx="8" ry="3"/><path d="M4 6v6c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></svg>,
  radar: (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M19.07 4.93A10 10 0 1 0 21 11M12 12l6-6"/><circle cx="12" cy="12" r="1.5"/></svg>,
  arrow: (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  sun:   (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1.5 1.5M17.5 17.5 19 19M19 5l-1.5 1.5M6.5 17.5 5 19"/></svg>,
  moon:  (p) => <svg viewBox="0 0 24 24" width={p.s||16} height={p.s||16} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>,
};

Object.assign(window, { TONE, Pill, Tag, Eyebrow, SectionHead, Track, Ring, SegRing, Sparkline, Columns, RangeBar, Stat, Icon });
