import Phaser from 'phaser';
import { LEVEL_DURATION, PLAYER_STARTING_LIVES, CHEST_REQUIRED_GIFTS } from '../utils/constants';
import { Player } from '../entities/Player';
import { GyroControl } from '../controls/GyroControl';
import { JumpButton } from '../controls/JumpButton';
import { DirectionalButtons } from '../controls/DirectionalButtons';
import { SuperTreasure } from '../entities/SuperTreasure';
import { TreasureChest } from '../entities/TreasureChest';

/**
 * Scène principale du jeu
 * Supporte PC (clavier) et Mobile (gyroscope + tactile)
 */
export class GameScene extends Phaser.Scene {
    private player?: Player;
    private cursors?: Phaser.Types.Input.Keyboard.CursorKeys;
    private gyroControl?: GyroControl;
    private jumpButton?: JumpButton;
    private directionalButtons?: DirectionalButtons;

    // Plateformes et groupes
    private platforms?: Phaser.Physics.Arcade.StaticGroup;
    private obstacles?: Phaser.Physics.Arcade.Group;
    private gifts?: Phaser.Physics.Arcade.Group;
    private superTreasures?: Phaser.Physics.Arcade.Group;
    private treasureChest?: TreasureChest;
    private bgMusic?: Phaser.Sound.BaseSound;
    private platformRects: { x: number; y: number; w: number; h: number }[] = [];

    // Background
    private background?: Phaser.GameObjects.TileSprite;

    // UI
    private scoreText?: Phaser.GameObjects.Text;
    private timerText?: Phaser.GameObjects.Text;
    private controlInfoText?: Phaser.GameObjects.Text;
    private livesText?: Phaser.GameObjects.Text;
    private giftsCollectedText?: Phaser.GameObjects.Text;
    private volumeText?: Phaser.GameObjects.Text;
    private sfxVolumeText?: Phaser.GameObjects.Text;

    // Game state
    private score: number = 0;
    private timeRemaining: number = LEVEL_DURATION;
    private gameStartTime: number = 0;
    private isMobile: boolean = false;
    private lives: number = PLAYER_STARTING_LIVES;
    private giftsCollected: number = 0;
    private lastCheckpointX: number = 200; // Position du dernier checkpoint
    private musicVolume: number = 0.5;
    private sfxVolume: number = 0.6;
    private snowPileTimer?: Phaser.Time.TimerEvent;
    private snowHeights: number[] = [];
    private snowPileGraphics?: Phaser.GameObjects.Graphics;

    constructor() {
        super({ key: 'GameScene' });
    }

    create(): void {
        const width = this.cameras.main.width;
        const height = this.cameras.main.height;

        // Réinitialiser l'état de partie
        this.score = 0;
        this.giftsCollected = 0;
        this.lives = PLAYER_STARTING_LIVES;
        this.lastCheckpointX = 200;

        this.gameStartTime = this.time.now;

        // Détecter si mobile
        this.isMobile = this.sys.game.device.os.android || this.sys.game.device.os.iOS;

        // Configurer les limites du monde physique (IMPORTANT pour permettre mouvement infini)
        // Étendre un peu plus pour inclure la plateforme finale et le coffre
        const levelWidth = Math.max(width * 7, 8000);
        this.physics.world.setBounds(0, 0, levelWidth, height);

        // Créer le background qui défile
        this.createBackground(levelWidth);

        // Créer les plateformes
        this.createPlatforms();

        // Créer le joueur
        this.player = new Player(this, 200, height - 150);

        // Collision joueur / plateformes
        this.physics.add.collider(this.player, this.platforms!);

        // Créer les groupes d'objets
        this.createObjectGroups();

        // Configuration caméra (suit le joueur)
        this.cameras.main.startFollow(this.player, true, 0.1, 0.1);
        this.cameras.main.setBounds(0, 0, levelWidth, height);

        // Contrôles PC (clavier)
        this.cursors = this.input.keyboard?.createCursorKeys();

        // Contrôles Mobile (gyroscope + bouton tactile)
        if (this.isMobile) {
            this.setupMobileControls();
        }

        // UI
        this.createUI();

        // Effet neige
        this.createSnow();

        // Musique
        this.setupMusic();

        // Volume SFX initial
        this.registry.set('sfxVolume', this.sfxVolume);

        // Générer quelques obstacles et cadeaux de test
        this.spawnTestObjects();

        console.log(`GameScene créée - Mode: ${this.isMobile ? 'Mobile' : 'PC'}`);
    }

    /**
     * Crée le background qui défile
     */
    private createBackground(levelWidth: number): void {
        const width = this.cameras.main.width;
        const height = this.cameras.main.height;

        // Background temporaire (sera remplacé par une vraie image)
        const graphics = this.add.graphics();

        // Ciel dégradé
        graphics.fillGradientStyle(0x87CEEB, 0x87CEEB, 0xE0F6FF, 0xE0F6FF, 1);
        graphics.fillRect(0, 0, width, height);

        // Nuages simples
        graphics.fillStyle(0xFFFFFF, 0.6);
        for (let i = 0; i < 5; i++) {
            const x = (width / 5) * i + 50;
            const y = 100 + Math.random() * 100;
            graphics.fillCircle(x, y, 30);
            graphics.fillCircle(x + 20, y, 25);
            graphics.fillCircle(x + 40, y, 30);
        }

        graphics.generateTexture('sky', width, height);
        graphics.destroy();

        this.background = this.add.tileSprite(0, 0, levelWidth, height, 'sky');
        this.background.setOrigin(0, 0);
        this.background.setScrollFactor(0.3); // Effet parallaxe
    }

