import { playMusic, stopMusic } from '../../audio.js';

export default class CodeBugInvaders extends Phaser.Scene {
    constructor() { super({ key: 'CodeBugInvaders' }); }

    preload() {
        this.load.json('cbiConfig', 'src/games/code-bug-invaders/config.json');
        this.load.audio('cbiMusic', 'assets/music/02-code-bug-invaders.mp3');
        this.load.audio('cbiComplete', 'assets/fx/complete.mp3');
        this.load.audio('cbifire', 'assets/fx/fire.mp3');
        this.load.audio('cbilaser', 'assets/fx/laser.mp3');
        this.load.audio('cbideath', 'assets/fx/death.mp3');
        this.load.audio('cbibugdeath', 'assets/fx/short_death.mp3');
    }

    init(data) {
        this.globalLives = data.lives;
        this.level = data.level || 1;
        this.gameActive = false;
    }

    create() {
        const all = this.cache.json.get('cbiConfig');
        const lvl = String(this.level);
        this.cfg = all.levels ? (all.levels[lvl] ?? all.levels['1']) : all;
        this.bugs = [];
        this.playerBullets = [];
        this.bugBullets = [];
        this.bugsHit = 0;
        this.gameActive = true;
        this.formationDir = 1; // 1 = right, -1 = left
        this.formationX = 0;
        this.formationY = 0;
        this.bugFireTimer = this.cfg.bugFireInterval;

        playMusic(this, 'cbiMusic');

        this._buildBackground();
        this._buildBugs();
        this._buildPlayer();
        this.mainGfx = this.add.graphics();
        this._buildHUD();
        this._setupInput();
    }

    shutdown() {
        stopMusic(this);
    }

    _buildBackground() {
        const bg = this.add.graphics();
        bg.fillStyle(0x000011);
        bg.fillRect(0, 0, 1600, 900);
        for (let i = 0; i < 150; i++) {
            bg.fillStyle(0xffffff, Math.random() * 0.7 + 0.1);
            bg.fillRect(Phaser.Math.Between(0, 1599), Phaser.Math.Between(0, 899), 2, 2);
        }
        this.add.text(800, 15, 'CODE BUG INVADERS', {
            fontSize: '20px', fontFamily: 'monospace', color: '#00ff88', alpha: 0.7,
        }).setOrigin(0.5, 0);
    }

    _buildBugs() {
        const { cols, rows, bugSpacingX, bugSpacingY, startX, startY } = this.cfg;
        const colors = [0xff2222, 0xff8800, 0xffff00, 0x00ff44];
        for (let r = 0; r < rows; r++) {
            for (let c = 0; c < cols; c++) {
                this.bugs.push({
                    col: c, row: r,
                    x: startX + c * bugSpacingX,
                    y: startY + r * bugSpacingY,
                    alive: true,
                    color: colors[r % colors.length],
                    frame: 0,
                });
            }
        }
    }

    _buildPlayer() {
        this.player = { x: 800, y: 845, alive: true };
    }

    _buildHUD() {
        this.livesText = this.add.text(800, 40, '♥ '.repeat(this.globalLives).trim(), {
            fontSize: '24px', fontFamily: 'monospace', color: '#ff4444',
        }).setOrigin(0.5, 0);
        this.bugsText = this.add.text(1580, 40, '', {
            fontSize: '22px', fontFamily: 'monospace', color: '#00ff88',
        }).setOrigin(1, 0);
    }

    _setupInput() {
        this.cursors = this.input.keyboard.createCursorKeys();
        this.keyA = this.input.keyboard.addKey('A');
        this.keyAPressed = false;
    }

    update(time, delta) {
        if (!this.gameActive) return;
        const dt = delta / 1000;

        this._movePlayer(dt);
        this._moveFormation(dt);
        this._moveProjectiles(dt);
        this._handleBugFire(delta);
        this._checkCollisions();
        this._checkWinLose();
        this._draw();
    }

