// AXLU — Gamification: CountUp, StreakBadge, LevelBar, TrophyShelf, Leaderboard, Confetti.

// Anim CSS injectées une seule fois.
(function injectGamificationCSS() {
  if (document.getElementById("axlu-gam-css")) return;
  const css = `
    @keyframes axlu-pop      { 0% { transform: scale(.6); opacity:0 } 60% { transform: scale(1.08); opacity:1 } 100% { transform: scale(1) } }
    @keyframes axlu-flicker  { 0%,100% { transform: scale(1) rotate(-3deg); filter: drop-shadow(0 0 0 rgba(245,158,11,0)) } 50% { transform: scale(1.08) rotate(3deg); filter: drop-shadow(0 0 6px rgba(245,158,11,.6)) } }
    @keyframes axlu-spin     { to { transform: rotate(360deg) } }
    @keyframes axlu-shimmer  { 0% { background-position: -200% 0 } 100% { background-position: 200% 0 } }
    @keyframes axlu-float    { 0% { transform: translate(0,0) scale(.4); opacity: 0 }
                               20% { opacity: 1 }
                               100% { transform: translate(var(--dx,0), var(--dy,-80px)) scale(1); opacity: 0 } }
    @keyframes axlu-sparkle  { 0%,100% { opacity: .25; transform: scale(.85) rotate(0) } 50% { opacity: 1; transform: scale(1) rotate(20deg) } }
    @keyframes axlu-jump     { 0%,100% { transform: translateY(0) } 30% { transform: translateY(-3px) } 60% { transform: translateY(0) } }
    .axlu-pop      { animation: axlu-pop .35s cubic-bezier(.34,1.56,.64,1) both; }
    .axlu-flicker  { display:inline-block; animation: axlu-flicker 1.6s ease-in-out infinite; transform-origin: 50% 70%; }
    .axlu-spin     { animation: axlu-spin 1.4s linear infinite; }
    .axlu-jump     { display:inline-block; animation: axlu-jump 1.8s ease-in-out infinite; }
    .axlu-shimmer  {
      background-image: linear-gradient(90deg,
        transparent 0%, transparent 35%,
        rgba(255,255,255,.45) 50%,
        transparent 65%, transparent 100%);
      background-size: 200% 100%;
      animation: axlu-shimmer 2.2s ease-in-out infinite;
    }
    .axlu-sparkle-dot { animation: axlu-sparkle 1.6s ease-in-out infinite; }
    .axlu-confetti-piece {
      position: fixed; pointer-events: none; z-index: 9999;
      font-size: 22px; line-height: 1;
      animation: axlu-float 1600ms cubic-bezier(.2,.6,.3,1) forwards;
      will-change: transform, opacity;
    }
  `;
  const tag = document.createElement("style");
  tag.id = "axlu-gam-css";
  tag.textContent = css;
  document.head.appendChild(tag);
})();

// ─── CountUp ───────────────────────────────────────────────────────────
function CountUp({ to = 0, duration = 700, format = (n) => n.toLocaleString("fr-FR"), className = "" }) {
  const target = Number(to) || 0;
  const [val, setVal] = useState(target);
  const fromRef = useRef(target);

  useEffect(() => {
    const from = fromRef.current;
    if (from === target) return;
    const start = performance.now();
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      const eased = 1 - Math.pow(1 - p, 3); // ease-out cubic
      setVal(Math.round(from + (target - from) * eased));
      if (p < 1) raf = requestAnimationFrame(tick);
      else fromRef.current = target;
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target, duration]);

  return <span className={className}>{format(val)}</span>;
}

// ─── StreakBadge ───────────────────────────────────────────────────────
function StreakBadge({ days = 0, compact = false }) {
  if (compact) {
    return (
      <span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium"
            style={{ background: "rgba(245,158,11,.12)", color: "#b45309" }}
            title={`${days} jours consécutifs`}>
        <span className="axlu-flicker" aria-hidden>🔥</span>
        <span className="mono tabular-nums">{days}j</span>
      </span>
    );
  }
  return (
    <div className="surface border rounded-md px-3 py-2 flex items-center gap-2.5"
         style={{ borderColor: "var(--border)" }}>
      <span className="axlu-flicker text-[22px] leading-none" aria-hidden>🔥</span>
      <div className="leading-tight">
        <div className="text-[11px] uppercase tracking-wider text-subtle font-medium">Streak</div>
        <div className="text-[15px] font-semibold mono tabular-nums">
          {days} <span className="text-muted text-[12px] font-normal">jours</span>
        </div>
      </div>
    </div>
  );
}

