/**
 * Small particle burst used by the Add Friend and Save buttons.
 * Ported from the reference design: dots fly outward on an arc, then fall
 * slightly and shrink as they fade.
 */
export function burst(host: HTMLElement, colors: string[], n = 10, spread = 24) {
  for (let i = 0; i < n; i++) {
    const p = document.createElement("span");
    p.className = "pt";
    const a = Math.random() * Math.PI * 2;
    const d = spread * (0.6 + Math.random() * 0.7);
    const tx = Math.cos(a) * d;
    const ty = Math.sin(a) * d;
    const size = 3 + Math.random() * 3;
    p.style.width = `${size}px`;
    p.style.height = `${size}px`;
    p.style.background = colors[i % colors.length];
    p.style.boxShadow = `0 0 6px ${colors[i % colors.length]}`;
    host.appendChild(p);
    p.animate(
      [
        { transform: "translate(-50%,-50%)", opacity: 1, offset: 0 },
        {
          transform: `translate(calc(-50% + ${tx * 0.8}px), calc(-50% + ${ty * 0.8}px))`,
          opacity: 1,
          offset: 0.55,
        },
        {
          transform: `translate(calc(-50% + ${tx}px), calc(-50% + ${ty + 16}px)) scale(.2)`,
          opacity: 0,
          offset: 1,
        },
      ],
      { duration: 650 + Math.random() * 300, easing: "cubic-bezier(.15,.75,.35,1)" }
    ).onfinish = () => p.remove();
  }
}

/**
 * A full firework: a bright flash, an expanding shockwave ring, a dense
 * spray of colored sparks that arc outward and fall, plus a few twinkling
 * star glyphs. Used by Save and Add Friend.
 */
export function firework(host: HTMLElement, colors: string[]) {
  // Render into a fixed-position layer on <body> rather than inside the
  // button: React re-renders the button when its label changes, which would
  // otherwise wipe these nodes out mid-animation.
  const r = host.getBoundingClientRect();
  const layer = document.createElement("div");
  layer.style.cssText = `position:fixed;left:${r.left + r.width / 2}px;top:${
    r.top + r.height / 2
  }px;width:0;height:0;pointer-events:none;z-index:9999`;
  document.body.appendChild(layer);
  setTimeout(() => layer.remove(), 1600);
  host = layer;

  // 1. Centre flash
  const flash = document.createElement("span");
  flash.className = "fw-flash";
  flash.style.background = `radial-gradient(circle, ${colors[0]}cc, transparent 70%)`;
  host.appendChild(flash);
  flash.animate(
    [
      { transform: "translate(-50%,-50%) scale(.2)", opacity: 1 },
      { transform: "translate(-50%,-50%) scale(2.6)", opacity: 0 },
    ],
    { duration: 480, easing: "ease-out" }
  ).onfinish = () => flash.remove();

  // 2. Shockwave ring
  const ring = document.createElement("span");
  ring.className = "fw-ring";
  ring.style.borderColor = colors[0];
  host.appendChild(ring);
  ring.animate(
    [
      { transform: "translate(-50%,-50%) scale(.2)", opacity: 1, borderWidth: "3px" },
      { transform: "translate(-50%,-50%) scale(2.8)", opacity: 0, borderWidth: "1px" },
    ],
    { duration: 620, easing: "cubic-bezier(.2,.7,.4,1)" }
  ).onfinish = () => ring.remove();

  // 3. Spark spray — two rings of particles at different speeds
  for (let i = 0; i < 26; i++) {
    const p = document.createElement("span");
    p.className = "pt";
    const a = (i / 26) * Math.PI * 2 + Math.random() * 0.35;
    const fast = i % 2 === 0;
    const d = (fast ? 78 : 52) * (0.7 + Math.random() * 0.6);
    const tx = Math.cos(a) * d;
    const ty = Math.sin(a) * d;
    const size = 5 + Math.random() * 5;
    const c = colors[i % colors.length];
    p.style.width = `${size}px`;
    p.style.height = `${size}px`;
    p.style.background = c;
    p.style.boxShadow = `0 0 8px ${c}, 0 0 14px ${c}`;
    host.appendChild(p);
    p.animate(
      [
        { transform: "translate(-50%,-50%) scale(1)", opacity: 1, offset: 0 },
        {
          transform: `translate(calc(-50% + ${tx * 0.85}px), calc(-50% + ${ty * 0.85}px)) scale(1)`,
          opacity: 1,
          offset: 0.5,
        },
        {
          // Gravity: drift down as they fade out.
          transform: `translate(calc(-50% + ${tx}px), calc(-50% + ${ty + 26}px)) scale(.2)`,
          opacity: 0,
          offset: 1,
        },
      ],
      { duration: 950 + Math.random() * 500, easing: "cubic-bezier(.12,.7,.3,1)" }
    ).onfinish = () => p.remove();
  }

  // 4. Twinkling stars
  for (let i = 0; i < 6; i++) {
    const s = document.createElement("span");
    s.className = "fw-star";
    s.textContent = "✦";
    const a = Math.random() * Math.PI * 2;
    const d = 20 + Math.random() * 30;
    s.style.left = `calc(50% + ${Math.cos(a) * d}px)`;
    s.style.top = `calc(50% + ${Math.sin(a) * d}px)`;
    s.style.fontSize = `${8 + Math.random() * 7}px`;
    s.style.color = colors[i % colors.length];
    s.style.textShadow = `0 0 10px ${colors[i % colors.length]}`;
    s.style.animationDelay = `${Math.random() * 0.25}s`;
    host.appendChild(s);
    setTimeout(() => s.remove(), 1200);
  }
}
