// Modern chart primitives — Apple/shadcn flavor
// Smooth area charts, gradient fills, hairline axes, dotted grid

const CH = window.TLB_TOKENS.color;

// Catmull-Rom → cubic Bezier path
function smoothPath(points) {
  if (points.length < 2) return '';
  const d = [`M ${points[0][0]} ${points[0][1]}`];
  for (let i = 0; i < points.length - 1; i++) {
    const p0 = points[i - 1] || points[i];
    const p1 = points[i];
    const p2 = points[i + 1];
    const p3 = points[i + 2] || p2;
    const t = 0.18;
    const c1x = p1[0] + (p2[0] - p0[0]) * t;
    const c1y = p1[1] + (p2[1] - p0[1]) * t;
    const c2x = p2[0] - (p3[0] - p1[0]) * t;
    const c2y = p2[1] - (p3[1] - p1[1]) * t;
    d.push(`C ${c1x} ${c1y} ${c2x} ${c2y} ${p2[0]} ${p2[1]}`);
  }
  return d.join(' ');
}

// AreaChart — single or stacked series, gradient fill, dotted grid
function AreaChart({
  data,            // [{label, ...keys}]
  keys = ['value'],
  height = 220,
  yTicks = 4,
  showAxis = true,
  formatY = (v) => v,
  formatX = (l) => l,
  highlightIdx = null,
  uniqueId,
}) {
  const id = React.useMemo(() => uniqueId || `ch${Math.random().toString(36).slice(2, 8)}`, [uniqueId]);
  const w = 800;
  const h = height;
  const padL = showAxis ? 44 : 8;
  const padR = 12;
  const padT = 16;
  const padB = showAxis ? 28 : 8;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;

  const allVals = data.flatMap(d => keys.map(k => d[k] || 0));
  const maxV = Math.max(...allVals) * 1.08;
  const minV = 0;
  const xStep = innerW / Math.max(1, data.length - 1);
  const xy = (i, v) => [padL + i * xStep, padT + innerH - ((v - minV) / (maxV - minV || 1)) * innerH];

  const ticks = Array.from({ length: yTicks + 1 }, (_, i) => minV + (maxV - minV) * (i / yTicks));

  return (
    <div style={{ width: '100%' }}>
      <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ width: '100%', height, display: 'block' }}>
        <defs>
          {keys.map((k, ki) => (
            <linearGradient key={k} id={`${id}-g${ki}`} x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%" stopColor={CH.ink} stopOpacity={ki === 0 ? 0.22 : 0.12} />
              <stop offset="100%" stopColor={CH.ink} stopOpacity="0" />
            </linearGradient>
          ))}
        </defs>

        {/* horizontal grid — dotted */}
        {ticks.map((t, i) => {
          const y = padT + innerH - ((t - minV) / (maxV - minV || 1)) * innerH;
          return (
            <g key={i}>
              <line x1={padL} x2={w - padR} y1={y} y2={y} stroke={CH.border} strokeWidth="1" strokeDasharray="2 4" />
              {showAxis && <text x={padL - 8} y={y + 3} textAnchor="end" style={{ fontFamily: F_TLB.ui, fontSize: 10, fill: CH.muted, fontWeight: 500 }}>{formatY(Math.round(t))}</text>}
            </g>
          );
        })}

        {/* area + line per key */}
        {keys.map((k, ki) => {
          const pts = data.map((d, i) => xy(i, d[k] || 0));
          const linePath = smoothPath(pts);
          const baseline = padT + innerH;
          const areaPath = `${linePath} L ${pts[pts.length-1][0]} ${baseline} L ${pts[0][0]} ${baseline} Z`;
          return (
            <g key={k}>
              <path d={areaPath} fill={`url(#${id}-g${ki})`} />
              <path d={linePath} fill="none" stroke={ki === 0 ? CH.ink : CH.mid} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
            </g>
          );
        })}

        {/* highlight dot */}
        {highlightIdx !== null && highlightIdx >= 0 && keys.map((k, ki) => {
          const [hx, hy] = xy(highlightIdx, data[highlightIdx][k] || 0);
          return (
            <g key={`hl-${k}`}>
              <line x1={hx} x2={hx} y1={padT} y2={padT + innerH} stroke={CH.deep} strokeWidth="1" strokeDasharray="2 3" />
              <circle cx={hx} cy={hy} r="5" fill={CH.white} stroke={CH.ink} strokeWidth="2" />
            </g>
          );
        })}

        {/* x-axis labels */}
        {showAxis && data.map((d, i) => {
          if (data.length > 12 && i % Math.ceil(data.length / 8) !== 0 && i !== data.length - 1) return null;
          const [x] = xy(i, 0);
          return <text key={i} x={x} y={h - 8} textAnchor="middle" style={{ fontFamily: F_TLB.ui, fontSize: 10, fill: CH.muted, fontWeight: 500 }}>{formatX(d.label)}</text>;
        })}
      </svg>
    </div>
  );
}