    /**
     * Crée les plateformes du niveau (version étendue avec beaucoup plus de plateformes)
     */
    private createPlatforms(): void {
        this.platforms = this.physics.add.staticGroup();

        const width = this.cameras.main.width;
        const height = this.cameras.main.height;

        // Sol principal (très large pour le niveau 6x)
        const groundWidth = width * 6;
        const ground = this.add.rectangle(groundWidth / 2, height - 25, groundWidth, 50, 0x8B4513);
        this.physics.add.existing(ground, true);
        this.platforms.add(ground);
        this.platformRects.push({ x: groundWidth / 2, y: height - 25, w: groundWidth, h: 50 });

        // BEAUCOUP plus de plateformes réparties sur toute la longueur
        const platformPositions = [
            // Zone 1 (début - facile)
            { x: 400, y: height - 150, w: 200, h: 30 },
            { x: 700, y: height - 250, w: 180, h: 30 },
            { x: 1000, y: height - 200, w: 200, h: 30 },
            { x: 1300, y: height - 300, w: 150, h: 30 },

            // Zone 2 (moyen)
            { x: 1600, y: height - 180, w: 220, h: 30 },
            { x: 1900, y: height - 320, w: 160, h: 30 },
            { x: 2200, y: height - 240, w: 200, h: 30 },
            { x: 2500, y: height - 380, w: 140, h: 30 },
            { x: 2800, y: height - 280, w: 180, h: 30 },

            // Zone 3 (plus difficile)
            { x: 3100, y: height - 200, w: 150, h: 30 },
            { x: 3350, y: height - 350, w: 120, h: 30 },
            { x: 3600, y: height - 250, w: 200, h: 30 },
            { x: 3900, y: height - 400, w: 150, h: 30 },
            { x: 4200, y: height - 300, w: 180, h: 30 },

            // Zone 4 (avancé)
            { x: 4500, y: height - 180, w: 160, h: 30 },
            { x: 4800, y: height - 340, w: 140, h: 30 },
            { x: 5100, y: height - 250, w: 200, h: 30 },
            { x: 5400, y: height - 420, w: 150, h: 30 },
            { x: 5700, y: height - 320, w: 180, h: 30 },

            // Zone 5 (très difficile)
            { x: 6000, y: height - 200, w: 140, h: 30 },
            { x: 6250, y: height - 380, w: 120, h: 30 },
            { x: 6500, y: height - 280, w: 160, h: 30 },
            { x: 6800, y: height - 450, w: 130, h: 30 },
            { x: 7100, y: height - 350, w: 180, h: 30 },

            // Zone 6 (finale)
            { x: 7400, y: height - 250, w: 200, h: 30 },
            { x: 7700, y: height - 180, w: 300, h: 30 }, // Grande plateforme finale
        ];

        platformPositions.forEach((pos) => {
            const platform = this.add.rectangle(pos.x, pos.y, pos.w, pos.h, 0x6B8E23);
            this.physics.add.existing(platform, true);
            this.platforms!.add(platform);
            this.platformRects.push({ x: pos.x, y: pos.y, w: pos.w, h: pos.h });
        });

        console.log(`${platformPositions.length} plateformes créées sur ${groundWidth}px`);
    }

    /**
     * Crée les groupes d'obstacles, cadeaux et super trésors
     */
    private createObjectGroups(): void {
        this.obstacles = this.physics.add.group();
        this.gifts = this.physics.add.group();
        this.superTreasures = this.physics.add.group();

        // Collisions
        this.physics.add.overlap(this.player!, this.gifts, this.collectGift, undefined, this);
        this.physics.add.overlap(this.player!, this.obstacles, this.hitObstacle, undefined, this);
        this.physics.add.overlap(this.player!, this.superTreasures, this.collectSuperTreasure, undefined, this);
    }

