// Shared small UI primitives.

const { useState, useEffect, useMemo, useRef } = React;

// Sparkline SVG path
function Sparkline({ data, height = 28, stroke = "currentColor" }) {
  if (!data || !data.length) return null;
  const w = 100, h = height;
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - ((v - min) / range) * (h - 4) - 2;
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(" ");
  return (
    <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" className="spark" style={{ stroke }}>
      <polyline points={pts} fill="none" strokeWidth="1.4" />
    </svg>
  );
}

// 16-segment bar (ASCII bar)
function Segments({ value, total = 16 }) {
  const filled = Math.round(Math.max(0, Math.min(1, value)) * total);
  return (
    <span className="seg">
      {Array.from({ length: total }, (_, i) => (
        <i key={i} className={i < filled ? "on" : ""} />
      ))}
    </span>
  );
}

function Meter({ value, tone }) {
  const t = tone || (value < 0.5 ? "crit" : value < 0.7 ? "warn" : "");
  return (
    <div className={`meter ${t}`}>
      <i style={{ width: `${(value * 100).toFixed(1)}%` }} />
    </div>
  );
}

// Brand glyph + corner brackets
function Brackets({ children }) {
  return (
    <div className="brk">
      <span className="brk-tr" />
      <span className="brk-bl" />
      {children}
    </div>
  );
}

// Number readout that animates on mount
function CountUp({ to, dur = 600, decimals = 0 }) {
  const [v, setV] = useState(to);
  const rafRef = useRef(0);
  useEffect(() => {
    let cancelled = false;
    const t0 = performance.now();
    const step = (t) => {
      if (cancelled) return;
      const p = Math.min(1, (t - t0) / dur);
      const eased = 1 - Math.pow(1 - p, 3);
      setV(eased * to);
      if (p < 1) rafRef.current = requestAnimationFrame(step);
      else setV(to);
    };
    setV(0);
    rafRef.current = requestAnimationFrame(step);
    return () => { cancelled = true; cancelAnimationFrame(rafRef.current); };
  }, [to, dur]);
  return <span>{Number(v).toFixed(decimals)}</span>;
}

// Delta indicator
function Delta({ v }) {
  if (v === 0 || v == null) return <span className="flat">±0</span>;
  if (v > 0) return <span className="up">▲ +{v}</span>;
  return <span className="down">▼ {v}</span>;
}

function PanelH({ num, title, right }) {
  return (
    <div className="panel-h">
      <span className="ttl">
        {num != null && <span className="num">[{String(num).padStart(2, "0")}]</span>}
        <span>{title}</span>
      </span>
      {right && <span>{right}</span>}
    </div>
  );
}

// blinking caret
function Caret() {
  return <span style={{ display: "inline-block", width: 8, height: 14, background: "currentColor", verticalAlign: "-2px", animation: "pulse 1.1s steps(2,end) infinite" }} />;
}

Object.assign(window, { Sparkline, Segments, Meter, Brackets, CountUp, Delta, PanelH, Caret });