// SparkArea — tiny inline area chart
function SparkArea({ values, height = 40, width = 120 }) {
  const id = React.useMemo(() => `sp${Math.random().toString(36).slice(2, 8)}`, []);
  const max = Math.max(...values) * 1.05;
  const min = 0;
  const step = width / Math.max(1, values.length - 1);
  const pts = values.map((v, i) => [i * step, height - ((v - min) / (max - min || 1)) * (height - 4) - 2]);
  const linePath = smoothPath(pts);
  const areaPath = `${linePath} L ${pts[pts.length-1][0]} ${height} L 0 ${height} Z`;
  return (
    <svg viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" style={{ width, height, display: 'block' }}>
      <defs>
        <linearGradient id={id} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={CH.ink} stopOpacity="0.22" />
          <stop offset="100%" stopColor={CH.ink} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={areaPath} fill={`url(#${id})`} />
      <path d={linePath} fill="none" stroke={CH.ink} strokeWidth="1.4" strokeLinecap="round" />
    </svg>
  );
}

// Donut — minimal, single value
function Donut({ value, size = 140, label, sub }) {
  const r = size / 2 - 8;
  const c = size / 2;
  const circ = 2 * Math.PI * r;
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg viewBox={`0 0 ${size} ${size}`} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={c} cy={c} r={r} fill="none" stroke={CH.border} strokeWidth="6" />
        <circle cx={c} cy={c} r={r} fill="none" stroke={CH.ink} strokeWidth="6" strokeLinecap="round"
          strokeDasharray={circ} strokeDashoffset={circ * (1 - value / 100)} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', textAlign: 'center' }}>
        <div>
          <div style={{ fontFamily: F_TLB.ui, fontSize: 28, fontWeight: 600, fontVariantNumeric: 'tabular-nums', letterSpacing: '-0.02em' }}>{label || `${value}%`}</div>
          {sub && <div style={{ fontFamily: F_TLB.ui, fontSize: 9, fontWeight: 600, letterSpacing: '0.14em', color: CH.mid, textTransform: 'uppercase', marginTop: 4 }}>{sub}</div>}
        </div>
      </div>
    </div>
  );
}

// Stacked horizontal bar — channel mix etc.
function StackBar({ segments, height = 28 }) {
  const total = segments.reduce((a, s) => a + s.value, 0);
  return (
    <div style={{ display: 'flex', height, borderRadius: 100, overflow: 'hidden', background: CH.offWhite }}>
      {segments.map((s, i) => {
        const tones = [CH.ink, CH.deep, CH.mid, CH.muted];
        return (
          <div key={i} title={`${s.label} · ${Math.round(s.value/total*100)}%`} style={{ width: `${s.value/total*100}%`, background: tones[i % 4], color: CH.white, display: 'grid', placeItems: 'center', fontFamily: F_TLB.ui, fontSize: 10, fontWeight: 600, fontVariantNumeric: 'tabular-nums', letterSpacing: '0.08em', textTransform: 'uppercase', overflow: 'hidden' }}>
            {s.value/total > 0.12 ? `${s.label} · ${Math.round(s.value/total*100)}%` : ''}
          </div>
        );
      })}
    </div>
  );
}

// Money — modern figure rendering
//   - tabular nums
//   - smaller currency symbol, lifted, with tighter letter-spacing
function Money({ value, currency = 'USD', size = 22, weight = 600, color, italic = false }) {
  const symbol = currency === 'USD' ? '$' : currency === 'IDR' ? 'Rp' : currency;
  const v = typeof value === 'number' ? value.toLocaleString(undefined, { maximumFractionDigits: 0 }) : value;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'baseline', fontFamily: F_TLB.ui, fontWeight: weight, fontSize: size, color: color || CH.ink, fontStyle: italic ? 'italic' : 'normal', letterSpacing: '-0.02em', fontVariantNumeric: 'tabular-nums', lineHeight: 1 }}>
      <span style={{ fontSize: Math.round(size * 0.62), opacity: 0.65, marginRight: 3, fontWeight: weight, transform: 'translateY(-0.18em)' }}>{symbol}</span>
      <span>{v}</span>
    </span>
  );
}

Object.assign(window, { AreaChart, SparkArea, Donut, StackBar, Money });