    /**
     * Génère BEAUCOUP d'objets répartis sur tout le niveau
     */
    private spawnTestObjects(): void {
        const height = this.cameras.main.height;

        // BEAUCOUP de cadeaux répartis partout (environ tous les 300-500px)
        const giftPositions = [
            // Zone 1
            600, 900, 1200, 1500,
            // Zone 2
            1800, 2100, 2400, 2700,
            // Zone 3
            3000, 3300, 3600, 3900,
            // Zone 4
            4200, 4500, 4800, 5100,
            // Zone 5
            5400, 5700, 6000, 6300,
            // Zone 6
            6600, 6900, 7200, 7500,
        ];

        giftPositions.forEach((x) => {
            // Alterner entre sol et en hauteur
            const isHigh = Math.random() > 0.5;
            const y = isHigh ? height - 200 - Math.random() * 150 : height - 100;

            const gift = this.add.circle(x, y, 20, 0xFFEB3B);
            this.physics.add.existing(gift);
            this.gifts!.add(gift);
        });

        // BEAUCOUP d'obstacles répartis partout
        const obstaclePositions = [
            // Zone 1
            800, 1100, 1400,
            // Zone 2
            2000, 2300, 2600, 2900,
            // Zone 3
            3200, 3500, 3800, 4100,
            // Zone 4
            4400, 4700, 5000, 5300,
            // Zone 5
            5600, 5900, 6200, 6500,
            // Zone 6
            6800, 7100, 7400,
        ];

        // Obstacles sur plateformes (x, y)
        const obstaclePlatforms = [
            { x: 700, y: height - 280 },
            { x: 1300, y: height - 330 },
            { x: 1900, y: height - 350 },
            { x: 2500, y: height - 410 },
            { x: 3350, y: height - 380 },
            { x: 3900, y: height - 430 },
            { x: 4800, y: height - 360 },
            { x: 5400, y: height - 440 },
            { x: 6250, y: height - 400 },
            { x: 6800, y: height - 500 },
        ];

        // Ajouter quelques champignons directement sur les plateformes existantes
        const platformPlaced: Array<{ x: number; y: number }> = [];
        this.platformRects
            .filter((rect) => rect.y < height - 80 && rect.w >= 120) // ignorer le sol et les très petites plateformes
            .forEach((rect, idx) => {
                // Placer un champignon sur ~1 plateforme sur 2 pour ne pas surcharger
                if (idx % 2 !== 0) return;
                const x = rect.x + Phaser.Math.Between(Math.round(-rect.w / 4), Math.round(rect.w / 4));
                const y = rect.y - rect.h / 2;
                platformPlaced.push({ x, y });
            });

        obstaclePositions.filter((_, idx) => idx % 2 === 0).forEach((x) => {
            const obstacle = this.physics.add.sprite(x, height - 50, 'obstacle_mushroom');
            obstacle.setOrigin(0.5, 1); // ancré sur les pieds
            obstacle.setImmovable(true);
            obstacle.setPushable(false);
            obstacle.setScale(0.9);

            const body = obstacle.body as Phaser.Physics.Arcade.Body;
            body.setAllowGravity(false);
            body.setSize(45, 81); // hitbox 10% plus petite avec le scale
            body.setOffset((obstacle.displayWidth - 45) / 2, obstacle.displayHeight - 81);

            this.obstacles!.add(obstacle);
        });

        obstaclePlatforms.filter((_, idx) => idx % 2 === 0).forEach((pos) => {
            // Trouver la plateforme la plus proche à cet x
            const target = this.platformRects.find((rect) => Math.abs(pos.x - rect.x) <= rect.w / 2);
            const topY = target ? target.y - target.h / 2 : pos.y;
            const obstacle = this.physics.add.sprite(pos.x, topY, 'obstacle_mushroom');
            obstacle.setOrigin(0.5, 1);
            obstacle.setImmovable(true);
            obstacle.setPushable(false);
            obstacle.setScale(0.9);

            const body = obstacle.body as Phaser.Physics.Arcade.Body;
            body.setAllowGravity(false);
            body.setSize(45, 81);
            body.setOffset((obstacle.displayWidth - 45) / 2, obstacle.displayHeight - 81);

            this.obstacles!.add(obstacle);
        });

        platformPlaced.filter((_, idx) => idx % 2 === 0).forEach((pos) => {
            const obstacle = this.physics.add.sprite(pos.x, pos.y, 'obstacle_mushroom');
            obstacle.setOrigin(0.5, 1);
            obstacle.setImmovable(true);
            obstacle.setPushable(false);
            obstacle.setScale(0.9);

            const body = obstacle.body as Phaser.Physics.Arcade.Body;
            body.setAllowGravity(false);
            body.setSize(45, 81);
            body.setOffset((obstacle.displayWidth - 45) / 2, obstacle.displayHeight - 81);

            this.obstacles!.add(obstacle);
        });

        // SUPER TRÉSORS (rares et précieux - 1 par zone)
        const superTreasurePositions = [
            { x: 1000, y: height - 350 },  // Zone 1 - en hauteur
            { x: 2500, y: height - 420 },  // Zone 2 - très haut
            { x: 3900, y: height - 450 },  // Zone 3 - très haut
            { x: 5400, y: height - 470 },  // Zone 4 - ultra haut
            { x: 6800, y: height - 500 },  // Zone 5 - ultra haut
            { x: 7300, y: height - 250 },  // Zone 6 - sur plateforme finale
        ];

        superTreasurePositions.forEach((pos) => {
            const superTreasure = new SuperTreasure(this, pos.x, pos.y);
            this.superTreasures!.add(superTreasure);
        });

        // COFFRE FINAL au bout du niveau
        this.treasureChest = new TreasureChest(this, 7700, height - 300, CHEST_REQUIRED_GIFTS);
        this.physics.add.overlap(this.player!, this.treasureChest, this.openChest, undefined, this);

        console.log(`${giftPositions.length} cadeaux, ${obstaclePositions.length} obstacles, ${superTreasurePositions.length} SUPER TRÉSORS et 1 COFFRE FINAL créés`);
    }