    _movePlayer(dt) {
        if (!this.player.alive) return;
        const speed = this.cfg.playerSpeed;
        if (this.cursors.left.isDown) this.player.x -= speed * dt;
        if (this.cursors.right.isDown) this.player.x += speed * dt;
        this.player.x = Phaser.Math.Clamp(this.player.x, 50, 1550);

        if (this.keyA.isDown && !this.keyAPressed) {
            this.keyAPressed = true;
            // Limit to 2 bullets at once
            if (this.playerBullets.length < 2) {
                this.playerBullets.push({ x: this.player.x, y: this.player.y - 20 });
                const snd = this.sound.add('cbifire', { volume: 0.6 });
                snd.once('complete', () => snd.destroy());
                snd.play();
            }
        }
        if (!this.keyA.isDown) this.keyAPressed = false;
    }

    _moveFormation(dt) {
        const aliveBugs = this.bugs.filter(b => b.alive);
        if (aliveBugs.length === 0) return;

        // Speed scales up as fewer bugs remain
        const speedScale = 1 + (1 - aliveBugs.length / (this.cfg.cols * this.cfg.rows)) * 2.5;
        const move = this.cfg.formationSpeed * speedScale * dt * this.formationDir;

        // Check bounds first
        const { rightBound, leftBound } = this.cfg;
        let minX = Infinity, maxX = -Infinity;
        aliveBugs.forEach(b => { minX = Math.min(minX, b.x); maxX = Math.max(maxX, b.x); });

        if (maxX + move > rightBound || minX + move < leftBound) {
            // Step down, reverse
            this.formationDir *= -1;
            aliveBugs.forEach(b => { b.y += this.cfg.formationStepDown; });
        } else {
            aliveBugs.forEach(b => { b.x += move; });
        }
    }

    _moveProjectiles(dt) {
        const pbSpeed = this.cfg.playerBulletSpeed * dt;
        this.playerBullets = this.playerBullets.filter(b => {
            b.y -= pbSpeed;
            return b.y > -10;
        });

        const bbSpeed = this.cfg.bugBulletSpeed * dt;
        this.bugBullets = this.bugBullets.filter(b => {
            b.y += bbSpeed;
            return b.y < 920;
        });
    }

    _handleBugFire(delta) {
        this.bugFireTimer -= delta;
        if (this.bugFireTimer <= 0) {
            this.bugFireTimer = this.cfg.bugFireInterval * (0.7 + Math.random() * 0.6);
            // Pick a random bug from the bottom of each column
            const cols = {};
            this.bugs.filter(b => b.alive).forEach(b => {
                if (!cols[b.col] || b.row > cols[b.col].row) cols[b.col] = b;
            });
            const shooters = Object.values(cols);
            if (shooters.length > 0) {
                const shooter = Phaser.Utils.Array.GetRandom(shooters);
                this.bugBullets.push({ x: shooter.x, y: shooter.y + 20 });
                const snd = this.sound.add('cbilaser', { volume: 0.5 });
                snd.once('complete', () => snd.destroy());
                snd.play();
            }
        }
    }

    _checkCollisions() {
        // Player bullets vs bugs
        for (let bi = this.playerBullets.length - 1; bi >= 0; bi--) {
            const bullet = this.playerBullets[bi];
            let hit = false;
            for (const bug of this.bugs) {
                if (!bug.alive) continue;
                if (Math.abs(bullet.x - bug.x) < 28 && Math.abs(bullet.y - bug.y) < 22) {
                    bug.alive = false;
                    this.bugsHit++;
                    hit = true;
                    const snd = this.sound.add('cbibugdeath', { volume: 0.6 });
                    snd.once('complete', () => snd.destroy());
                    snd.play();
                    break;
                }
            }
            if (hit) {
                this.playerBullets.splice(bi, 1);
                if (this.bugsHit >= this.cfg.bugsToPass) {
                    this._endGame(true);
                    return;
                }
            }
        }

        // Bug bullets vs player
        if (this.player.alive) {
            for (const bb of this.bugBullets) {
                if (Math.abs(bb.x - this.player.x) < 30 && Math.abs(bb.y - this.player.y) < 25) {
                    this.player.alive = false;
                    const snd = this.sound.add('cbideath', { volume: 0.8 });
                    snd.once('complete', () => snd.destroy());
                    snd.play();
                    this._endGame(false);
                    return;
                }
            }
        }
    }

