// Reusable visual components: rolling digits, count-up number, habit burst, heatmap row.

// Single digit that rolls vertically when it changes
function RollingDigit({ digit }) {
  const ref = useRef(null);
  useLayoutEffect(() => {
    if (!ref.current) return;
    ref.current.style.transform = `translateY(-${digit * 10}%)`;
  }, [digit]);
  return (
    <span className="col" style={{ display: 'inline-block', width: '0.62em', height: '1em', verticalAlign: 'top' }}>
      <span ref={ref} className="track" style={{ willChange: 'transform' }}>
        {[0,1,2,3,4,5,6,7,8,9].map(n => (
          <span key={n} style={{ height: '1em', display: 'block' }}>{n}</span>
        ))}
      </span>
    </span>
  );
}

// Number that rolls each of its digits individually
function RollingNumber({ value, minDigits = 1, className = '', style = {} }) {
  const str = String(Math.max(0, Math.floor(value))).padStart(minDigits, '0');
  return (
    <span className={`num-rollup tabular ${className}`} style={style}>
      {str.split('').map((ch, i) => (
        <RollingDigit key={i} digit={parseInt(ch, 10)} />
      ))}
    </span>
  );
}

// Animated count-up (non-digit-flipping, just numeric tween)
function CountUp({ value, decimals = 0, duration = 800, suffix = '', className = '', style = {} }) {
  const display = useCountUp(value, { duration, decimals });
  return (
    <span className={`tabular ${className}`} style={style}>
      {decimals === 0 ? Math.round(display) : display.toFixed(decimals)}{suffix}
    </span>
  );
}

// Particle burst for habit checkoff
function Burst({ active }) {
  if (!active) return null;
  const parts = Array.from({ length: 12 });
  return (
    <div className="burst" key={active}>
      {parts.map((_, i) => {
        const angle = (i / parts.length) * Math.PI * 2;
        const dist = 40 + Math.random() * 30;
        const tx = Math.cos(angle) * dist;
        const ty = Math.sin(angle) * dist;
        return (
          <div
            key={i}
            className="p"
            style={{
              '--tx': `${tx}px`,
              '--ty': `${ty}px`,
              animationDelay: `${Math.random() * 0.05}s`,
            }}
          />
        );
      })}
    </div>
  );
}

// Heatmap row with labels, hover tooltip, recent-cell glow
function HeatmapRow({ label, cells, pad, getColor, streak, total, totalLabel, highlight, recentIndexes = [] }) {
  const [hover, setHover] = useState(null);
  return (
    <div>
      <div className="flex items-baseline justify-between mb-2">
        <div className={`text-sm ${highlight ? 'font-medium' : ''}`} style={{ color: highlight ? 'var(--text-0)' : 'var(--text-1)' }}>{label}</div>
        <div className="text-[11px] tracking-wide" style={{ color: 'var(--text-2)' }}>
          {streak !== null && streak !== undefined ? (
            <><span className="font-medium tabular" style={{ color: 'var(--accent)' }}>{streak}</span> day streak</>
          ) : total !== undefined ? (
            <><span className="font-medium tabular" style={{ color: 'var(--accent)' }}>{total}</span> {totalLabel}</>
          ) : null}
          {hover && (
            <span className="ml-3 tabular" style={{ color: 'var(--text-1)' }}>
              · {hover.date} · {typeof hover.value === 'number' && hover.value > 0 && hover.value < 1 ? hover.value.toFixed(1) : hover.value || 0}
            </span>
          )}
        </div>
      </div>
      <div
        className="grid grid-rows-7 grid-flow-col"
        style={{ gridTemplateRows: 'repeat(7, 14px)', gridAutoColumns: '14px', gap: '4px' }}
      >
        {Array.from({ length: pad }).map((_, i) => <div key={`p${i}`} />)}
        {cells.map((c, idx) => (
          <div
            key={c.date}
            onMouseEnter={() => setHover(c)}
            onMouseLeave={() => setHover(null)}
            className={`heat-cell ${recentIndexes.includes(idx) && c.value > 0 ? 'heat-recent' : ''}`}
            style={{
              width: '14px',
              height: '14px',
              background: getColor(c.value),
            }}
          />
        ))}
      </div>
    </div>
  );
}

// Shared heatmap cell color getter
function makeCellColor(theme) {
  return (value, max = 1) => {
    if (!value) {
      if (theme === 'editorial') return '#E6DDC9';
      if (theme === 'terminal') return '#0E1A12';
      return '#151819';
    }
    if (max <= 1) return 'var(--accent)';
    const i = Math.min(1, value / max);
    // Accent interpolation using color-mix-ish fallback with hardcoded steps
    const css = getComputedStyle(document.body);
    const accent = css.getPropertyValue('--accent').trim() || '#7FD4A3';
    const bg = css.getPropertyValue('--bg-1').trim() || '#0C0F10';
    // Mix: blend bg → accent by i
    const mix = (c1, c2, t) => {
      const h = (s) => {
        const n = parseInt(s.replace('#', ''), 16);
        return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
      };
      const [r1, g1, b1] = h(c1);
      const [r2, g2, b2] = h(c2);
      const r = Math.round(r1 + (r2 - r1) * t);
      const g = Math.round(g1 + (g2 - g1) * t);
      const b = Math.round(b1 + (b2 - b1) * t);
      return `rgb(${r}, ${g}, ${b})`;
    };
    return mix(bg, accent, 0.2 + i * 0.8);
  };
}

Object.assign(window, { RollingDigit, RollingNumber, CountUp, Burst, HeatmapRow, makeCellColor });
