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

const TAU = Math.PI * 2;

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

    preload() {
        this.load.json('vortexConfig', 'src/games/vortex/config.json?v=1');
        this.load.audio('vortexMusic', 'assets/music/05-vortex.mp3');
        this.load.audio('vortexComplete', 'assets/fx/complete.mp3');
        this.load.audio('vortexFire', 'assets/fx/laser.mp3');
        this.load.audio('vortexHit', 'assets/fx/destroy.mp3');
        this.load.audio('vortexBreach', 'assets/fx/short_death.mp3');
    }

    init(data) {
        this.lives = data.lives ?? 3;
        this.level = String(data.level ?? 1);
    }

    create() {
        const all = this.cache.json.get('vortexConfig');
        const cfg = all.levels[this.level] ?? all.levels['1'];
        this.cfg = cfg;

        this.cx = 800;
        this.cy = 470;
        this.TWO_PI_N = TAU / cfg.numLanes;

        this.playerLane = 0;
        this.moveCooldown = 0;
        this.keyAPressed = false;

        this.bullets = [];
        this.enemies = [];
        this.kills = 0;
        this.misses = 0;
        this.spawnTimer = cfg.spawnInterval * 0.5; // first spawn after half interval
        this.gameActive = true;

        this.cursors = this.input.keyboard.createCursorKeys();
        this.keyA = this.input.keyboard.addKey('A');

        this.bgGfx = this.add.graphics();
        this.mainGfx = this.add.graphics();

        this._drawBackground();

        this.killsText = this.add.text(800, 16, '', {
            fontSize: '26px', fontFamily: 'monospace',
            color: '#00ffff', stroke: '#000000', strokeThickness: 4,
        }).setOrigin(0.5, 0).setDepth(10);

        this.shieldsText = this.add.text(20, 16, '', {
            fontSize: '26px', fontFamily: 'monospace',
            color: '#ffaa00', stroke: '#000000', strokeThickness: 4,
        }).setDepth(10);

        this.livesText = this.add.text(1580, 16, '', {
            fontSize: '26px', fontFamily: 'monospace',
            color: '#ff4444', stroke: '#000000', strokeThickness: 4,
        }).setOrigin(1, 0).setDepth(10);

        this.levelText = this.add.text(800, 860, `LEVEL ${this.level}  |  Arrow Keys: Move   A: Fire`, {
            fontSize: '20px', fontFamily: 'monospace',
            color: '#446688', stroke: '#000000', strokeThickness: 3,
        }).setOrigin(0.5, 1).setDepth(10);

        playMusic(this, 'vortexMusic');
        this._updateHUD();
    }

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

        this._handleInput(dt);
        this._spawnEnemies(dt);
        this._updateBullets(dt);
        this._updateEnemies(dt);
        this._draw();
        this._updateHUD();
    }

    // ─── Input ────────────────────────────────────────────────────────────────

    _handleInput(dt) {
        this.moveCooldown = Math.max(0, this.moveCooldown - dt * 1000);

        if (this.moveCooldown <= 0) {
            if (this.cursors.left.isDown) {
                this.playerLane = (this.playerLane - 1 + this.cfg.numLanes) % this.cfg.numLanes;
                this.moveCooldown = this.cfg.moveCooldown;
            } else if (this.cursors.right.isDown) {
                this.playerLane = (this.playerLane + 1) % this.cfg.numLanes;
                this.moveCooldown = this.cfg.moveCooldown;
            }
        }

        if (this.keyA.isDown && !this.keyAPressed) {
            this.keyAPressed = true;
            this._shoot();
        }
        if (!this.keyA.isDown) this.keyAPressed = false;
    }

    _shoot() {
        this.bullets.push({ lane: this.playerLane, t: 0.98 });
        this._playFx('vortexFire', 0.45);
    }

    // ─── Spawn ────────────────────────────────────────────────────────────────

    _spawnEnemies(dt) {
        this.spawnTimer += dt;
        if (this.spawnTimer < this.cfg.spawnInterval) return;
        if (this.enemies.length >= this.cfg.maxActiveEnemies) return;
        this.spawnTimer = 0;

        const lane = Phaser.Math.Between(0, this.cfg.numLanes - 1);
        this.enemies.push({ lane, t: 0.04, alive: true, flash: 0 });
    }

    // ─── Update ───────────────────────────────────────────────────────────────

    _updateBullets(dt) {
        const speed = this.cfg.bulletSpeed;
        for (const b of this.bullets) {
            b.t -= speed * dt;
        }

        // Bullet–enemy collision
        for (const b of this.bullets) {
            if (b.t <= 0) continue;
            for (const e of this.enemies) {
                if (!e.alive || e.lane !== b.lane) continue;
                if (Math.abs(b.t - e.t) < 0.07) {
                    e.alive = false;
                    b.t = -1;
                    this.kills++;
                    this._playFx('vortexHit', 0.6);
                    if (this.kills >= this.cfg.killsToWin) {
                        this._endGame(true);
                        return;
                    }
                }
            }
        }

        this.bullets = this.bullets.filter(b => b.t > 0);
    }

    _updateEnemies(dt) {
        const speed = this.cfg.enemySpeed;
        for (const e of this.enemies) {
            if (!e.alive) continue;
            e.t += speed * dt;
            if (e.flash > 0) e.flash -= dt;
        }

        // Check rim breaches
        for (const e of this.enemies) {
            if (!e.alive || e.t < 1.0) continue;
            e.alive = false;
            this.misses++;
            this._playFx('vortexBreach', 0.7);
            if (this.misses >= this.cfg.maxMisses) {
                this._endGame(false);
                return;
            }
        }

        this.enemies = this.enemies.filter(e => e.alive);
    }

    // ─── Drawing ──────────────────────────────────────────────────────────────

    _drawBackground() {
        this.bgGfx.fillStyle(0x000814);
        this.bgGfx.fillRect(0, 0, 1600, 900);
    }

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

        this._drawTube(g);
        this._drawPlayerLaneHighlight(g);
        this._drawEnemies(g);
        this._drawBullets(g);
        this._drawPlayer(g);
    }

    _drawTube(g) {
        const { numLanes, rimRadius } = this.cfg;
        const cx = this.cx, cy = this.cy;
        const step = this.TWO_PI_N;
        const RINGS = 7;

        // Depth rings (concentric polygons shrinking toward center)
        for (let r = 1; r <= RINGS; r++) {
            const t = r / RINGS;
            const depth = t * t; // non-linear for stronger perspective
            const radius = rimRadius * depth;
            const alpha = 0.15 + t * 0.25;
            const blue = Math.floor(60 + t * 140);
            g.lineStyle(1, Phaser.Display.Color.GetColor(0, blue / 3, blue), alpha);
            g.beginPath();
            for (let i = 0; i <= numLanes; i++) {
                const angle = i * step - Math.PI / 2;
                const x = cx + radius * Math.cos(angle);
                const y = cy + radius * Math.sin(angle);
                if (i === 0) g.moveTo(x, y); else g.lineTo(x, y);
            }
            g.closePath();
            g.strokePath();
        }

        // Lane dividers: lines from each rim vertex to center
        for (let i = 0; i < numLanes; i++) {
            const angle = i * step - Math.PI / 2;
            const rx = cx + rimRadius * Math.cos(angle);
            const ry = cy + rimRadius * Math.sin(angle);
            const isEdge = i === this.playerLane || i === (this.playerLane + 1) % numLanes;
            if (isEdge) {
                g.lineStyle(2, 0x00eeff, 0.75);
            } else {
                g.lineStyle(1, 0x003355, 0.55);
            }
            g.lineBetween(cx, cy, rx, ry);
        }

        // Outer rim
        g.lineStyle(3, 0x00ccff, 1.0);
        g.beginPath();
        for (let i = 0; i <= numLanes; i++) {
            const angle = i * step - Math.PI / 2;
            const x = cx + rimRadius * Math.cos(angle);
            const y = cy + rimRadius * Math.sin(angle);
            if (i === 0) g.moveTo(x, y); else g.lineTo(x, y);
        }
        g.closePath();
        g.strokePath();

        // Center vanishing point glow
        g.fillStyle(0x00aaff, 0.6);
        g.fillCircle(cx, cy, 5);
        g.fillStyle(0x002244, 0.4);
        g.fillCircle(cx, cy, 12);
    }

    _drawPlayerLaneHighlight(g) {
        const { numLanes, rimRadius } = this.cfg;
        const cx = this.cx, cy = this.cy;
        const step = this.TWO_PI_N;
        const pl = this.playerLane;
        const a0 = pl * step - Math.PI / 2;
        const a1 = (pl + 1) * step - Math.PI / 2;

        g.fillStyle(0x00ffff, 0.06);
        g.beginPath();
        g.moveTo(cx, cy);
        const SEGS = 6;
        for (let i = 0; i <= SEGS; i++) {
            const a = a0 + (a1 - a0) * (i / SEGS);
            g.lineTo(cx + rimRadius * Math.cos(a), cy + rimRadius * Math.sin(a));
        }
        g.closePath();
        g.fillPath();
    }

    _drawEnemies(g) {
        for (const e of this.enemies) {
            if (!e.alive) continue;
            const pos = this._lanePos(e.lane, e.t);
            const angle = this._laneAngle(e.lane);
            const size = 13;
            const perp = angle + Math.PI / 2;

            // Triangle pointing outward (toward rim)
            const tx = pos.x + Math.cos(angle) * size;
            const ty = pos.y + Math.sin(angle) * size;
            const lx = pos.x - Math.cos(angle) * (size * 0.4) + Math.cos(perp) * (size * 0.65);
            const ly = pos.y - Math.sin(angle) * (size * 0.4) + Math.sin(perp) * (size * 0.65);
            const rx = pos.x - Math.cos(angle) * (size * 0.4) - Math.cos(perp) * (size * 0.65);
            const ry = pos.y - Math.sin(angle) * (size * 0.4) - Math.sin(perp) * (size * 0.65);

            // Pulse red as they get closer to rim
            const danger = e.t;
            const r = Math.floor(200 + danger * 55);
            const gv = Math.floor(80 - danger * 70);
            const color = Phaser.Display.Color.GetColor(r, Math.max(0, gv), 0);

            g.fillStyle(color, 1.0);
            g.beginPath();
            g.moveTo(tx, ty);
            g.lineTo(lx, ly);
            g.lineTo(rx, ry);
            g.closePath();
            g.fillPath();

            g.lineStyle(1.5, 0xff8800, 0.7);
            g.beginPath();
            g.moveTo(tx, ty);
            g.lineTo(lx, ly);
            g.lineTo(rx, ry);
            g.closePath();
            g.strokePath();
        }
    }

    _drawBullets(g) {
        for (const b of this.bullets) {
            const pos = this._lanePos(b.lane, b.t);
            const trailPos = this._lanePos(b.lane, Math.min(1, b.t + 0.08));

            g.lineStyle(2, 0xffff00, 0.55);
            g.lineBetween(pos.x, pos.y, trailPos.x, trailPos.y);

            g.fillStyle(0xffffff, 1.0);
            g.fillCircle(pos.x, pos.y, 5);
            g.fillStyle(0xffff00, 0.9);
            g.fillCircle(pos.x, pos.y, 3);
        }
    }

    _drawPlayer(g) {
        const { rimRadius } = this.cfg;
        const cx = this.cx, cy = this.cy;
        const pl = this.playerLane;
        const angle = this._laneAngle(pl);
        const perp = angle + Math.PI / 2;

        // Position slightly outside rim
        const px = cx + (rimRadius + 22) * Math.cos(angle);
        const py = cy + (rimRadius + 22) * Math.sin(angle);

        const arm = 18;
        const depth = 14;

        // Claw: two arms that open toward center, connected at the back
        const tipX = px + Math.cos(angle) * 6;
        const tipY = py + Math.sin(angle) * 6;
        const backX = px - Math.cos(angle) * depth;
        const backY = py - Math.sin(angle) * depth;

        g.lineStyle(2.5, 0x00ffff, 1.0);

        // Left arm
        g.lineBetween(tipX, tipY,
            backX + Math.cos(perp) * arm, backY + Math.sin(perp) * arm);
        // Right arm
        g.lineBetween(tipX, tipY,
            backX - Math.cos(perp) * arm, backY - Math.sin(perp) * arm);
        // Back connector
        g.lineBetween(
            backX + Math.cos(perp) * arm, backY + Math.sin(perp) * arm,
            backX - Math.cos(perp) * arm, backY - Math.sin(perp) * arm);

        // Tip dot
        g.fillStyle(0x00ffff, 1.0);
        g.fillCircle(tipX, tipY, 4);

        // Glow ring
        g.lineStyle(1, 0x00ffff, 0.3);
        g.strokeCircle(px, py, 26);
    }

    // ─── Geometry helpers ─────────────────────────────────────────────────────

    _laneAngle(lane) {
        return (lane + 0.5) * this.TWO_PI_N - Math.PI / 2;
    }

    _lanePos(lane, t) {
        const angle = this._laneAngle(lane);
        const r = t * this.cfg.rimRadius;
        return {
            x: this.cx + r * Math.cos(angle),
            y: this.cy + r * Math.sin(angle),
        };
    }

    // ─── HUD ──────────────────────────────────────────────────────────────────

    _updateHUD() {
        const cfg = this.cfg;
        this.killsText.setText(`KILLS  ${this.kills} / ${cfg.killsToWin}`);
        const shieldsLeft = cfg.maxMisses - this.misses;
        this.shieldsText.setText('■ '.repeat(shieldsLeft).trim() + '□ '.repeat(this.misses).trim());
        this.livesText.setText('♥ '.repeat(this.lives).trim());
    }

    // ─── End game ─────────────────────────────────────────────────────────────

    _endGame(success) {
        if (!this.gameActive) return;
        this.gameActive = false;

        if (success) this._playFx('vortexComplete', 0.8);

        const msg = success ? 'VICTORY!' : 'BREACHED!';
        const color = success ? '#00ff44' : '#ff2222';
        this.add.text(800, 440, msg, {
            fontSize: '80px', fontFamily: 'monospace',
            color, stroke: '#000000', strokeThickness: 6,
        }).setOrigin(0.5).setDepth(20);

        this.time.delayedCall(2200, () => {
            this.game.events.emit('miniGameResult', { success });
        });
    }

    shutdown() {
        stopMusic(this);
    }

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