import { ChaseEnemy } from '../entities/enemies/ChaseEnemy.js';
import { ShooterEnemy } from '../entities/enemies/ShooterEnemy.js';
import { SwarmerEnemy } from '../entities/enemies/SwarmerEnemy.js';
import { SprayerEnemy } from '../entities/enemies/SprayerEnemy.js';
import { BomberEnemy } from '../entities/enemies/BomberEnemy.js';

const ENEMY_CLASSES = { ChaseEnemy, ShooterEnemy, SwarmerEnemy, SprayerEnemy, BomberEnemy };
const SPAWN_MARGIN = 40;

export class WaveManager {
  constructor(scene, player) {
    this.scene = scene;
    this.player = player;
    this.zones = [];
    this.zoneIndex = 0;
    this.waveIndex = 0;
    this.enemies = [];
    this.active = false;
    this.spriteGroup = scene.physics.add.group();
  }

  load(data) {
    this.zones = data;
  }

  start() {
    this.active = true;
    this._spawnWave();
  }

  get currentZone() { return this.zones[this.zoneIndex]; }
  get currentWave() { return this.currentZone?.waves[this.waveIndex]; }
  get zoneNum() { return this.zoneIndex + 1; }
  get waveNum() { return this.waveIndex + 1; }
  get totalWaves() { return this.currentZone?.waves.length ?? 0; }

  _spawnWave() {
    const wave = this.currentWave;
    if (!wave) return;

    this.scene.events.emit('wave-start', { zone: this.zoneNum, wave: this.waveNum, totalWaves: this.totalWaves });

    wave.enemies.forEach(({ type, count }) => {
      const EnemyClass = ENEMY_CLASSES[type];
      if (!EnemyClass) return;
      for (let i = 0; i < count; i++) {
        const [x, y] = this._edgePosition();
        const enemy = new EnemyClass(this.scene, x, y, this.player);
        this.enemies.push(enemy);
        this.spriteGroup.add(enemy.sprite);
      }
    });
  }

  _edgePosition() {
    const W = this.scene.scale.width;
    const H = this.scene.scale.height;
    const side = Phaser.Math.Between(0, 3);
    switch (side) {
      case 0: return [Phaser.Math.Between(0, W), -SPAWN_MARGIN];
      case 1: return [W + SPAWN_MARGIN, Phaser.Math.Between(0, H)];
      case 2: return [Phaser.Math.Between(0, W), H + SPAWN_MARGIN];
      case 3: return [-SPAWN_MARGIN, Phaser.Math.Between(0, H)];
    }
  }

  update(delta) {
    if (!this.active) return;

    // Prune dead enemies
    this.enemies = this.enemies.filter(e => e.active);

    // Update living enemies
    this.enemies.forEach(e => e.update(delta));

    // Check wave clear
    if (this.enemies.length === 0) {
      this.active = false;
      this.scene.time.delayedCall(1500, () => this._advance());
    }
  }

  _advance() {
    this.waveIndex++;

    if (this.waveIndex >= this.currentZone.waves.length) {
      // All waves cleared — let the player exit to trigger next zone
      this.scene.events.emit('zone-clear', { zone: this.zoneNum });
      this.scene.events.emit('zone-waves-complete');
    } else {
      this.active = true;
      this._spawnWave();
    }
  }

  /** Called by GameScene after the player exits the screen. */
  startNextZone() {
    this.waveIndex = 0;
    this.zoneIndex++;
    if (this.zoneIndex >= this.zones.length) {
      this.scene.events.emit('victory');
      return;
    }
    this.active = true;
    this._spawnWave();
  }

  reset() {
    this.enemies.forEach(e => { if (e.active) e.destroy(); });
    this.enemies = [];
    this.spriteGroup.clear(false, false);
    this.zoneIndex = 0;
    this.waveIndex = 0;
    this.active = false;
  }
}
