// Game — the playable scene. The template ships a simple
// "catch good, dodge bad" mechanic so it runs out of the box.
// Replace the marked section with your own mechanic.
window.GameScene = class GameScene extends Phaser.Scene {
  constructor() { super('Game'); }

  create() {
    const W = window.GAME.WIDTH, H = window.GAME.HEIGHT;
    const T = window.GAME.tuning;

    // Background
    if (this.textures.exists('bg')) {
      this.add.image(W / 2, H / 2, 'bg').setDisplaySize(W, H);
    } else {
      this.cameras.main.setBackgroundColor(window.GAME.BG_COLOR);
    }

    // State
    this.score = 0;
    this.lives = T.startLives;
    this.fallSpeed = T.fallSpeed;
    this.spawnEvery = T.spawnEveryMs;
    this.gameOver = false;

    // HUD
    this.scoreText = this.add.text(16, 14, 'SCORE 0', {
      fontFamily: 'Arial', fontSize: '24px', fontStyle: 'bold', color: '#fff',
      stroke: '#000', strokeThickness: 4,
    }).setDepth(500);
    this.livesText = this.add.text(W - 16, 14, this._hearts(), {
      fontFamily: 'Arial', fontSize: '24px', color: '#ff4d4d',
      stroke: '#000', strokeThickness: 4,
    }).setOrigin(1, 0).setDepth(500);

    // =========================================================
    // === YOUR MECHANIC HERE ===  (CATNIP CATCH)
    // The cat (player) at the bottom catches falling FISH (+1)
    // and must dodge falling BOMBS (-1 life). Missing a fish also
    // costs a life. Fall speed + spawn rate escalate over time.
    // 3 lives -> game over.
    // =========================================================

    // Player — the cat
    const playerTex = this.textures.exists('hero') ? 'hero' : this._makeTri('hero', 0x8a8a99);
    this.player = this.physics.add.image(W / 2, H - 90, playerTex);
    this.player.setCollideWorldBounds(true);
    this._fit(this.player, 84);

    // Falling items as physics groups (groups recycle = pooling).
    this.goodGroup = this.physics.add.group();
    this.badGroup = this.physics.add.group();

    this.physics.add.overlap(this.player, this.goodGroup, (p, item) => this._collect(item), null, this);
    this.physics.add.overlap(this.player, this.badGroup, (p, item) => this._hit(item), null, this);

    // Spawning + difficulty ramp
    this.spawnTimer = this.time.addEvent({ delay: this.spawnEvery, loop: true, callback: () => this._spawn() });
    this.time.addEvent({
      delay: T.rampEveryMs, loop: true, callback: () => {
        this.fallSpeed = Math.min(T.fallSpeedMax, this.fallSpeed + 50);
        this.spawnEvery = Math.max(T.spawnMinMs, this.spawnEvery - 90);
        this.spawnTimer.delay = this.spawnEvery;
      },
    });

    // ---- input: keyboard + pointer/touch ----
    this.cursors = this.input.keyboard.createCursorKeys();
    this.keys = this.input.keyboard.addKeys('A,D');
    this.pointerTargetX = null;
    this.input.on('pointermove', (p) => { if (p.isDown || this.sys.game.device.input.touch) this.pointerTargetX = p.x; });
    this.input.on('pointerdown', (p) => { this.pointerTargetX = p.x; });

    // Music
    window.Audio.startMusic();

    // Mute toggle (M)
    this.input.keyboard.on('keydown-M', () => window.Audio.toggleMute());

    this.events.once('shutdown', () => window.Audio.stopMusic());
  }

  update(time, delta) {
    if (this.gameOver) return;
    const dt = Math.min(delta, 32) / 1000; // clamp delta-time
    const T = window.GAME.tuning;
    const W = window.GAME.WIDTH, H = window.GAME.HEIGHT;

    // Player movement
    let vx = 0;
    if (this.cursors.left.isDown || this.keys.A.isDown) vx = -T.playerSpeed;
    else if (this.cursors.right.isDown || this.keys.D.isDown) vx = T.playerSpeed;
    if (vx !== 0) {
      this.player.setVelocityX(vx);
      this.pointerTargetX = null;
      if (time % 200 < 16) window.Audio.sfx('move');
    } else if (this.pointerTargetX !== null) {
      const dx = this.pointerTargetX - this.player.x;
      this.player.setVelocityX(Phaser.Math.Clamp(dx * 12, -T.playerSpeed, T.playerSpeed));
      if (Math.abs(dx) < 4) this.player.setVelocityX(0);
    } else {
      this.player.setVelocityX(0);
    }

    // Recycle items that fell off the bottom; missing a GOOD costs a life.
    this.goodGroup.getChildren().forEach((item) => {
      if (item.active && item.y > H + 40) {
        this._kill(item, this.goodGroup);
        this._loseLife(true);
      }
    });
    this.badGroup.getChildren().forEach((item) => {
      if (item.active && item.y > H + 40) this._kill(item, this.badGroup);
    });
  }

  // ---- mechanic helpers ----
  _spawn() {
    if (this.gameOver) return;
    const W = window.GAME.WIDTH;
    const x = Phaser.Math.Between(40, W - 40);
    const isBad = Math.random() < 0.32;
    const group = isBad ? this.badGroup : this.goodGroup;
    const tex = isBad
      ? (this.textures.exists('bad') ? 'bad' : this._makeTri('bad', 0xff5555))
      : (this.textures.exists('good') ? 'good' : this._makeTri('good', 0xffd166));

    const item = group.get(x, -40, tex);
    if (!item) return;
    item.setActive(true).setVisible(true);
    if (item.body) item.body.enable = true;
    this._fit(item, 54);
    item.setVelocity(0, this.fallSpeed);
    item.setAngularVelocity(isBad ? 120 : 40);
    // spin/scale-in tween (no linear pop)
    item.setScale(item.scale * 0.4);
    this.tweens.add({ targets: item, scale: item.scale / 0.4, duration: 180, ease: 'Back.easeOut' });
  }

  _collect(item) {
    if (!item.active) return;
    this.score += 1;
    this.scoreText.setText('SCORE ' + this.score);
    Juice.burstParticles(this, item.x, item.y, 0xffd166);
    Juice.squashStretch(this, this.player, 0.3);
    Juice.scorePopup(this, item.x, item.y - 10, '+1', '#ffd166');
    window.Audio.sfx('catch');
    this._kill(item, this.goodGroup);
  }

  _hit(item) {
    if (!item.active) return;
    Juice.screenShake(this, 220, 0.016);
    Juice.flash(this, 110, [255, 80, 80]);
    Juice.hitStop(this, 70);
    Juice.burstParticles(this, item.x, item.y, 0xff5555, 20);
    window.Audio.sfx('hit');
    this._kill(item, this.badGroup);
    this._loseLife(false);
  }

  _loseLife(missed) {
    this.lives -= 1;
    this.livesText.setText(this._hearts());
    if (missed) window.Audio.sfx('miss');
    Juice.squashStretch(this, this.livesText, 0.4, 160);
    if (this.lives <= 0) this.endGame();
  }

  _kill(item, group) {
    item.setActive(false).setVisible(false);
    item.setAngularVelocity(0);
    if (item.body) { item.body.enable = false; item.setVelocity(0, 0); }
    item.x = -100; item.y = -100;
  }

  endGame() {
    if (this.gameOver) return;
    this.gameOver = true;
    this.spawnTimer.remove();
    window.Audio.sfx('lose');
    window.Audio.stopMusic();
    Juice.flash(this, 200, [255, 255, 255]);
    this.cameras.main.fade(500, 0, 0, 0);
    this.time.delayedCall(520, () => this.scene.start('GameOver', { score: this.score }));
  }

  // ---- utilities ----
  _hearts() { return '♥'.repeat(Math.max(0, this.lives)); }

  _fit(obj, target) {
    const max = Math.max(obj.width, obj.height) || target;
    obj.setScale(target / max);
  }

  // Themed fallback art drawn with vector graphics. Used only when
  // the fal.ai PNGs are not present (e.g. art not generated yet).
  // Re-run tools/gen-assets.mjs and these are replaced automatically.
  _makeTri(key, _color) {
    if (this.textures.exists(key)) return key;
    const g = this.add.graphics();
    const S = 80;
    if (key === 'hero') {
      // grey tabby cat catcher
      g.fillStyle(0x8a8a99, 1);
      g.fillRoundedRect(10, 24, 60, 50, 16);          // head/body
      g.fillTriangle(12, 28, 26, 6, 32, 30);          // left ear
      g.fillTriangle(68, 28, 54, 6, 48, 30);          // right ear
      g.fillStyle(0xff9bbf, 1);
      g.fillTriangle(18, 22, 26, 12, 30, 26);         // inner ear
      g.fillTriangle(62, 22, 54, 12, 50, 26);
      g.fillStyle(0x1a1a26, 1);
      g.fillCircle(30, 46, 6); g.fillCircle(50, 46, 6); // eyes
      g.fillStyle(0xff9bbf, 1);
      g.fillTriangle(36, 54, 44, 54, 40, 60);          // nose
    } else if (key === 'good') {
      // plump orange fish
      g.fillStyle(0xff8a3d, 1);
      g.fillEllipse(40, 40, 56, 34);                   // body
      g.fillTriangle(64, 40, 78, 26, 78, 54);          // tail
      g.fillStyle(0xfff1d6, 1);
      g.fillEllipse(34, 42, 30, 18);                   // belly
      g.fillStyle(0x1a1a26, 1);
      g.fillCircle(26, 36, 4);                          // eye
    } else if (key === 'bad') {
      // round black bomb with fuse
      g.fillStyle(0x222230, 1);
      g.fillCircle(40, 46, 26);                         // body
      g.fillStyle(0x44445a, 1);
      g.fillRect(46, 16, 8, 12);                        // neck
      g.lineStyle(4, 0x8a6a2a, 1);
      g.beginPath(); g.moveTo(52, 16); g.lineTo(62, 6); g.strokePath(); // fuse
      g.fillStyle(0xffcc33, 1);
      g.fillCircle(64, 5, 5);                           // spark
      g.fillStyle(0xffffff, 0.5);
      g.fillCircle(32, 38, 6);                          // highlight
    } else {
      g.fillStyle(0x66ccff, 1);
      g.fillRoundedRect(8, 8, 64, 64, 14);
    }
    g.generateTexture(key, S, S);
    g.destroy();
    return key;
  }
};
