"use client";

import { useEffect, useRef } from "react";

/** Counts from 0 to `value` when scrolled into view. */
export function CountUp({ value, className, duration = 1300 }: { value: number; className?: string; duration?: number }) {
  const ref = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
      el.textContent = value.toLocaleString("en-IN");
      return;
    }
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (!entry.isIntersecting) return;
        observer.disconnect();
        const start = performance.now();
        const tick = (now: number) => {
          if (finished) return;
          const p = Math.min(1, (now - start) / duration);
          const eased = 1 - Math.pow(1 - p, 3);
          el.textContent = Math.round(value * eased).toLocaleString("en-IN");
          if (p < 1) requestAnimationFrame(tick);
        };
        requestAnimationFrame(tick);
      },
      { threshold: 0.4 }
    );
    let finished = false;
    observer.observe(el);
    // IntersectionObserver and rAF are throttled or paused in hidden tabs —
    // unconditionally land on the final value once the entrance window passes.
    const settle = setTimeout(() => {
      finished = true;
      el.textContent = value.toLocaleString("en-IN");
    }, duration + 1200);
    return () => { observer.disconnect(); clearTimeout(settle); };
  }, [value, duration]);

  return <span ref={ref} className={className}>0</span>;
}

const CONFETTI_COLORS = ["#6366f1", "#a855f7", "#ec4899", "#f59e0b", "#10b981", "#0ea5e9"];

/** One-shot celebratory confetti burst (used after successful registration). */
export function Confetti({ pieces = 90 }: { pieces?: number }) {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const host = ref.current;
    if (!host || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    const frag = document.createDocumentFragment();
    for (let i = 0; i < pieces; i++) {
      const p = document.createElement("span");
      const size = 6 + Math.random() * 7;
      const left = Math.random() * 100;
      const delay = Math.random() * 0.6;
      const fall = 2.4 + Math.random() * 1.8;
      const drift = (Math.random() - 0.5) * 240;
      const spin = 360 + Math.random() * 720;
      p.style.cssText = `
        position: fixed; top: -3vh; left: ${left}vw; z-index: 60; pointer-events: none;
        width: ${size}px; height: ${size * (Math.random() > 0.5 ? 0.45 : 1)}px;
        background: ${CONFETTI_COLORS[i % CONFETTI_COLORS.length]};
        border-radius: ${Math.random() > 0.6 ? "50%" : "2px"};
        opacity: 0.95;
        animation: cfx-fall ${fall}s cubic-bezier(0.25, 0.4, 0.6, 1) ${delay}s forwards;
        --cfx-drift: ${drift}px; --cfx-spin: ${spin}deg;
      `;
      frag.appendChild(p);
    }
    const style = document.createElement("style");
    style.textContent = `@keyframes cfx-fall {
      to { transform: translate3d(var(--cfx-drift), 105vh, 0) rotate(var(--cfx-spin)); opacity: 0.7; }
    }`;
    host.appendChild(style);
    host.appendChild(frag);
    const t = setTimeout(() => { host.replaceChildren(); }, 5500);
    return () => { clearTimeout(t); host.replaceChildren(); };
  }, [pieces]);

  return <div ref={ref} aria-hidden />;
}