    /**
     * Configure les contrôles mobile
     */
    private setupMobileControls(): void {
        // Gyroscope
        this.gyroControl = new GyroControl();

        // Bouton de saut
        this.jumpButton = new JumpButton(this, () => {
            this.player?.jump();
        });

        // Boutons gauche/droite (en bas à gauche)
        this.directionalButtons = new DirectionalButtons(this);
    }

    /**
     * Crée l'interface utilisateur
     */
    private createUI(): void {
        // Score
        this.scoreText = this.add.text(20, 20, 'Score: 0', {
            fontSize: '32px',
            color: '#ffffff',
            stroke: '#000000',
            strokeThickness: 4,
        });
        this.scoreText.setScrollFactor(0);
        this.scoreText.setDepth(100);

        // Vies
        this.livesText = this.add.text(20, 60, `❤️ Vies: ${this.lives}`, {
            fontSize: '28px',
            color: '#ff0000',
            stroke: '#000000',
            strokeThickness: 4,
        });
        this.livesText.setScrollFactor(0);
        this.livesText.setDepth(100);

        // Cadeaux collectés
        this.giftsCollectedText = this.add.text(20, 100, `🎁 Cadeaux: ${this.giftsCollected}/${CHEST_REQUIRED_GIFTS}`, {
            fontSize: '24px',
            color: '#FFD700',
            stroke: '#000000',
            strokeThickness: 3,
        });
        this.giftsCollectedText.setScrollFactor(0);
        this.giftsCollectedText.setDepth(100);

        // Timer
        this.timerText = this.add.text(this.cameras.main.width / 2, 20, '3:00', {
            fontSize: '32px',
            color: '#ffffff',
            stroke: '#000000',
            strokeThickness: 4,
        });
        this.timerText.setOrigin(0.5, 0);
        this.timerText.setScrollFactor(0);
        this.timerText.setDepth(100);

        // Info contrôles (avec mention du double saut)
        const controlText = this.isMobile
            ? 'Inclinez pour bouger • Bouton pour sauter (DOUBLE SAUT disponible!)'
            : 'Flèches pour bouger • Espace pour sauter (DOUBLE SAUT disponible!)';

        this.controlInfoText = this.add.text(
            this.cameras.main.width / 2,
            this.cameras.main.height - 30,
            controlText,
            {
                fontSize: '18px',
                color: '#ffffff',
                backgroundColor: '#00000088',
                padding: { x: 10, y: 5 },
            }
        );
        this.controlInfoText.setOrigin(0.5);
        this.controlInfoText.setScrollFactor(0);
        this.controlInfoText.setDepth(100);

        // Bouton retour menu
        const backButton = this.add.text(this.cameras.main.width - 20, 20, '⬅ Menu', {
            fontSize: '24px',
            color: '#ffffff',
            backgroundColor: '#000000',
            padding: { x: 10, y: 5 },
        });
        backButton.setOrigin(1, 0);
        backButton.setScrollFactor(0);
        backButton.setDepth(100);
        backButton.setInteractive({ useHandCursor: true });
        backButton.on('pointerdown', () => {
            this.cleanup();
            this.scene.start('MenuScene');
        });

        // Volume musique
        this.volumeText = this.add.text(this.cameras.main.width - 20, 60, this.getVolumeLabel(), {
            fontSize: '18px',
            color: '#ffffff',
            backgroundColor: '#000000',
            padding: { x: 8, y: 4 },
        });
        this.volumeText.setOrigin(1, 0);
        this.volumeText.setScrollFactor(0);
        this.volumeText.setDepth(100);
        this.volumeText.setInteractive({ useHandCursor: true });
        this.volumeText.on('pointerdown', () => {
            this.cycleMusicVolume();
        });

        // Volume SFX
        this.sfxVolumeText = this.add.text(this.cameras.main.width - 20, 90, this.getSfxVolumeLabel(), {
            fontSize: '18px',
            color: '#ffffff',
            backgroundColor: '#000000',
            padding: { x: 8, y: 4 },
        });
        this.sfxVolumeText.setOrigin(1, 0);
        this.sfxVolumeText.setScrollFactor(0);
        this.sfxVolumeText.setDepth(100);
        this.sfxVolumeText.setInteractive({ useHandCursor: true });
        this.sfxVolumeText.on('pointerdown', () => {
            this.cycleSfxVolume();
        });
    }

