import { AnimatePresence, motion } from "framer-motion";
import { useEffect, useState } from "react";
import { useNfcWs } from "./NfcWsContext";

const SPARKS = 16;
const COINS = 7;

function playChaChing() {
  try {
    const Ctx = window.AudioContext || (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext;
    if (!Ctx) {
      return;
    }
    const ctx = new Ctx();
    const master = ctx.createGain();
    master.gain.value = 0.11;
    master.connect(ctx.destination);

    const ding = (freq: number, t0: number, dur: number) => {
      const o = ctx.createOscillator();
      const g = ctx.createGain();
      o.type = "sine";
      o.frequency.setValueAtTime(freq, t0);
      g.gain.setValueAtTime(0, t0);
      g.gain.linearRampToValueAtTime(1, t0 + 0.02);
      g.gain.exponentialRampToValueAtTime(0.01, t0 + dur);
      o.connect(g);
      g.connect(master);
      o.start(t0);
      o.stop(t0 + dur + 0.05);
    };

    const now = ctx.currentTime;
    ding(523.25, now, 0.11);
    ding(659.25, now + 0.055, 0.13);
    ding(783.99, now + 0.1, 0.16);
    ding(1046.5, now + 0.14, 0.2);

    const noise = ctx.createBufferSource();
    const buf = ctx.createBuffer(1, ctx.sampleRate * 0.07, ctx.sampleRate);
    const data = buf.getChannelData(0);
    for (let i = 0; i < data.length; i++) {
      data[i] = (Math.random() * 2 - 1) * Math.exp(-i / (data.length * 0.32));
    }
    noise.buffer = buf;
    const ng = ctx.createGain();
    ng.gain.setValueAtTime(0.055, now + 0.04);
    ng.gain.exponentialRampToValueAtTime(0.001, now + 0.12);
    noise.connect(ng);
    ng.connect(master);
    noise.start(now + 0.04);
    noise.stop(now + 0.18);

    void ctx.resume?.();
    setTimeout(() => void ctx.close(), 700);
  } catch {
    /* autoplay / policy */
  }
}

export default function ScanCashFlourish() {
  const { cashWave, cashVariant, lastTag } = useNfcWs();
  const [visible, setVisible] = useState(false);
  const [burstKey, setBurstKey] = useState(0);

  useEffect(() => {
    if (cashWave === 0) {
      return;
    }
    setBurstKey(cashWave);
    setVisible(true);
    playChaChing();
    const t = window.setTimeout(() => setVisible(false), 1650);
    return () => window.clearTimeout(t);
  }, [cashWave]);

  return (
    <div className="pointer-events-none fixed left-2 top-[4.25rem] z-[55] sm:left-4 sm:top-[4.5rem] md:top-[5.25rem]">
      <AnimatePresence mode="wait">
        {visible ? (
          <motion.div
            key={burstKey}
            className="relative flex flex-col items-start"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0, scale: 0.92, filter: "blur(4px)" }}
            transition={{ duration: 0.4 }}
          >
            <motion.div
              className="absolute -left-8 -top-8 h-40 w-40 rounded-full bg-gradient-to-br from-amber-400/45 via-yellow-200/30 to-bubble-mint/35 blur-2xl"
              initial={{ scale: 0.2, opacity: 0 }}
              animate={{ scale: [0.2, 1.35, 1], opacity: [0, 1, 0.7] }}
              transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
            />

            {Array.from({ length: SPARKS }).map((_, i) => {
              const a = (i / SPARKS) * Math.PI * 2;
              const dist = 56 + (i % 4) * 10;
              return (
                <motion.span
                  key={`s-${i}`}
                  className="absolute left-8 top-9 h-2 w-2 rounded-full bg-gradient-to-br from-yellow-100 to-amber-500 shadow-[0_0_12px_rgba(250,204,21,1)]"
                  initial={{ x: 0, y: 0, opacity: 0, scale: 0 }}
                  animate={{
                    x: Math.cos(a) * dist,
                    y: Math.sin(a) * dist,
                    opacity: [0, 1, 0],
                    scale: [0, 1.3, 0.3],
                  }}
                  transition={{ duration: 0.8, delay: i * 0.018, ease: "easeOut" }}
                />
              );
            })}

            {Array.from({ length: COINS }).map((_, i) => (
              <motion.span
                key={`c-${i}`}
                className="absolute left-8 top-8 text-xl sm:text-2xl"
                initial={{ x: 0, y: 0, opacity: 0, rotate: -30, scale: 0 }}
                animate={{
                  x: (i % 2 === 0 ? 1 : -1) * (36 + i * 12),
                  y: -32 - i * 11,
                  opacity: [0, 1, 0],
                  rotate: i * 35,
                  scale: [0, 1.15, 0.85],
                }}
                transition={{ duration: 0.9, delay: 0.04 + i * 0.035, ease: [0.22, 1, 0.36, 1] }}
              >
                🪙
              </motion.span>
            ))}

            <motion.div
              className="relative flex h-[4.75rem] w-[4.75rem] items-center justify-center sm:h-[5.5rem] sm:w-[5.5rem]"
              initial={{ scale: 0, rotate: -40 }}
              animate={{
                scale: [0, 1.3, 0.92, 1.06, 1],
                rotate: [-40, 12, -6, 3, 0],
              }}
              transition={{ duration: 0.7, ease: [0.34, 1.56, 0.64, 1] }}
            >
              <motion.div
                className="absolute inset-0 rounded-2xl border-2 border-yellow-200/90"
                animate={{
                  boxShadow: [
                    "0 0 25px rgba(250,204,21,0.55), inset 0 0 22px rgba(254,240,138,0.2)",
                    "0 0 50px rgba(0,255,157,0.5), inset 0 0 28px rgba(0,229,255,0.15)",
                    "0 0 28px rgba(250,204,21,0.6), inset 0 0 18px rgba(254,240,138,0.25)",
                  ],
                }}
                transition={{ duration: 1.1, repeat: 2 }}
              />
              <svg
                viewBox="0 0 100 100"
                className="relative z-[1] h-[72%] w-[72%] drop-shadow-[0_0_14px_rgba(250,204,21,0.9)]"
                aria-hidden
              >
                <defs>
                  <linearGradient id="cashGold" x1="0%" y1="0%" x2="100%" y2="100%">
                    <stop offset="0%" stopColor="#fef9c3" />
                    <stop offset="40%" stopColor="#facc15" />
                    <stop offset="100%" stopColor="#a16207" />
                  </linearGradient>
                  <filter id="cashGlow" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="1.2" result="b" />
                    <feMerge>
                      <feMergeNode in="b" />
                      <feMergeNode in="SourceGraphic" />
                    </feMerge>
                  </filter>
                </defs>
                <circle cx="50" cy="50" r="44" fill="url(#cashGold)" filter="url(#cashGlow)" />
                <circle cx="50" cy="50" r="40" fill="none" stroke="#422006" strokeOpacity="0.28" strokeWidth="2" />
                <text
                  x="50"
                  y="64"
                  textAnchor="middle"
                  fill="#713f12"
                  fontSize="54"
                  fontWeight="700"
                  fontFamily="Audiowide, Orbitron, system-ui, sans-serif"
                >
                  $
                </text>
              </svg>
              <motion.div
                className="pointer-events-none absolute inset-0 overflow-hidden rounded-2xl"
                initial={false}
              >
                <motion.div
                  className="absolute inset-y-2 w-2/5 bg-gradient-to-r from-transparent via-white/60 to-transparent skew-x-[-18deg]"
                  initial={{ left: "-40%" }}
                  animate={{ left: "140%" }}
                  transition={{ duration: 0.55, delay: 0.12, ease: "easeInOut" }}
                />
              </motion.div>
            </motion.div>

            <motion.div
              className="relative -mt-0.5 max-w-[12rem] pl-0.5"
              initial={{ opacity: 0, y: 10 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ delay: 0.12, type: "spring", stiffness: 320, damping: 22 }}
            >
              <motion.p
                className="font-display text-[10px] tracking-[0.42em] text-yellow-100 sm:text-[11px]"
                animate={{
                  textShadow: [
                    "0 0 10px rgba(250,204,21,0.95)",
                    "0 0 22px rgba(0,255,157,0.75)",
                    "0 0 12px rgba(250,204,21,0.9)",
                  ],
                }}
                transition={{ duration: 0.75, repeat: 3 }}
              >
                {cashVariant === "vault" ? "VAULT · LOCKED" : "CHA-CHING · HIT"}
              </motion.p>
              {lastTag?.uid ? (
                <motion.p
                  className="mt-1 truncate font-mono text-[10px] font-bold tracking-[0.15em] text-bubble-mint sm:text-xs"
                  initial={{ opacity: 0, x: -6 }}
                  animate={{ opacity: 1, x: 0 }}
                  transition={{ delay: 0.22 }}
                >
                  {lastTag.uid}
                </motion.p>
              ) : null}
            </motion.div>
          </motion.div>
        ) : null}
      </AnimatePresence>
    </div>
  );
}
