(() => {
  const canvas = document.getElementById('game');
  const ctx = canvas.getContext('2d');
  const scoreEl = document.getElementById('score');
  const comboLabelEl = document.getElementById('comboLabel');
  const livesHeartsEl = document.getElementById('livesHearts');
  const overlayEl = document.getElementById('overlay');
  const finalScoreEl = document.getElementById('finalScore');
  const finalStatsEl = document.getElementById('finalStats');
  const restartBtn = document.getElementById('restartBtn');

  const BASKET_WIDTH = 130;
  const BASKET_HEIGHT = 30;
  const BASKET_BOTTOM_GAP = 70; // distance entre le panier et le bas de l'ecran
  const ITEM_SIZE = 46;
  const START_LIVES = 5;
  const BASE_SPEED = 2.6;
  const MAX_SPEED = 6.5;

  const KIND_STYLE = {
    like: { emoji: '❤️', points: 1, life: 0, color: '#ff2d55' },
    gift: { emoji: '🎁', points: 10, life: 1, color: '#ffd23f' },
    follow: { emoji: '⭐', points: 50, life: 0, color: '#3fd0ff' }
  };

  let dpr = Math.min(window.devicePixelRatio || 1, 2);
  let width, height;
  let basketX, basketPrevX, basketTilt, trail;
  let items, particles, popups;
  let score, combo, comboMultiplier, bestCombo, lives, gameOver, shakeAmount, elapsed, caughtCount;

  function resize() {
    width = window.innerWidth;
    height = window.innerHeight;
    canvas.width = width * dpr;
    canvas.height = height * dpr;
    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    if (basketX === undefined) basketX = width / 2;
  }
  window.addEventListener('resize', resize);

  function basketLineY() {
    return height - BASKET_BOTTOM_GAP;
  }

  function reset() {
    basketX = width / 2;
    basketPrevX = basketX;
    basketTilt = 0;
    trail = [];
    items = [];
    particles = [];
    popups = [];
    score = 0;
    combo = 0;
    comboMultiplier = 1;
    bestCombo = 0;
    lives = START_LIVES;
    gameOver = false;
    shakeAmount = 0;
    elapsed = 0;
    caughtCount = 0;

    scoreEl.textContent = '0';
    comboLabelEl.textContent = '';
    renderLives();
    overlayEl.classList.add('hidden');
  }

  function renderLives() {
    livesHeartsEl.innerHTML = '';
    for (let i = 0; i < lives; i++) {
      const span = document.createElement('span');
      span.textContent = '❤️';
      livesHeartsEl.appendChild(span);
    }
  }

  function bumpScoreUI() {
    scoreEl.classList.remove('bump');
    void scoreEl.offsetWidth;
    scoreEl.classList.add('bump');
  }

  function addPopup(x, y, text, color) {
    popups.push({ x, y, text, color, life: 1 });
  }

  function spawnParticles(x, y, color, count) {
    for (let i = 0; i < count && particles.length < 160; i++) {
      const angle = Math.random() * Math.PI * 2;
      const spd = 1.5 + Math.random() * 4.5;
      particles.push({
        x, y,
        vx: Math.cos(angle) * spd,
        vy: Math.sin(angle) * spd - 1.5,
        color,
        size: 2 + Math.random() * 3,
        life: 1,
        gravity: 0.18
      });
    }
  }

  function shake(amount) {
    shakeAmount = Math.max(shakeAmount, amount);
  }

  function currentSpeed() {
    return Math.min(MAX_SPEED, BASE_SPEED + elapsed / 1800);
  }

  function spawnItem(kind, label) {
    if (gameOver) return;
    items.push({
      kind,
      label,
      baseX: 40 + Math.random() * (width - 80),
      x: 0,
      y: -ITEM_SIZE,
      speed: currentSpeed() + Math.random() * 1.2,
      swayAmp: 18 + Math.random() * 26,
      swayFreq: 0.015 + Math.random() * 0.015,
      swayPhase: Math.random() * Math.PI * 2,
      rotation: 0,
      vRotation: (Math.random() - 0.5) * 0.06,
      scale: 0
    });
  }

  function loseLife() {
    lives -= 1;
    combo = 0;
    comboMultiplier = 1;
    comboLabelEl.textContent = '';
    const hearts = livesHeartsEl.children;
    if (hearts.length) hearts[hearts.length - 1].classList.add('lost');
    shake(7);
    SFX.miss();
    setTimeout(renderLives, 380);
    if (lives <= 0) endGame();
  }

  function catchItem(item) {
    const style = KIND_STYLE[item.kind];
    combo += 1;
    bestCombo = Math.max(bestCombo, combo);
    caughtCount += 1;
    comboMultiplier = 1 + Math.min(combo, 15) * 0.15;
    const gained = Math.round(style.points * comboMultiplier);
    score += gained;
    scoreEl.textContent = String(score);
    bumpScoreUI();
    comboLabelEl.textContent = combo > 2 ? `Combo x${combo}` : '';

    addPopup(item.x, basketLineY() - 10, `+${gained}`, '#fff');
    spawnParticles(item.x, basketLineY() - 10, style.color, item.kind === 'follow' ? 26 : 14);

    if (item.kind === 'gift') { SFX.gift(); shake(4); }
    else if (item.kind === 'follow') { SFX.follow(); shake(3); }
    else SFX.tick();
  }

  function update() {
    if (shakeAmount > 0.05) shakeAmount *= 0.85; else shakeAmount = 0;
    if (gameOver) return;

    elapsed += 16.7;

    basketTilt += ((basketX - basketPrevX) * 0.02 - basketTilt) * 0.2;
    basketPrevX = basketX;
    trail.push({ x: basketX, y: basketLineY() });
    if (trail.length > 6) trail.shift();

    for (let i = items.length - 1; i >= 0; i--) {
      const item = items[i];
      item.scale = Math.min(1, item.scale + 0.08);
      item.y += item.speed;
      item.swayPhase += item.swayFreq;
      item.x = item.baseX + Math.sin(item.swayPhase) * item.swayAmp;
      item.rotation += item.vRotation;

      const basketY = basketLineY();
      const withinX = item.x + ITEM_SIZE * 0.32 > basketX - BASKET_WIDTH / 2 &&
                      item.x - ITEM_SIZE * 0.32 < basketX + BASKET_WIDTH / 2;
      const withinY = item.y + ITEM_SIZE / 2 > basketY - BASKET_HEIGHT &&
                      item.y - ITEM_SIZE / 2 < basketY + BASKET_HEIGHT * 0.6;

      if (withinX && withinY) {
        catchItem(item);
        items.splice(i, 1);
        continue;
      }

      if (item.y - ITEM_SIZE / 2 > height) {
        const style = KIND_STYLE[item.kind];
        spawnParticles(item.x, height - 6, style.color, 8);
        if (style.life > 0) {
          loseLife();
        } else {
          combo = 0;
          comboMultiplier = 1;
          comboLabelEl.textContent = '';
        }
        items.splice(i, 1);
      }
    }

    for (let i = particles.length - 1; i >= 0; i--) {
      const p = particles[i];
      p.vy += p.gravity;
      p.x += p.vx;
      p.y += p.vy;
      p.life -= 0.025;
      if (p.life <= 0) particles.splice(i, 1);
    }

    for (let i = popups.length - 1; i >= 0; i--) {
      const p = popups[i];
      p.y -= 0.8;
      p.life -= 0.018;
      if (p.life <= 0) popups.splice(i, 1);
    }
  }

  function endGame() {
    gameOver = true;
    finalScoreEl.textContent = `Score : ${score}`;
    finalStatsEl.textContent = `${caughtCount} objets attrapés • meilleur combo x${bestCombo}`;
    overlayEl.classList.remove('hidden');
  }

  function drawBackground() {
    const grad = ctx.createLinearGradient(0, 0, 0, height);
    grad.addColorStop(0, '#0e0b26');
    grad.addColorStop(0.6, '#161244');
    grad.addColorStop(1, '#1c1550');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, width, height);

    ctx.fillStyle = 'rgba(255,255,255,0.5)';
    for (let i = 0; i < 30; i++) {
      const x = (i * 137.5) % width;
      const y = (i * 97.3 + elapsed * 0.02) % height;
      ctx.globalAlpha = 0.15 + (Math.sin(i + elapsed * 0.001) + 1) * 0.1;
      ctx.beginPath();
      ctx.arc(x, y, 1.4, 0, Math.PI * 2);
      ctx.fill();
    }
    ctx.globalAlpha = 1;
  }

  function drawStage() {
    const y = basketLineY() + BASKET_HEIGHT * 0.6;
    const grad = ctx.createLinearGradient(0, y, 0, height);
    grad.addColorStop(0, 'rgba(80, 60, 130, 0.5)');
    grad.addColorStop(1, 'rgba(20, 15, 45, 0.1)');
    ctx.fillStyle = grad;
    ctx.fillRect(0, y, width, height - y);
    ctx.fillStyle = 'rgba(255,255,255,0.25)';
    ctx.fillRect(0, y, width, 2);
  }

  const BASKET_HUE = 195;

  function drawBasket() {
    for (let i = 0; i < trail.length; i++) {
      const t = trail[i];
      ctx.globalAlpha = (i / trail.length) * 0.25;
      ctx.fillStyle = ToyBox.hsl(BASKET_HUE, 78, 62);
      ctx.beginPath();
      ctx.roundRect(t.x - BASKET_WIDTH / 2, basketLineY() - BASKET_HEIGHT, BASKET_WIDTH, BASKET_HEIGHT, 10);
      ctx.fill();
    }
    ctx.globalAlpha = 1;

    ctx.save();
    ctx.translate(basketX, basketLineY() - BASKET_HEIGHT / 2);
    ctx.rotate(basketTilt);
    ctx.shadowColor = ToyBox.hsl(BASKET_HUE, 80, 65);
    ctx.shadowBlur = 18;
    ToyBox.drawToyBlock(ctx, -BASKET_WIDTH / 2, -BASKET_HEIGHT / 2, BASKET_WIDTH, BASKET_HEIGHT, BASKET_HUE, { depth: 9 });
    ctx.restore();
  }

  function draw() {
    ctx.save();
    if (shakeAmount > 0) {
      ctx.translate((Math.random() - 0.5) * shakeAmount, (Math.random() - 0.5) * shakeAmount);
    }

    drawBackground();
    drawStage();

    for (const item of items) {
      ctx.save();
      ctx.globalAlpha = Math.min(1, item.scale + 0.2);
      ctx.translate(item.x, item.y);
      ctx.rotate(item.rotation);
      ctx.scale(item.scale, item.scale);
      ctx.font = `${ITEM_SIZE}px sans-serif`;
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(KIND_STYLE[item.kind].emoji, 0, 0);
      ctx.restore();
    }

    drawBasket();

    for (const p of particles) {
      ctx.globalAlpha = Math.max(0, p.life);
      ctx.fillStyle = p.color;
      ctx.beginPath();
      ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
      ctx.fill();
      ctx.globalAlpha = 1;
    }

    ctx.textAlign = 'center';
    for (const p of popups) {
      ctx.globalAlpha = Math.max(0, p.life);
      ctx.fillStyle = p.color;
      ctx.font = 'bold 20px "Baloo 2", Arial, sans-serif';
      ctx.fillText(p.text, p.x, p.y);
      ctx.globalAlpha = 1;
    }

    ctx.restore();
  }

  function loop() {
    update();
    draw();
    requestAnimationFrame(loop);
  }

  function movePointer(clientX) {
    basketX = Math.max(BASKET_WIDTH / 2, Math.min(width - BASKET_WIDTH / 2, clientX));
  }

  window.addEventListener('pointermove', (e) => { SFX.unlock(); movePointer(e.clientX); });
  window.addEventListener('keydown', (e) => {
    const step = 45;
    if (e.code === 'ArrowLeft') movePointer(basketX - step);
    if (e.code === 'ArrowRight') movePointer(basketX + step);
  });

  restartBtn.addEventListener('click', reset);

  TikTokEvents.on('like', (data) => spawnItem('like', data.uniqueId));
  TikTokEvents.on('gift', (data) => spawnItem('gift', data.uniqueId));
  TikTokEvents.on('follow', (data) => spawnItem('follow', data.uniqueId));

  resize();
  reset();
  requestAnimationFrame(loop);
})();
