/* ============================================================
   CADENCE — Charts (data-driven SVG)
   window.Charts = { Sparkline, PriceChart, Donut, RevenueBars }
   ============================================================ */
(function () {
  const { useState, useRef, useMemo, useEffect } = React;

  const GREEN = 'oklch(0.755 0.155 158)';
  const RED = 'oklch(0.660 0.190 22)';
  const BLUE = 'oklch(0.700 0.165 252)';

  function linePath(data, w, h, pad) {
    const min = Math.min(...data), max = Math.max(...data);
    const rng = max - min || 1;
    const px = (i) => pad + (i / (data.length - 1)) * (w - pad * 2);
    // Center a perfectly flat series instead of pinning it to the bottom.
    const py = (v) => (max === min ? h / 2 : h - pad - ((v - min) / rng) * (h - pad * 2));
    let d = '';
    data.forEach((v, i) => { d += (i === 0 ? 'M' : 'L') + px(i).toFixed(2) + ' ' + py(v).toFixed(2) + ' '; });
    return { d, px, py };
  }

  // smooth-ish path via simple line (clean, fintech)
  function Sparkline({ data, up, height = 38, strokeW = 1.6 }) {
    const w = 120, h = height, pad = 3;
    const color = up ? GREEN : RED;
    const { d, px, py } = useMemo(() => linePath(data, w, h, pad), [data, h]);
    const area = d + `L ${px(data.length - 1)} ${h} L ${px(0)} ${h} Z`;
    const gid = useMemo(() => 'sp' + Math.random().toString(36).slice(2, 8), []);
    return (
      <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} preserveAspectRatio="none" style={{ display: 'block', overflow: 'visible' }}>
        <defs>
          <linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor={color} stopOpacity="0.28" />
            <stop offset="1" stopColor={color} stopOpacity="0" />
          </linearGradient>
        </defs>
        <path d={area} fill={`url(#${gid})`} />
        <path d={d} fill="none" stroke={color} strokeWidth={strokeW} vectorEffect="non-scaling-stroke" strokeLinejoin="round" strokeLinecap="round" />
      </svg>
    );
  }

  // Large interactive price chart with crosshair + tooltip + timeframe slicing
  function PriceChart({ data, up, height = 280, mode = 'area', labelFmt }) {
    const wrapRef = useRef(null);
    const [hover, setHover] = useState(null);
    const [w, setW] = useState(720);
    const h = height, padX = 6, padT = 14, padB = 22;
    const color = up ? GREEN : RED;
    const gid = useMemo(() => 'pc' + Math.random().toString(36).slice(2, 8), []);

    useEffect(() => {
      if (!wrapRef.current) return;
      const ro = new ResizeObserver((es) => setW(es[0].contentRect.width));
      ro.observe(wrapRef.current);
      return () => ro.disconnect();
    }, []);

    const min = Math.min(...data), max = Math.max(...data);
    const rng = max - min || 1;
    const px = (i) => padX + (i / (data.length - 1)) * (w - padX * 2);
    // Center a perfectly flat series instead of pinning it to the bottom.
    const py = (v) => (max === min ? padT + (h - padT - padB) / 2 : padT + (1 - (v - min) / rng) * (h - padT - padB));

    let line = '';
    data.forEach((v, i) => { line += (i === 0 ? 'M' : 'L') + px(i).toFixed(1) + ' ' + py(v).toFixed(1) + ' '; });
    const area = line + `L ${px(data.length - 1).toFixed(1)} ${h - padB} L ${px(0).toFixed(1)} ${h - padB} Z`;

    function onMove(e) {
      const r = wrapRef.current.getBoundingClientRect();
      const x = e.clientX - r.left;
      const i = Math.max(0, Math.min(data.length - 1, Math.round(((x - padX) / (w - padX * 2)) * (data.length - 1))));
      setHover(i);
    }

    // gridlines (4 horizontal)
    const grids = [0, 0.25, 0.5, 0.75, 1].map((f) => padT + f * (h - padT - padB));

    return (
      <div ref={wrapRef} style={{ position: 'relative', width: '100%' }}
        onMouseMove={onMove} onMouseLeave={() => setHover(null)}>
        <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} style={{ display: 'block' }}>
          <defs>
            <linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
              <stop offset="0" stopColor={color} stopOpacity="0.26" />
              <stop offset="0.7" stopColor={color} stopOpacity="0.04" />
              <stop offset="1" stopColor={color} stopOpacity="0" />
            </linearGradient>
          </defs>
          {grids.map((y, i) => (
            <line key={i} x1={padX} x2={w - padX} y1={y} y2={y} stroke="oklch(0.30 0.014 256)" strokeWidth="1" strokeDasharray="2 5" opacity="0.5" />
          ))}
          {mode === 'area' && <path d={area} fill={`url(#${gid})`} />}
          <path d={line} fill="none" stroke={color} strokeWidth="2" strokeLinejoin="round" strokeLinecap="round" />
          {/* last point pulse */}
          <circle cx={px(data.length - 1)} cy={py(data[data.length - 1])} r="3.5" fill={color} />
          <circle cx={px(data.length - 1)} cy={py(data[data.length - 1])} r="3.5" fill="none" stroke={color} opacity="0.4">
            <animate attributeName="r" from="3.5" to="11" dur="1.8s" repeatCount="indefinite" />
            <animate attributeName="opacity" from="0.45" to="0" dur="1.8s" repeatCount="indefinite" />
          </circle>
          {hover != null && (
            <g>
              <line x1={px(hover)} x2={px(hover)} y1={padT} y2={h - padB} stroke="oklch(0.7 0.01 256)" strokeWidth="1" strokeDasharray="3 3" opacity="0.6" />
              <circle cx={px(hover)} cy={py(data[hover])} r="4.5" fill={color} stroke="var(--bg)" strokeWidth="2" />
            </g>
          )}
        </svg>
        {hover != null && (
          <div className="chart-tip num" style={{ left: Math.min(Math.max(px(hover), 48), w - 48), top: py(data[hover]) }}>
            <div className="tp">${data[hover].toFixed(2)}</div>
            <div className="td">{labelFmt ? labelFmt(hover, data.length) : `t-${data.length - 1 - hover}`}</div>
          </div>
        )}
      </div>
    );
  }

  // Ownership donut
  function Donut({ segments, size = 168, thickness = 22, centerLabel, centerSub }) {
    const r = (size - thickness) / 2;
    const c = size / 2;
    const circ = 2 * Math.PI * r;
    let offset = 0;
    return (
      <div style={{ position: 'relative', width: size, height: size }}>
        <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
          <circle cx={c} cy={c} r={r} fill="none" stroke="var(--surface-2)" strokeWidth={thickness} />
          {segments.map((s, i) => {
            const len = (s.value / 100) * circ;
            const el = (
              <circle key={i} cx={c} cy={c} r={r} fill="none" stroke={s.color} strokeWidth={thickness}
                strokeDasharray={`${len} ${circ - len}`} strokeDashoffset={-offset} strokeLinecap="butt">
              </circle>
            );
            offset += len;
            return el;
          })}
        </svg>
        <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', textAlign: 'center' }}>
          <div>
            <div className="num" style={{ fontSize: 26, fontWeight: 600, letterSpacing: '-0.03em' }}>{centerLabel}</div>
            <div style={{ fontSize: 11, color: 'var(--text-mute)' }}>{centerSub}</div>
          </div>
        </div>
      </div>
    );
  }

  // Revenue bars
  function RevenueBars({ data, height = 130, labels }) {
    const wrapRef = useRef(null);
    const [w, setW] = useState(520);
    const [hover, setHover] = useState(null);
    useEffect(() => {
      if (!wrapRef.current) return;
      const ro = new ResizeObserver((es) => setW(es[0].contentRect.width));
      ro.observe(wrapRef.current);
      return () => ro.disconnect();
    }, []);
    const max = Math.max(...data) || 1; // avoid divide-by-zero when revenue is all 0
    const n = data.length;
    const gap = 6;
    const bw = (w - gap * (n - 1)) / n;
    const h = height, padB = 4;
    return (
      <div ref={wrapRef} style={{ position: 'relative', width: '100%' }}>
        <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} style={{ display: 'block' }}>
          <defs>
            <linearGradient id="revbar" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0" stopColor="oklch(0.70 0.165 252)" />
              <stop offset="1" stopColor="oklch(0.52 0.11 256)" />
            </linearGradient>
          </defs>
          {data.map((v, i) => {
            const bh = Math.max(3, (v / max) * (h - padB - 6));
            const x = i * (bw + gap);
            const isH = hover === i;
            return (
              <rect key={i} x={x} y={h - padB - bh} width={bw} height={bh} rx="3"
                fill={isH ? 'oklch(0.78 0.16 158)' : 'url(#revbar)'}
                onMouseEnter={() => setHover(i)} onMouseLeave={() => setHover(null)}
                style={{ transition: 'fill .12s' }} />
            );
          })}
        </svg>
        {hover != null && (
          <div className="chart-tip num" style={{ left: hover * (bw + gap) + bw / 2, top: h - padB - (data[hover] / max) * (h - padB - 6) }}>
            <div className="tp">${data[hover].toLocaleString()}</div>
            <div className="td">{labels ? labels[hover] : `month ${hover + 1}`}</div>
          </div>
        )}
      </div>
    );
  }

  window.Charts = { Sparkline, PriceChart, Donut, RevenueBars };
})();