    update(time: number): void {
        if (!this.player) return;

        // Mise à jour du timer
        this.updateTimer(time);

        // Gestion des contrôles
        let direction = 0;

        // PC : Clavier
        if (this.cursors) {
            if (this.cursors.left.isDown) {
                direction = -1;
            } else if (this.cursors.right.isDown) {
                direction = 1;
            }

            // Saut avec Espace
            if (Phaser.Input.Keyboard.JustDown(this.cursors.space!)) {
                this.player.jump();
            }

            // Saut avec flèche haut (alternative)
            if (Phaser.Input.Keyboard.JustDown(this.cursors.up!)) {
                this.player.jump();
            }
        }

        // Mobile : boutons directionnels priment, sinon gyroscope
        if (this.isMobile) {
            const dirButtons = this.directionalButtons?.getDirection() ?? 0;
            if (dirButtons !== 0) {
                direction = dirButtons;
            } else if (this.gyroControl) {
                const tiltValue = this.gyroControl.getTiltValue();
                direction = tiltValue; // -1 à 1
            }
        }

        // Déplacer le joueur
        this.player.move(direction);
        this.player.update();

        // Système de checkpoint (sauvegarde tous les 1000px)
        const playerX = this.player.x;
        if (playerX > this.lastCheckpointX + 1000) {
            this.lastCheckpointX = Math.floor(playerX / 1000) * 1000;
            console.log(`✅ Checkpoint atteint à x=${this.lastCheckpointX}`);

            // Feedback visuel rapide
            this.cameras.main.flash(50, 0, 255, 0, true);
        }

        // Scroll du background (effet parallaxe)
        if (this.background) {
            this.background.tilePositionX = this.cameras.main.scrollX * 0.3;
        }
    }

    /**
     * Met à jour le timer
     */
    private updateTimer(time: number): void {
        const elapsed = Math.floor((time - this.gameStartTime) / 1000);
        this.timeRemaining = LEVEL_DURATION - elapsed;

        if (this.timeRemaining <= 0) {
            this.timeRemaining = 0;
            this.endGame();
        }

        const minutes = Math.floor(this.timeRemaining / 60);
        const seconds = this.timeRemaining % 60;
        this.timerText?.setText(`${minutes}:${seconds.toString().padStart(2, '0')}`);

        // Changement de couleur si temps faible
        if (this.timeRemaining <= 30) {
            this.timerText?.setColor('#FF0000');
        }
    }

    /**
     * Collecte un cadeau
     */
    private collectGift(_player: any, gift: any): void {
        gift.destroy();
        this.giftsCollected++;
        this.addScore(100);
        this.playSfx('sfx_powerup', 0.5);

        // Mettre à jour l'UI
        this.giftsCollectedText?.setText(`🎁 Cadeaux: ${this.giftsCollected}/${CHEST_REQUIRED_GIFTS}`);

        // Feedback si on a assez pour le coffre
        if (this.giftsCollected >= CHEST_REQUIRED_GIFTS && !this.treasureChest?.getIsOpen()) {
            // Flash doré
            this.cameras.main.flash(100, 255, 215, 0, true);

            const hint = this.add.text(
                this.cameras.main.scrollX + this.cameras.main.width / 2,
                this.cameras.main.height / 2,
                '🏆 Assez de cadeaux! Trouvez le coffre! 🏆',
                {
                    fontSize: '32px',
                    color: '#FFD700',
                    stroke: '#000000',
                    strokeThickness: 4,
                }
            );
            hint.setOrigin(0.5);
            hint.setScrollFactor(0);
            hint.setDepth(1000);

            this.tweens.add({
                targets: hint,
                alpha: 0,
                duration: 3000,
                onComplete: () => hint.destroy(),
            });
        }
    }

    /**
     * Collision avec un obstacle
     */
    private hitObstacle(player: any, obstacle: any): void {
        // Vérifier si on saute dessus (player au-dessus de l'obstacle)
        const playerBody = player.body as Phaser.Physics.Arcade.Body;
        const obstacleBody = obstacle.body as Phaser.Physics.Arcade.Body;

        const isJumpingOn = playerBody.velocity.y > 0 &&
                            playerBody.bottom <= obstacleBody.top + 10;

        if (isJumpingOn) {
            // Sauter dessus = détruit l'obstacle
            obstacle.destroy();
            this.addScore(50); // Bonus pour avoir sauté dessus
            player.jump(); // Petit rebond
            this.playSfx('sfx_saute_champi', 0.6);

            // Effet visuel
            const explosion = this.add.circle(obstacleBody.x, obstacleBody.y, 20, 0x00FF00, 0.5);
            explosion.setDepth(100);
            this.tweens.add({
                targets: explosion,
                scaleX: 2,
                scaleY: 2,
                alpha: 0,
                duration: 300,
                onComplete: () => explosion.destroy(),
            });

            console.log('💚 Obstacle détruit en sautant dessus ! +50 pts');
        } else {
            // Collision frontale = perd une vie
            if (player.getIsInvincible()) {
                console.log('🛡️ Invincible - pas de dégâts');
                return;
            }

            this.playSfx('sfx_hit', 0.6);
            this.loseLife();
        }
    }

    /**
     * Collecte un SUPER TRÉSOR (beaucoup de points!)
     */
    private collectSuperTreasure(_player: any, superTreasure: any): void {
        // Effet visuel de collecte
        this.cameras.main.flash(200, 255, 215, 0, true); // Flash doré

        // Destruction avec effet
        superTreasure.destroy();

        // GROS BONUS de points!
        this.addScore(500);
        this.playSfx('sfx_super', 0.6);

        // Message spécial
        const bonusText = this.add.text(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height / 2,
            '★ SUPER TRÉSOR +500 ★',
            {
                fontSize: '48px',
                color: '#FFD700',
                stroke: '#FF8C00',
                strokeThickness: 6,
                fontStyle: 'bold',
            }
        );
        bonusText.setOrigin(0.5);
        bonusText.setScrollFactor(0);
        bonusText.setDepth(1000);

        // Animation du texte (apparition puis disparition)
        this.tweens.add({
            targets: bonusText,
            scaleX: 1.5,
            scaleY: 1.5,
            alpha: 0,
            duration: 1500,
            ease: 'Power2',
            onComplete: () => {
                bonusText.destroy();
            },
        });

        console.log('🌟 SUPER TRÉSOR COLLECTÉ ! +500 points !');
    }

