/* ============ FX: sounds, confetti, emoji effects ============ */
(function(){
  const { useState, useEffect, useRef } = React;

  /* ---- AudioContext ---- */
  let actx=null;
  function getCtx(){ if(!actx){ try{ actx=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){} } return actx; }
  function blip(freq, dur=0.09, type='square', vol=0.13){
    const ctx=getCtx(); if(!ctx) return;
    if(ctx.state==='suspended') ctx.resume();
    const o=ctx.createOscillator(), g=ctx.createGain();
    o.type=type; o.frequency.value=freq;
    g.gain.setValueAtTime(vol,ctx.currentTime);
    g.gain.exponentialRampToValueAtTime(0.0001,ctx.currentTime+dur);
    o.connect(g); g.connect(ctx.destination);
    o.start(); o.stop(ctx.currentTime+dur);
  }
  const pick=(a)=>a[(Math.random()*a.length)|0];
  function popUp(step){ blip(440+step*60, 0.08); }
  function popDown(){ blip(300,0.07,'square',0.1); }
  function coinSound(){ blip(880,0.06); setTimeout(()=>blip(1320,0.12),60); }
  function levelSound(){ [523,659,784,1046].forEach((f,i)=>setTimeout(()=>blip(f,0.12,'square',0.14),i*90)); }
  function fanfare(){ [523,659,784,1046,784,1046,1318].forEach((f,i)=>setTimeout(()=>blip(f,0.16,'square',0.15),i*110)); }
  const JINGLES=[[523,659,784,1046],[659,523,784,1046,1318],[784,659,523,659,784,1046],[523,587,659,698,784],[1046,784,1046,1318,1568],[392,523,659,784,1046],[659,784,988,784,1318],[880,988,1046,1318,1046,1568]];
  function playJingle(j){ (j||pick(JINGLES)).forEach((f,i)=>setTimeout(()=>blip(f,0.13,'square',0.13),i*92)); }
  function twinkle(){ [1318,1568,2093,1568].forEach((f,i)=>setTimeout(()=>blip(f,0.1,'triangle',0.11),i*70)); }
  function boing(){ const ctx=getCtx(); if(!ctx)return; if(ctx.state==='suspended')ctx.resume();
    const o=ctx.createOscillator(),g=ctx.createGain(); o.type='sine';
    o.frequency.setValueAtTime(640,ctx.currentTime); o.frequency.exponentialRampToValueAtTime(150,ctx.currentTime+0.28);
    g.gain.setValueAtTime(0.15,ctx.currentTime); g.gain.exponentialRampToValueAtTime(0.0001,ctx.currentTime+0.32);
    o.connect(g);g.connect(ctx.destination); o.start(); o.stop(ctx.currentTime+0.32); }
  function silly(){ [700,500,650,450,600,820].forEach((f,i)=>setTimeout(()=>blip(f,0.09,'sawtooth',0.09),i*78)); }
  function party(){ playJingle(); setTimeout(twinkle,200); }
  const SURPRISE_SOUNDS=[playJingle,twinkle,boing,silly,party,coinSound];

  /* ---- victory fanfare: trumpets + drums ---- */
  function trumpet(freq,start,dur=0.3,vol=0.17){
    const ctx=getCtx(); if(!ctx)return; if(ctx.state==='suspended')ctx.resume();
    const now=ctx.currentTime+start;
    const o=ctx.createOscillator(), o2=ctx.createOscillator(), g=ctx.createGain();
    o.type='sawtooth'; o2.type='square'; o.frequency.value=freq; o2.frequency.value=freq*1.005;
    g.gain.setValueAtTime(0.0001,now); g.gain.exponentialRampToValueAtTime(vol,now+0.035);
    g.gain.setValueAtTime(vol,now+dur*0.65); g.gain.exponentialRampToValueAtTime(0.0001,now+dur);
    o.connect(g); o2.connect(g); g.connect(ctx.destination);
    o.start(now); o2.start(now); o.stop(now+dur); o2.stop(now+dur);
  }
  function noiseBurst(dur=0.13,vol=0.22,hp=1500){
    const ctx=getCtx(); if(!ctx)return; if(ctx.state==='suspended')ctx.resume();
    const len=Math.floor(ctx.sampleRate*dur);
    const buf=ctx.createBuffer(1,len,ctx.sampleRate); const d=buf.getChannelData(0);
    for(let i=0;i<len;i++) d[i]=(Math.random()*2-1)*Math.pow(1-i/len,2);
    const src=ctx.createBufferSource(); src.buffer=buf;
    const g=ctx.createGain(); g.gain.value=vol;
    const f=ctx.createBiquadFilter(); f.type='highpass'; f.frequency.value=hp;
    src.connect(f); f.connect(g); g.connect(ctx.destination); src.start();
  }
  function kick(t=0){ const ctx=getCtx(); if(!ctx)return; if(ctx.state==='suspended')ctx.resume();
    const now=ctx.currentTime+t; const o=ctx.createOscillator(), g=ctx.createGain();
    o.frequency.setValueAtTime(170,now); o.frequency.exponentialRampToValueAtTime(48,now+0.14);
    g.gain.setValueAtTime(0.45,now); g.gain.exponentialRampToValueAtTime(0.001,now+0.19);
    o.connect(g); g.connect(ctx.destination); o.start(now); o.stop(now+0.2); }
  function snare(t=0){ setTimeout(()=>noiseBurst(0.12,0.20,1600),t*1000); }
  function victoryFanfare(){
    const ctx=getCtx(); if(!ctx)return; if(ctx.state==='suspended')ctx.resume();
    [[392,0,.15],[523,.15,.15],[659,.30,.16],[784,.46,.42],[784,.94,.14],[1046,1.09,.85]].forEach(([f,s,d])=>trumpet(f,s,d));
    trumpet(659,1.09,.85,.11); trumpet(523,1.09,.85,.09);
    kick(0); kick(.30); kick(.46); kick(.94); kick(1.09);
    snare(.15); snare(.46); snare(.78);
    for(let i=0;i<7;i++) snare(.74+i*0.045);
    setTimeout(()=>noiseBurst(0.5,0.26,2200),1090);
    setTimeout(()=>noiseBurst(0.5,0.18,1200),1090);
  }

  /* ---- confetti ---- */
  const COLORS=['#2fe07a','#1fd9e6','#ffd23f','#ff4d9d','#b06bff','#ff9a3f'];
  let cf={canvas:null,ctx:null,parts:[],raf:null};
  function initConfetti(){
    cf.canvas=document.getElementById('confetti'); if(!cf.canvas) return;
    cf.ctx=cf.canvas.getContext('2d'); resizeConfetti();
    window.addEventListener('resize',resizeConfetti);
  }
  function resizeConfetti(){ if(!cf.canvas)return; cf.canvas.width=innerWidth; cf.canvas.height=innerHeight; }
  function fireConfetti(amount=90){
    if(!cf.ctx){ initConfetti(); if(!cf.ctx) return; }
    for(let i=0;i<amount;i++){
      cf.parts.push({x:innerWidth/2+(Math.random()-0.5)*120,y:innerHeight*0.42,vx:(Math.random()-0.5)*11,vy:-(Math.random()*13+6),g:0.32+Math.random()*0.12,s:6+Math.random()*7,rot:Math.random()*Math.PI,vr:(Math.random()-0.5)*0.3,c:COLORS[(Math.random()*COLORS.length)|0],life:1});
    }
    if(!cf.raf) loopConfetti();
  }
  function loopConfetti(){
    const {ctx}=cf; ctx.clearRect(0,0,cf.canvas.width,cf.canvas.height);
    cf.parts=cf.parts.filter(p=>p.life>0);
    cf.parts.forEach(p=>{
      p.vy+=p.g; p.x+=p.vx; p.y+=p.vy; p.rot+=p.vr;
      if(p.y>innerHeight*0.5) p.life-=0.012;
      ctx.save(); ctx.globalAlpha=Math.max(0,p.life);
      ctx.translate(p.x,p.y); ctx.rotate(p.rot);
      ctx.fillStyle=p.c; ctx.fillRect(-p.s/2,-p.s/2,p.s,p.s); ctx.restore();
    });
    if(cf.parts.length){ cf.raf=requestAnimationFrame(loopConfetti); }
    else { cancelAnimationFrame(cf.raf); cf.raf=null; ctx.clearRect(0,0,cf.canvas.width,cf.canvas.height); }
  }

  /* ---- emoji effects ---- */
  const EMOJIS=['🍾','🥤','🫙','🪙','💰','♻️','🌍','🌱','⭐','✨','🎉','🎊','💚','🤩','🥳','🦄','🌈'];
  const COINS=['🪙','💰','💵','🤑'];
  const SPARKS=['⭐','✨','🌟','💫','🌈'];
  const PRAISE=['מהמם!','וואו!','אלופים!','כל הכבוד!','איזה כיף!','סחתיין!','יש!','מגניב!','אלופי על!','ירוקים!','פצצה!','חמודים!'];
  function spawnFx(content,cls,style,life){
    const s=document.createElement('div'); s.className='fx '+cls; s.textContent=content;
    Object.assign(s.style,style); document.body.appendChild(s); setTimeout(()=>s.remove(), life||2200);
  }
  function emojiRain(pool,n=16){
    for(let i=0;i<n;i++){ const dur=1600+Math.random()*1500;
      spawnFx(pick(pool),'fx-fall',{left:(Math.random()*100)+'vw',top:'-50px',fontSize:(22+Math.random()*24)+'px',animationDuration:dur+'ms',animationDelay:(Math.random()*500)+'ms'}, dur+700); }
  }
  function emojiBurst(pool,n=16,x,y){
    x=(x==null)?innerWidth/2:x; y=(y==null)?innerHeight*0.45:y;
    for(let i=0;i<n;i++){ const a=Math.random()*Math.PI*2, dist=70+Math.random()*180, dur=850+Math.random()*550;
      const s=document.createElement('div'); s.className='fx fx-burst'; s.textContent=pick(pool);
      s.style.left=x+'px'; s.style.top=y+'px'; s.style.fontSize=(20+Math.random()*22)+'px';
      s.style.setProperty('--dx',(Math.cos(a)*dist)+'px'); s.style.setProperty('--dy',(Math.sin(a)*dist-30)+'px');
      s.style.setProperty('--r',(Math.random()*720-360)+'deg'); s.style.animationDuration=dur+'ms';
      document.body.appendChild(s); setTimeout(()=>s.remove(),dur+200); }
  }
  function bubbles(n=14){
    for(let i=0;i<n;i++){ const dur=2200+Math.random()*1600;
      spawnFx(pick(['🫧','💧','✨','⭐','🌟','💚']),'fx-bubble',{left:(Math.random()*100)+'vw',bottom:'-40px',fontSize:(16+Math.random()*22)+'px',animationDuration:dur+'ms',animationDelay:(Math.random()*500)+'ms'}, dur+700); }
  }
  function praise(text,color){
    const p=document.createElement('div'); p.className='praise'; p.textContent=text||pick(PRAISE);
    p.style.left=(28+Math.random()*44)+'vw'; p.style.top=(32+Math.random()*22)+'vh';
    p.style.fontSize=(2+Math.random()*1.5)+'rem'; p.style.color=color||pick(COLORS);
    document.body.appendChild(p); setTimeout(()=>p.remove(),1700);
  }
  function screenShake(){
    const a=document.querySelector('.app')||document.getElementById('root'); if(!a)return;
    a.classList.remove('shake'); void a.offsetWidth; a.classList.add('shake'); setTimeout(()=>a.classList.remove('shake'),650);
  }
  const FX=[()=>emojiBurst(EMOJIS,18),()=>emojiRain(EMOJIS,18),()=>{praise();emojiBurst(SPARKS,12);},()=>bubbles(16),()=>fireConfetti(80),()=>emojiRain(COINS,18),()=>emojiBurst(SPARKS,20),()=>{screenShake();emojiBurst(['🎉','🎊','🥳'],16);},()=>{fireConfetti(60);emojiRain(SPARKS,12);},()=>{praise();bubbles(12);}];
  function surpriseSmall(muted){ if(!muted) pick(SURPRISE_SOUNDS)(); pick([()=>praise(),()=>emojiBurst(EMOJIS,9),()=>bubbles(7),()=>emojiBurst(SPARKS,10)])(); }
  function surpriseBig(muted){ pick(FX)(); if(Math.random()<0.45) pick(FX)(); praise(); if(!muted){ Math.random()<0.45?fanfare():playJingle(); } }
  function goalBlast(muted){
    const blast=()=>{ fireConfetti(170); emojiRain(['🎉','🎊','🥳','🤩','🌟','🏆','🦄','💚'],32); };
    blast(); [350,800,1400,2100,3000,3900].forEach(t=>setTimeout(blast,t));
    if(!muted) victoryFanfare();
  }

  /* ---- AnimatedNumber component ---- */
  function AnimatedNumber({value, className, prefix=true}){
    const [disp,setDisp]=useState(value); const ref=useRef(value);
    useEffect(()=>{
      const from=ref.current, to=value, dur=420, t0=performance.now(); let raf;
      const tick=(t)=>{ const k=Math.min(1,(t-t0)/dur); const e=1-Math.pow(1-k,3); setDisp(from+(to-from)*e);
        if(k<1) raf=requestAnimationFrame(tick); else { setDisp(to); ref.current=to; } };
      raf=requestAnimationFrame(tick); return ()=>cancelAnimationFrame(raf);
    },[value]);
    return <span className={className} dir="ltr">{prefix && <span className="sh">₪</span>}{disp.toFixed(2)}</span>;
  }

  Object.assign(window, {
    initConfetti, fireConfetti, emojiBurst, emojiRain, bubbles, praise, screenShake,
    popUp, popDown, coinSound, levelSound, fanfare, playJingle, twinkle, boing, silly,
    victoryFanfare, surpriseSmall, surpriseBig, goalBlast, AnimatedNumber, FX_COLORS:COLORS,
    SPARKS, EMOJIS, COINS
  });
})();
