const BLOCK_COLORS = [0xff2222, 0xff8800, 0xffff00, 0x00ff44, 0x00aaff];

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

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

    preload() {
        this.load.json('soConfig', 'src/games/smash-out/config.json');
        this.load.audio('soMusic', 'assets/music/04-smash-out.mp3');
        this.load.audio('soComplete', 'assets/fx/complete.mp3');
        this.load.audio('soLaunch', 'assets/fx/launch.mp3');
        this.load.audio('soBounce', 'assets/fx/bounce.mp3');
        this.load.audio('soDestroy', 'assets/fx/short_death.mp3');
    }

    shutdown() {
        stopMusic(this);
    }

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

    create() {
        const all = this.cache.json.get('soConfig');
        const lvl = String(this.level);
        this.cfg = all.levels ? (all.levels[lvl] ?? all.levels['1']) : all;
        this.blocks = [];
        this.bricksDestroyed = 0;
        this.gameActive = true;
        this.ballLaunched = false;

        playMusic(this, 'soMusic');

        this._buildBackground();
        this._buildBlocks();
        this._buildPaddle();
        this._buildBall();
        this.mainGfx = this.add.graphics();
        this._buildHUD();
        this._setupInput();
    }

    _buildBackground() {
        const bg = this.add.graphics();
        bg.fillStyle(0x050510);
        bg.fillRect(0, 0, 1600, 900);
        // Grid lines for retro feel
        bg.lineStyle(1, 0x111133, 0.4);
        for (let x = 0; x < 1600; x += 80) bg.lineBetween(x, 0, x, 900);
        for (let y = 0; y < 900; y += 60) bg.lineBetween(0, y, 1600, y);
        this.add.text(800, 15, 'SMASH OUT', {
            fontSize: '20px', fontFamily: 'monospace', color: '#aaaaff', alpha: 0.7,
        }).setOrigin(0.5, 0);
    }

    _buildBlocks() {
        const { blockCols, blockRows, blockWidth, blockHeight, blockGapX, blockGapY, blocksStartX, blocksStartY } = this.cfg;
        for (let r = 0; r < blockRows; r++) {
            for (let c = 0; c < blockCols; c++) {
                const x = blocksStartX + c * (blockWidth + blockGapX);
                const y = blocksStartY + r * (blockHeight + blockGapY);
                this.blocks.push({ x, y, w: blockWidth, h: blockHeight, alive: true, color: BLOCK_COLORS[r] });
            }
        }
    }

    _buildPaddle() {
        const { paddleWidth, paddleHeight, paddleY } = this.cfg;
        this.paddle = { x: 800, y: paddleY, w: paddleWidth, h: paddleHeight };
    }

    _buildBall() {
        const r = this.cfg.ballRadius;
        this.ball = {
            x: this.paddle.x,
            y: this.paddle.y - this.paddle.h / 2 - r - 1,
            vx: 0, vy: 0,
            r,
            launched: false,
        };
    }

    _buildHUD() {
        this.livesText = this.add.text(800, 40, '♥ '.repeat(this.globalLives).trim(), {
            fontSize: '24px', fontFamily: 'monospace', color: '#ff4444',
        }).setOrigin(0.5, 0).setDepth(10);
        this.blocksText = this.add.text(1580, 40, '', {
            fontSize: '22px', fontFamily: 'monospace', color: '#aaaaff',
        }).setOrigin(1, 0).setDepth(10);
        this.launchHint = this.add.text(800, 820, 'PRESS A TO LAUNCH', {
            fontSize: '24px', fontFamily: 'monospace', color: '#ffffff',
        }).setOrigin(0.5, 0).setDepth(10);
        this.tweens.add({ targets: this.launchHint, alpha: 0, duration: 600, yoyo: true, repeat: -1 });
    }

    _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;

        // Move paddle
        const pSpeed = this.cfg.paddleSpeed;
        const halfW = this.paddle.w / 2;
        if (this.cursors.left.isDown) this.paddle.x -= pSpeed * dt;
        if (this.cursors.right.isDown) this.paddle.x += pSpeed * dt;
        this.paddle.x = Phaser.Math.Clamp(this.paddle.x, halfW, 1600 - halfW);

        // Launch
        if (!this.ball.launched) {
            this.ball.x = this.paddle.x;
            if (this.keyA.isDown && !this.keyAPressed) {
                this.keyAPressed = true;
                this._launch();
            }
            if (!this.keyA.isDown) this.keyAPressed = false;
        } else {
            this._moveBall(dt);
        }

        this._draw();
    }

    _playFx(key, volume = 0.6) {
        const snd = this.sound.add(key, { volume });
        snd.once('complete', () => snd.destroy());
        snd.play();
    }

    _launch() {
        this.ball.launched = true;
        this.launchHint.setVisible(false);
        const angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI / 3;
        const s = this.cfg.ballSpeed;
        this.ball.vx = Math.cos(angle) * s;
        this.ball.vy = Math.sin(angle) * s;
        this._playFx('soLaunch', 0.7);
    }

    _moveBall(dt) {
        const ball = this.ball;
        const r = ball.r;

        ball.x += ball.vx * dt;
        ball.y += ball.vy * dt;

        // Wall bounces
        let wallBounced = false;
        if (ball.x - r < 0) { ball.x = r; ball.vx = Math.abs(ball.vx); wallBounced = true; }
        if (ball.x + r > 1600) { ball.x = 1600 - r; ball.vx = -Math.abs(ball.vx); wallBounced = true; }
        if (ball.y - r < 0) { ball.y = r; ball.vy = Math.abs(ball.vy); wallBounced = true; }
        if (wallBounced) this._playFx('soBounce', 0.5);

        // Paddle bounce
        const { paddle } = this;
        const pTop = paddle.y - paddle.h / 2;
        if (ball.vy > 0 &&
            ball.y + r >= pTop && ball.y + r <= pTop + paddle.h + 2 &&
            ball.x >= paddle.x - paddle.w / 2 - r &&
            ball.x <= paddle.x + paddle.w / 2 + r) {
            const hitOffset = (ball.x - paddle.x) / (paddle.w / 2);
            const angle = -Math.PI / 2 + hitOffset * (Math.PI / 3);
            const speed = Math.hypot(ball.vx, ball.vy);
            ball.vx = Math.cos(angle) * speed;
            ball.vy = -Math.abs(Math.sin(angle) * speed);
            ball.y = pTop - r - 1;
            this._playFx('soBounce', 0.5);
        }

        // Block collisions
        this._checkBlockCollisions();

        // Ball lost
        if (ball.y - r > 900) {
            this._endGame(false);
        }
    }

    _checkBlockCollisions() {
        const ball = this.ball;
        const r = ball.r;

        for (const block of this.blocks) {
            if (!block.alive) continue;

            const bLeft = block.x;
            const bRight = block.x + block.w;
            const bTop = block.y;
            const bBottom = block.y + block.h;

            // AABB vs circle
            const nearX = Phaser.Math.Clamp(ball.x, bLeft, bRight);
            const nearY = Phaser.Math.Clamp(ball.y, bTop, bBottom);
            const dist = Math.hypot(ball.x - nearX, ball.y - nearY);

            if (dist < r) {
                block.alive = false;
                this.bricksDestroyed++;
                this._playFx('soBounce', 0.4);
                this._playFx('soDestroy', 0.6);

                // Determine bounce axis: use which edge the ball is closest to
                const overlapX = (ball.x < bLeft || ball.x > bRight)
                    ? Math.min(Math.abs(ball.x - bLeft), Math.abs(ball.x - bRight))
                    : 0;
                const overlapY = (ball.y < bTop || ball.y > bBottom)
                    ? Math.min(Math.abs(ball.y - bTop), Math.abs(ball.y - bBottom))
                    : 0;

                // overlapX==0 → ball center inside block horizontally → top/bottom hit
                if (overlapX === 0 || (overlapY !== 0 && overlapX > overlapY)) {
                    ball.vy = -ball.vy;
                } else {
                    ball.vx = -ball.vx;
                }

                if (this.bricksDestroyed >= this.cfg.bricksToPass) {
                    this._endGame(true);
                }
                break; // one block per frame
            }
        }
    }

    _endGame(success) {
        if (!this.gameActive) return;
        this.gameActive = false;
        if (success) this._playFx('soComplete', 0.8);
        const msg = success ? 'SMASHED IT!' : 'BALL LOST!';
        const color = success ? '#00ff44' : '#ff2222';
        this.add.text(800, 440, msg, {
            fontSize: '80px', fontFamily: 'monospace',
            color, stroke: '#000000', strokeThickness: 5,
        }).setOrigin(0.5).setDepth(20);
        this.time.delayedCall(2200, () => {
            this.game.events.emit('miniGameResult', { success });
        });
    }

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

        this.blocksText.setText(`SMASH ${this.bricksDestroyed}/${this.cfg.bricksToPass}`);

        this.blocks.forEach(b => {
            if (!b.alive) return;
            g.fillStyle(b.color);
            g.fillRect(b.x, b.y, b.w, b.h);
            g.lineStyle(2, 0xffffff, 0.4);
            g.strokeRect(b.x + 1, b.y + 1, b.w - 2, b.h - 2);
            // Highlight
            g.lineStyle(2, 0xffffff, 0.6);
            g.lineBetween(b.x + 3, b.y + 3, b.x + b.w - 3, b.y + 3);
        });

        // Paddle
        const { paddle } = this;
        g.fillStyle(0xaaaaff);
        g.fillRoundedRect(paddle.x - paddle.w / 2, paddle.y - paddle.h / 2, paddle.w, paddle.h, 6);
        g.lineStyle(2, 0xffffff, 0.8);
        g.lineBetween(paddle.x - paddle.w / 2 + 6, paddle.y - paddle.h / 2 + 4, paddle.x + paddle.w / 2 - 6, paddle.y - paddle.h / 2 + 4);

        // Ball
        const { ball } = this;
        g.fillStyle(0xffffff);
        g.fillCircle(ball.x, ball.y, ball.r);
        g.fillStyle(0xccccff);
        g.fillCircle(ball.x - 3, ball.y - 3, ball.r * 0.4);

        // Walls
        g.lineStyle(2, 0x333366, 0.6);
        g.lineBetween(0, 0, 0, 900);
        g.lineBetween(1600, 0, 1600, 900);
        g.lineBetween(0, 0, 1600, 0);
    }
}