    /**
     * Ouvre le coffre au trésor final
     */
    private openChest(_player: any, chest: any): void {
        if (chest.canOpen(this.giftsCollected)) {
            const bonus = chest.open(this);
            this.addScore(bonus);

            // VICTOIRE ! Lancer l'animation de fin
            this.time.delayedCall(2000, () => {
                this.levelComplete();
            });
        } else if (!chest.getIsOpen()) {
            // Pas assez de cadeaux
            const remaining = chest.getRequiredGifts() - this.giftsCollected;

            const warning = this.add.text(
                this.cameras.main.scrollX + this.cameras.main.width / 2,
                this.cameras.main.height / 2,
                `❌ Encore ${remaining} cadeaux nécessaires! ❌`,
                {
                    fontSize: '28px',
                    color: '#FF0000',
                    stroke: '#000000',
                    strokeThickness: 4,
                }
            );
            warning.setOrigin(0.5);
            warning.setScrollFactor(0);
            warning.setDepth(1000);

            this.tweens.add({
                targets: warning,
                alpha: 0,
                duration: 2000,
                onComplete: () => warning.destroy(),
            });
        }
    }

    /**
     * Animation de victoire - Niveau terminé !
     */
    private levelComplete(): void {
        console.log('🏆 NIVEAU TERMINÉ ! VICTOIRE !');

        // Arrêter la physique
        this.physics.pause();
        this.playSfx('sfx_levelcomplete', 0.6);

        // Flash doré géant
        this.cameras.main.flash(1000, 255, 215, 0, true);

        // Fond sombre semi-transparent
        const overlay = this.add.rectangle(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height / 2,
            this.cameras.main.width,
            this.cameras.main.height,
            0x000000,
            0.7
        );
        overlay.setScrollFactor(0);
        overlay.setDepth(1500);

        // Message VICTOIRE
        const victoryText = this.add.text(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height / 2 - 150,
            '🏆 NIVEAU TERMINÉ ! 🏆',
            {
                fontSize: '64px',
                color: '#FFD700',
                stroke: '#FF8C00',
                strokeThickness: 10,
                fontStyle: 'bold',
            }
        );
        victoryText.setOrigin(0.5);
        victoryText.setScrollFactor(0);
        victoryText.setDepth(2000);

        // Animation pulsation
        this.tweens.add({
            targets: victoryText,
            scaleX: 1.2,
            scaleY: 1.2,
            duration: 800,
            yoyo: true,
            repeat: -1,
            ease: 'Sine.easeInOut',
        });

        // Statistiques
        const stats = this.add.text(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height / 2 - 20,
            `Score Final: ${this.score}\n\n` +
            `Cadeaux collectés: ${this.giftsCollected}\n` +
            `Vies restantes: ${this.lives}\n\n` +
            `Félicitations !`,
            {
                fontSize: '32px',
                color: '#FFFFFF',
                stroke: '#000000',
                strokeThickness: 6,
                align: 'center',
                lineSpacing: 10,
            }
        );
        stats.setOrigin(0.5);
        stats.setScrollFactor(0);
        stats.setDepth(2000);

        // Message retour menu
        const returnText = this.add.text(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height - 80,
            'Retour au menu dans 7 secondes...',
            {
                fontSize: '24px',
                color: '#CCCCCC',
                stroke: '#000000',
                strokeThickness: 4,
            }
        );
        returnText.setOrigin(0.5);
        returnText.setScrollFactor(0);
        returnText.setDepth(2000);

        // Particules de célébration
        this.createVictoryParticles();

        // Retour au menu après 7 secondes
        this.time.delayedCall(7000, () => {
            this.cleanup();
            this.scene.start('MenuScene');
        });
    }

    /**
     * Crée des particules de célébration pour la victoire
     */
    private createVictoryParticles(): void {
        const centerX = this.cameras.main.scrollX + this.cameras.main.width / 2;

        // Créer 50 particules dorées qui explosent
        for (let i = 0; i < 50; i++) {
            const angle = (i / 50) * Math.PI * 2;
            const radius = 100 + Math.random() * 200;

            const particle = this.add.circle(
                centerX,
                this.cameras.main.height / 2,
                5 + Math.random() * 10,
                Math.random() > 0.5 ? 0xFFD700 : 0xFF8C00
            );
            particle.setScrollFactor(0);
            particle.setDepth(1900);

            this.tweens.add({
                targets: particle,
                x: centerX + Math.cos(angle) * radius,
                y: this.cameras.main.height / 2 + Math.sin(angle) * radius - 100,
                alpha: 0,
                scaleX: 0.2,
                scaleY: 0.2,
                duration: 2000 + Math.random() * 1000,
                ease: 'Power2',
                onComplete: () => {
                    particle.destroy();
                },
            });
        }
    }