// ─── LevelBar ──────────────────────────────────────────────────────────
function LevelBar({ level = 1, levelName = "", xp = 0, xpForNext = 100, xpToday = 0, compact = false }) {
  const pct = Math.max(2, Math.min(100, Math.round((xp / xpForNext) * 100)));
  if (compact) {
    return (
      <div className="flex items-center gap-2">
        <span className="inline-flex items-center justify-center w-6 h-6 rounded-md font-semibold text-[11px]"
              style={{ background: "var(--accent-bg)", color: "var(--accent)" }}>
          {level}
        </span>
        <div className="flex-1 min-w-[120px]">
          <div className="h-1.5 sunken rounded-full overflow-hidden">
            <div className="h-full axlu-shimmer" style={{ width: pct + "%", background: "var(--accent)", borderRadius: "inherit" }}/>
          </div>
          <div className="text-[10.5px] text-subtle mono tabular-nums mt-0.5">
            {xp.toLocaleString("fr-FR")} / {xpForNext.toLocaleString("fr-FR")} XP
          </div>
        </div>
      </div>
    );
  }
  return (
    <div className="surface border rounded-md p-3" style={{ borderColor: "var(--border)" }}>
      <div className="flex items-center gap-2.5 mb-2">
        <span className="inline-flex items-center justify-center w-9 h-9 rounded-lg font-semibold text-[14px]"
              style={{ background: "var(--accent-bg)", color: "var(--accent)" }}>
          ⭐ {level}
        </span>
        <div className="flex-1 min-w-0">
          <div className="text-[11px] uppercase tracking-wider text-subtle font-medium">Niveau {level}</div>
          <div className="text-[13.5px] font-semibold truncate">{levelName}</div>
        </div>
        {xpToday > 0 && (
          <span className="px-2 py-0.5 rounded-full text-[11px] font-medium mono tabular-nums"
                style={{ background: "rgba(16,185,129,.12)", color: "#047857" }}>
            +{xpToday} XP aujourd'hui
          </span>
        )}
      </div>
      <div className="h-2 sunken rounded-full overflow-hidden relative">
        <div className="h-full axlu-shimmer transition-all duration-500"
             style={{ width: pct + "%", background: "var(--accent)", borderRadius: "inherit" }}/>
      </div>
      <div className="flex items-center justify-between mt-1.5 text-[11px]">
        <span className="text-muted mono tabular-nums">{xp.toLocaleString("fr-FR")} XP</span>
        <span className="text-subtle">
          plus que <span className="mono text-app">{(xpForNext - xp).toLocaleString("fr-FR")}</span> avant niv. {level + 1}
        </span>
      </div>
    </div>
  );
}

// ─── TrophyShelf ───────────────────────────────────────────────────────
function TrophyShelf({ badges = [], max = 8 }) {
  const shown = badges.slice(0, max);
  return (
    <div className="grid grid-cols-4 gap-1.5">
      {shown.map((b) => (
        <div key={b.id}
             title={b.earned ? `${b.name} — ${b.date}` : `À débloquer : ${b.name}`}
             className="aspect-square rounded-md flex flex-col items-center justify-center text-center p-1"
             style={{
               background: b.earned ? "var(--accent-bg)" : "var(--sunken)",
               border: "1px solid var(--border)",
               opacity: b.earned ? 1 : 0.55,
               filter: b.earned ? "none" : "grayscale(1)",
             }}>
          <span className={`text-[22px] leading-none ${b.earned ? "axlu-pop" : ""}`} aria-hidden>{b.emoji}</span>
          <span className="text-[9px] text-subtle mt-1 line-clamp-2 leading-tight">{b.name}</span>
        </div>
      ))}
    </div>
  );
}