    _checkWinLose() {
        const alive = this.bugs.filter(b => b.alive);
        if (alive.length === 0) { this._endGame(true); return; }

        // Bugs reach danger line
        if (alive.some(b => b.y >= this.cfg.dangerY)) {
            this._endGame(false);
        }
    }

    _endGame(success) {
        if (!this.gameActive) return;
        this.gameActive = false;
        if (success) {
            const snd = this.sound.add('cbiComplete', { volume: 0.8 });
            snd.once('complete', () => snd.destroy());
            snd.play();
        }
        const msg = success ? 'BUGS SQUASHED!' : 'BUGS WIN!';
        const color = success ? '#00ff44' : '#ff2222';
        this.add.text(800, 440, msg, {
            fontSize: '72px', fontFamily: 'monospace',
            color, stroke: '#000000', strokeThickness: 5,
        }).setOrigin(0.5).setDepth(20);
        this.time.delayedCall(2200, () => {
            this.game.events.emit('miniGameResult', { success });
        });
    }

    _drawBug(g, x, y, color, frame) {
        // Simple bug shape: body + 6 legs + antenna
        g.fillStyle(color);
        g.fillEllipse(x, y, 36, 26);
        // Head
        g.fillCircle(x, y - 16, 10);
        // Antennae
        g.lineStyle(2, color);
        g.lineBetween(x - 4, y - 24, x - 10, y - 34);
        g.lineBetween(x + 4, y - 24, x + 10, y - 34);
        // Legs (animated: offset based on frame)
        const legOff = (frame % 2 === 0) ? 4 : -4;
        g.lineBetween(x - 18, y - 4 + legOff, x - 30, y - 8);
        g.lineBetween(x - 18, y + 4 - legOff, x - 30, y + 8);
        g.lineBetween(x + 18, y - 4 + legOff, x + 30, y - 8);
        g.lineBetween(x + 18, y + 4 - legOff, x + 30, y + 8);
        // Eyes
        g.fillStyle(0x000000);
        g.fillCircle(x - 4, y - 16, 3);
        g.fillCircle(x + 4, y - 16, 3);
        g.fillStyle(0xffffff);
        g.fillCircle(x - 3, y - 17, 1);
        g.fillCircle(x + 5, y - 17, 1);
    }

    _draw() {
        const g = this.mainGfx;
        g.clear();

        const tick = Math.floor(this.time.now / 300);

        // Bugs
        this.bugs.forEach(b => {
            if (!b.alive) return;
            this._drawBug(g, b.x, b.y, b.color, tick);
        });

        // Player ship
        if (this.player.alive) {
            const { x, y } = this.player;
            g.fillStyle(0x00ff88);
            g.fillTriangle(x, y - 30, x - 30, y + 15, x + 30, y + 15);
            g.fillStyle(0x00aa55);
            g.fillRect(x - 35, y + 10, 70, 12);
            g.fillStyle(0x88ffcc);
            g.fillRect(x - 6, y - 28, 12, 30);
        }

        // Ground line for player area
        g.lineStyle(2, 0x00ff44, 0.3);
        g.lineBetween(0, 870, 1600, 870);

        // Player bullets
        g.fillStyle(0xffffff);
        this.playerBullets.forEach(b => g.fillRect(b.x - 2, b.y - 8, 4, 16));

        // Bug bullets
        g.fillStyle(0xff4400);
        this.bugBullets.forEach(b => g.fillRect(b.x - 3, b.y - 10, 6, 18));

        // Danger line
        g.lineStyle(1, 0xff0000, 0.3);
        g.lineBetween(0, this.cfg.dangerY, 1600, this.cfg.dangerY);

        // HUD update
        this.bugsText.setText(`BUGS ${this.bugsHit}/${this.cfg.bugsToPass}`);
    }
}