    /**
     * Fait perdre une vie au joueur
     */
    private loseLife(): void {
        this.lives--;
        this.livesText?.setText(`❤️ Vies: ${this.lives}`);

        // Flash rouge
        this.cameras.main.flash(200, 255, 0, 0, true);
        this.cameras.main.shake(200, 0.01);

        console.log(`💔 Vie perdue! Vies restantes: ${this.lives}`);

        if (this.lives <= 0) {
            this.gameOver();
        } else {
            this.respawnPlayer();
        }
    }

    /**
     * Réapparaît au dernier checkpoint avec invincibilité
     */
    private respawnPlayer(): void {
        if (!this.player) return;

        // Téléporter au dernier checkpoint
        this.player.setPosition(this.lastCheckpointX, this.cameras.main.height - 200);
        this.player.setVelocity(0, 0);

        // Activer l'invincibilité
        this.player.makeInvincible(this);

        // Message
        const respawnText = this.add.text(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height / 2,
            `💫 RESPAWN! ${this.lives} ❤️ restantes`,
            {
                fontSize: '36px',
                color: '#00FF00',
                stroke: '#000000',
                strokeThickness: 6,
            }
        );
        respawnText.setOrigin(0.5);
        respawnText.setScrollFactor(0);
        respawnText.setDepth(1000);

        this.tweens.add({
            targets: respawnText,
            alpha: 0,
            duration: 2000,
            onComplete: () => respawnText.destroy(),
        });
    }

    /**
     * Game Over - plus de vies
     */
    private gameOver(): void {
        console.log('💀 GAME OVER');

        // Arrêter la physique
        this.physics.pause();
        this.playSfx('sfx_gameover', 0.6);

        // Écran de game over
        const gameOverText = this.add.text(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height / 2 - 50,
            'GAME OVER',
            {
                fontSize: '72px',
                color: '#FF0000',
                stroke: '#000000',
                strokeThickness: 8,
                fontStyle: 'bold',
            }
        );
        gameOverText.setOrigin(0.5);
        gameOverText.setScrollFactor(0);
        gameOverText.setDepth(2000);

        const scoreText = this.add.text(
            this.cameras.main.scrollX + this.cameras.main.width / 2,
            this.cameras.main.height / 2 + 50,
            `Score Final: ${this.score}`,
            {
                fontSize: '36px',
                color: '#FFFFFF',
                stroke: '#000000',
                strokeThickness: 4,
            }
        );
        scoreText.setOrigin(0.5);
        scoreText.setScrollFactor(0);
        scoreText.setDepth(2000);

        // Retour au menu après 3 secondes
        this.time.delayedCall(3000, () => {
            this.cleanup();
            this.scene.start('MenuScene');
        });
    }

    /**
     * Ajoute des points au score
     */
    private addScore(points: number): void {
        this.score += points;
        if (this.score < 0) this.score = 0;
        this.scoreText?.setText(`Score: ${this.score}`);
    }

    /**
     * Termine le jeu
     */
    private endGame(): void {
        console.log(`Jeu terminé ! Score final: ${this.score}`);

        // TODO: Créer une EndScene
        this.add.text(
            this.cameras.main.width / 2,
            this.cameras.main.height / 2,
            `TEMPS ÉCOULÉ!\nScore: ${this.score}`,
            {
                fontSize: '48px',
                color: '#ffffff',
                backgroundColor: '#000000',
                padding: { x: 20, y: 20 },
                align: 'center',
            }
        ).setOrigin(0.5).setScrollFactor(0).setDepth(1000);

        this.time.delayedCall(3000, () => {
            this.cleanup();
            this.scene.start('MenuScene');
        });
    }

    /**
     * Configure et lance la musique de fond
     */
    private setupMusic(): void {
        if (this.bgMusic && this.bgMusic.isPlaying) {
            return;
        }

        this.bgMusic = this.sound.add('bgm', {
            loop: true,
            volume: this.musicVolume,
        });
        this.bgMusic.play();
    }

    /**
     * Met à jour le volume musique (cycle 0%, 20%, 40%, 60%, 80%, 100%)
     */
    private cycleMusicVolume(): void {
        const steps = [0, 0.2, 0.4, 0.6, 0.8, 1];
        const currentIndex = steps.findIndex((v) => v === this.musicVolume);
        const nextIndex = (currentIndex + 1) % steps.length;
        this.musicVolume = steps[nextIndex];

        if (this.bgMusic) {
            const webAudio = this.bgMusic as Phaser.Sound.WebAudioSound;
            const htmlAudio = this.bgMusic as Phaser.Sound.HTML5AudioSound;
            if (typeof webAudio.setVolume === 'function') {
                webAudio.setVolume(this.musicVolume);
            } else if (typeof htmlAudio.setVolume === 'function') {
                htmlAudio.setVolume(this.musicVolume);
            }
            if (this.musicVolume === 0 && this.bgMusic.isPlaying) {
                this.bgMusic.pause();
            } else if (this.musicVolume > 0 && this.bgMusic.isPaused) {
                this.bgMusic.resume();
            } else if (this.musicVolume > 0 && !this.bgMusic.isPlaying) {
                this.bgMusic.play();
            }
        }

        this.volumeText?.setText(this.getVolumeLabel());
    }