// ─── Leaderboard ───────────────────────────────────────────────────────
function Leaderboard({ rows = [] }) {
  const sorted = [...rows].sort((a, b) => b.xp - a.xp);
  const medals = ["🥇", "🥈", "🥉"];
  return (
    <div className="space-y-1">
      {sorted.map((r, i) => (
        <div key={r.name}
             className={`flex items-center gap-2 px-2 py-1.5 rounded ${r.you ? "" : "hover:bg-[var(--hover)]"}`}
             style={{ background: r.you ? "var(--accent-bg)" : "transparent" }}>
          <span className="w-5 text-center text-[14px]" aria-hidden>{medals[i] || <span className="text-subtle text-[11px] mono">{i + 1}</span>}</span>
          <span className={`flex-1 text-[12.5px] truncate ${r.you ? "font-semibold accent-fg" : ""}`}>
            {r.name}{r.you && " (vous)"}
          </span>
          <span className="mono tabular-nums text-[12px] text-muted">{r.xp.toLocaleString("fr-FR")} XP</span>
        </div>
      ))}
    </div>
  );
}

// ─── Confetti (emoji-based, lightweight) ───────────────────────────────
function fireConfetti({ origin, emojis = ["✨", "🎉", "🎊", "⭐", "💫"], count = 18 } = {}) {
  let cx, cy;
  if (origin && typeof origin.getBoundingClientRect === "function") {
    const r = origin.getBoundingClientRect();
    cx = r.left + r.width / 2;
    cy = r.top + r.height / 2;
  } else {
    cx = window.innerWidth / 2;
    cy = window.innerHeight / 2;
  }
  for (let i = 0; i < count; i++) {
    const span = document.createElement("span");
    span.className = "axlu-confetti-piece";
    span.textContent = emojis[i % emojis.length];
    const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.4;
    const dist = 80 + Math.random() * 80;
    span.style.left = cx + "px";
    span.style.top = cy + "px";
    span.style.setProperty("--dx", Math.cos(angle) * dist + "px");
    span.style.setProperty("--dy", (Math.sin(angle) * dist - 40) + "px");
    span.style.fontSize = (16 + Math.random() * 14) + "px";
    span.style.animationDelay = (Math.random() * 80) + "ms";
    document.body.appendChild(span);
    setTimeout(() => span.remove(), 1900);
  }
}

// ─── Sparkle decoration (3 dots tweening around an element) ────────────
function SparkleDots({ children }) {
  return (
    <span className="relative inline-block">
      {children}
      <span className="absolute -top-1 -right-2 text-[10px] axlu-sparkle-dot" style={{ animationDelay: "0s" }} aria-hidden>✨</span>
      <span className="absolute -bottom-1 -left-2 text-[8px] axlu-sparkle-dot" style={{ animationDelay: ".4s" }} aria-hidden>✨</span>
    </span>
  );
}

// ─── SupplierAvatar — real logo image if set, else emoji circle ────────
function SupplierAvatar({ supplier, size = 28 }) {
  const logo = supplier && supplier.logo;
  if (logo) {
    return (
      <span
        className="inline-flex items-center justify-center rounded-md border shrink-0 overflow-hidden"
        style={{ width: size, height: size, borderColor: "var(--border)", background: "#fff" }}
        aria-label={supplier && supplier.name}>
        <img src={logo} alt="" draggable={false}
             style={{ width: "100%", height: "100%", objectFit: "contain" }}/>
      </span>
    );
  }
  const emoji = (supplier && supplier.emoji) || "🏷️";
  return (
    <span
      className="inline-flex items-center justify-center rounded-md sunken border shrink-0"
      style={{
        width: size, height: size,
        borderColor: "var(--border)",
        fontSize: Math.round(size * 0.55),
        lineHeight: 1,
      }}
      aria-label={supplier && supplier.name}>
      {emoji}
    </span>
  );
}

// ─── StatusEmoji (decorate status badges) ──────────────────────────────
function StatusEmoji({ status, map }) {
  const cfg = map?.[status];
  if (!cfg?.emoji) return null;
  const cls = status === "running" ? "axlu-jump" : "";
  return <span className={`mr-1 ${cls}`} aria-hidden>{cfg.emoji}</span>;
}

Object.assign(window, {
  CountUp,
  StreakBadge,
  LevelBar,
  TrophyShelf,
  Leaderboard,
  fireConfetti,
  SparkleDots,
  SupplierAvatar,
  StatusEmoji,
});
