import { useEffect, useMemo, useState, useId } from "react";

type ConfettiBurstProps = {
  className?: string;
  colors?: string[];
  count?: number;
};

type Piece = { id: number; style: React.CSSProperties & ConfettiVars };

type ConfettiVars = {
  ["--x0"]: string;
  ["--y0"]: string;
  ["--x1"]: string;
  ["--y1"]: string;
};

const hashStringToUint32 = (value: string) => {
  // FNV-1a 32-bit
  let hash = 2166136261;
  for (let i = 0; i < value.length; i++) {
    hash ^= value.charCodeAt(i);
    hash = Math.imul(hash, 16777619);
  }
  return hash >>> 0;
};

const mulberry32 = (seed: number) => {
  return () => {
    let t = (seed += 0x6d2b79f5);
    t = Math.imul(t ^ (t >>> 15), t | 1);
    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
};

export const ConfettiBurst = ({
  className,
  colors = [
    "var(--color-primary)",
    "var(--color-accent)",
    "var(--color-primary-light)",
    "var(--color-accent-light)",
  ],
  count = 18,
}: ConfettiBurstProps) => {
  const [visible, setVisible] = useState(true);
  const instanceId = useId();

  useEffect(() => {
    const t = window.setTimeout(() => setVisible(false), 1100);
    return () => window.clearTimeout(t);
  }, []);

  const pieces = useMemo<Piece[]>(() => {
    const seed = hashStringToUint32(
      `${instanceId}:${count}:${colors.join(",")}`,
    );
    const rand = mulberry32(seed);
    const rnd = (min: number, max: number) => min + rand() * (max - min);

    return Array.from({ length: count }).map((_, i) => {
      const x0 = rnd(-6, 6);
      const y0 = rnd(-6, 6);
      const x1 = rnd(-160, 160);
      const y1 = rnd(60, 220);
      const delay = rnd(0, 120);
      const rotate = rnd(0, 360);
      const color = colors[i % colors.length];

      return {
        id: i,
        style: {
          left: "50%",
          top: "0%",
          backgroundColor: color,
          transform: `translate(${x0}px, ${y0}px) rotate(${rotate}deg)`,
          animationDelay: `${delay}ms`,
          // consumed by keyframes
          ["--x0"]: `${x0}px`,
          ["--y0"]: `${y0}px`,
          ["--x1"]: `${x1}px`,
          ["--y1"]: `${y1}px`,
        },
      };
    });
  }, [colors, count, instanceId]);

  if (!visible) return null;

  return (
    <div
      className={`pointer-events-none absolute inset-0 overflow-visible ${className ?? ""}`}
      aria-hidden
    >
      {pieces.map((p) => (
        <span key={p.id} className="lila-confetti-piece" style={p.style} />
      ))}
    </div>
  );
};