    private getVolumeLabel(): string {
        return `🔊 Volume: ${Math.round(this.musicVolume * 100)}% (clic)`;
    }

    /**
     * Met à jour le volume des SFX (cycle 0%, 20%, 40%, 60%, 80%, 100%)
     */
    private cycleSfxVolume(): void {
        const steps = [0, 0.2, 0.4, 0.6, 0.8, 1];
        const currentIndex = steps.findIndex((v) => v === this.sfxVolume);
        const nextIndex = (currentIndex + 1) % steps.length;
        this.sfxVolume = steps[nextIndex];
        this.registry.set('sfxVolume', this.sfxVolume);
        this.sfxVolumeText?.setText(this.getSfxVolumeLabel());
    }

    private getSfxVolumeLabel(): string {
        return `🎚️ Bruitages: ${Math.round(this.sfxVolume * 100)}% (clic)`;
    }

    /**
     * Lecture SFX avec volume global appliqué
     */
    private playSfx(key: string, baseVolume: number = 0.5): void {
        const globalSfxVolume = (this.registry.get('sfxVolume') as number | undefined) ?? this.sfxVolume;
        // Vérifier que l'asset audio existe pour éviter un blocage si le fichier est absent
        const audioCache = this.cache.audio;
        if (!audioCache.exists(key)) {
            console.warn(`SFX manquant: ${key}`);
            return;
        }
        this.sound.play(key, { volume: baseVolume * globalSfxVolume });
    }

    /**
     * Effet de neige qui tombe en overlay
     */
    private createSnow(): void {
        // Texture flocon si absente
        if (!this.textures.exists('snowflake')) {
            const g = this.add.graphics();
            g.fillStyle(0xffffff, 1);
            g.fillCircle(3, 3, 3);
            g.generateTexture('snowflake', 6, 6);
            g.destroy();
        }

        // Emetteur unique attaché à un manager en overlay
        const emitterManager = this.add.particles(0, 0, 'snowflake', {
            x: { min: 0, max: this.cameras.main.width },
            y: -10,
            lifespan: 8000,
            speedY: { min: 50, max: 100 },
            speedX: { min: -20, max: 20 },
            scale: { min: 0.5, max: 1 },
            quantity: 4,
            frequency: 80,
            alpha: { start: 0.9, end: 0.15 },
            rotate: { min: -30, max: 30 },
            blendMode: 'ADD',
            emitZone: { type: 'random', source: new Phaser.Geom.Rectangle(0, 0, this.cameras.main.width, 1) } as any,
        });
        emitterManager.setScrollFactor(0);
        emitterManager.setDepth(2000);

        // Neige qui s'accumule au sol (colonne par colonne)
        const initSnowBuffer = () => {
            const cols = Math.max(10, Math.ceil(this.cameras.main.width / 8));
            this.snowHeights = new Array(cols).fill(0);
            if (!this.snowPileGraphics) {
                this.snowPileGraphics = this.add.graphics();
                this.snowPileGraphics.setScrollFactor(0);
                this.snowPileGraphics.setDepth(5);
            }
            this.renderSnowPile();
        };

        initSnowBuffer();
        this.scale.on('resize', initSnowBuffer);

        const maxHeight = 160;
        this.snowPileTimer = this.time.addEvent({
            delay: 120,
            loop: true,
            callback: () => {
                if (this.snowHeights.length === 0) return;
                const idx = Phaser.Math.Between(0, this.snowHeights.length - 1);
                const add = Phaser.Math.Between(2, 6);
                this.snowHeights[idx] = Math.min(maxHeight, this.snowHeights[idx] + add);
                this.renderSnowPile();
            },
        });
    }

    /**
     * Dessine l'accumulation de neige au sol
     */
    private renderSnowPile(): void {
        if (!this.snowPileGraphics || this.snowHeights.length === 0) return;
        const gfx = this.snowPileGraphics;
        const colWidth = this.cameras.main.width / this.snowHeights.length;
        const baseY = this.cameras.main.height;

        gfx.clear();
        gfx.fillStyle(0xffffff, 0.9);

        this.snowHeights.forEach((h, i) => {
            if (h <= 0) return;
            const x = i * colWidth;
            gfx.fillRect(x, baseY - h, colWidth + 1, h);
        });
    }

    /**
     * Nettoyage avant de quitter la scène
     */
    private cleanup(): void {
        if (this.gyroControl) {
            this.gyroControl.destroy();
        }
        if (this.jumpButton) {
            this.jumpButton.destroy();
        }
        if (this.directionalButtons) {
            this.directionalButtons.destroy();
        }
        if (this.bgMusic) {
            this.bgMusic.stop();
            this.bgMusic.destroy();
        }
        if (this.snowPileTimer) {
            this.snowPileTimer.destroy();
        }
    }
}
