import { GameState } from '../state/GameState.js';
import { SlotMachine } from '../objects/SlotMachine.js';
import { WinAnimation } from '../objects/WinAnimation.js';
import { LossAnimation } from '../objects/LossAnimation.js';
import { VialDisplay } from '../objects/VialDisplay.js';

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

  create() {
    // Background image — stretched to fill the canvas
    this.add.image(800, 450, 'bg-gates').setDisplaySize(1600, 900);

    // ── Left section: Stage video panel ──────────────────────────────────────
    // Centered at x=160 (within the 360px left of the slot machine), y=490
    // (below the title gradient which ends at y=230). Size: 300x480.
    this._vidX = 160;
    this._vidY = 490;
    this._vidW = 300;
    this._vidH = 480;
    this._currentStage = 2;
    this._activeVideo = null;
    this._gameOver = false;
    this._currentMusicKey = null;
    this._musicSound = null;
    const vidX = this._vidX;
    const vidY = this._vidY;
    const vidW = this._vidW;
    const vidH = this._vidH;

    const vidFrame = this.add.graphics();
    vidFrame.fillStyle(0x0c0620, 0.65);
    vidFrame.fillRoundedRect(vidX - vidW / 2 - 8, vidY - vidH / 2 - 8, vidW + 16, vidH + 16, 14);
    vidFrame.lineStyle(1, 0xffd700, 0.3);
    vidFrame.strokeRoundedRect(vidX - vidW / 2 - 8, vidY - vidH / 2 - 8, vidW + 16, vidH + 16, 14);

    // Start with the stage-02 loop (game begins at stage 2)
    this._setVideo('stage-02', true);
    this._switchMusic(this._getMusicKey(2));

    // Gradient backdrop behind title — opaque on left, fades to transparent
    const titleBg = this.add.graphics();
    titleBg.fillGradientStyle(0x000000, 0x000000, 0x000000, 0x000000, 0.62, 0, 0.62, 0);
    titleBg.fillRect(0, 110, 700, 120);

    // Title above the machine — left aligned with padding
    this.add.text(40, 150, 'VIRTUE SLOTS', {
      fontSize: '42px',
      fontFamily: 'Georgia, serif',
      color: '#ffd700',
      stroke: '#5a3000',
      strokeThickness: 4,
      shadow: { offsetX: 2, offsetY: 2, color: '#000', blur: 6, fill: true }
    }).setOrigin(0, 0.5);

    this.add.text(40, 195, '✝  May Fortune Favor the Faithful  ✝', {
      fontSize: '18px',
      fontFamily: 'Georgia, serif',
      color: '#c8a87e',
      alpha: 0.8
    }).setOrigin(0, 0.5);

    // Slot machine — vertically centered to match The Reckoning panel (y=202–690)
    this.slotMachine = new SlotMachine(this, 710, 446);

    this.winAnim = new WinAnimation();
    this.lossAnim = new LossAnimation();

    // ── Right section: The Reckoning vials ──────────────────────────────────
    // Panel vertically centered in play area (y=100–790), with ~87px right margin
    const sectionBg = this.add.graphics();
    sectionBg.fillStyle(0x0c0620, 0.65);
    sectionBg.fillRoundedRect(1085, 202, 428, 488, 14);
    sectionBg.lineStyle(1, 0xffd700, 0.3);
    sectionBg.strokeRoundedRect(1085, 202, 428, 488, 14);

    this.add.text(1299, 220, 'THE RECKONING', {
      fontSize: '13px', fontFamily: 'Georgia, serif',
      color: '#c8a87e', letterSpacing: 5,
    }).setOrigin(0.5, 0.5);

    this.add.text(1299, 238, 'First to $2,000 wins', {
      fontSize: '10px', fontFamily: 'Georgia, serif', color: '#4a5a6a',
    }).setOrigin(0.5, 0.5);

    this.add.text(1295, 443, 'VS', {
      fontSize: '20px', fontFamily: 'Georgia, serif', fontStyle: 'bold',
      color: '#2a1a4a', stroke: '#000000', strokeThickness: 3,
    }).setOrigin(0.5, 0.5);

    this.lordVial = new VialDisplay(this, 1193, 258, 'The Lord', 0xffd700, 0xc8a87e);
    this.sinVial = new VialDisplay(this, 1398, 258, 'Sin', 0xff4444, 0xff6666);

    // Keyboard: Space to spin
    this.input.keyboard.on('keydown-SPACE', () => this._triggerSpin());

    // Listen for spin button events from UIScene via global event bus
    this.game.events.on('spin', () => this._triggerSpin(), this);

    // Restore the slot machine once animations finish
    this.game.events.on('spin-complete', () => {
      if (!this._gameOver) this.slotMachine.setEnabled(true);
    }, this);

    // Victory: play the victory video, music, and shatter the losing vial
    this.game.events.on('vial-winner', ({ winner }) => {
      this._gameOver = true;
      const lordWins = winner.toLowerCase().includes('lord');
      const key = lordWins ? 'lord-victory' : 'sin-victory';
      this._setVideo(key, false);

      // Fade out background music and play the victory track once
      if (this._musicSound) {
        const outgoing = this._musicSound;
        this._musicSound = null;
        this._currentMusicKey = null;
        this.tweens.add({
          targets: outgoing, volume: 0, duration: 1000,
          onComplete: () => { outgoing.stop(); outgoing.destroy(); },
        });
      }
      this.sound.play(lordWins ? 'music-lord-victory' : 'music-sin-victory');

      // Shatter the losing vial after a brief dramatic pause
      this.time.delayedCall(550, () => {
        if (lordWins) {
          this.sinVial.shatterEvil();
        } else {
          this.lordVial.shatterHoly();
        }
      });
    }, this);
  }

  _triggerSpin() {
    if (GameState.spinning) return;

    if (GameState.playerFunds < GameState.spinCost) {
      this.game.events.emit('insufficient-funds');
      return;
    }

    GameState.playerFunds -= GameState.spinCost;
    GameState.spinning = true;
    this.game.events.emit('funds-updated');
    this.game.events.emit('spinning-started');

    this.slotMachine.spin((result) => this._handleResult(result));
  }

  _handleResult({ win, symbols, payout }) {
    // Dim the slot machine half a second after the reels stop
    this.time.delayedCall(500, () => this.slotMachine.setEnabled(false));
    if (win) {
      const playerGain = Math.round(payout * 0.6);
      const lordGain = payout - playerGain;

      this.game.events.emit('win', { playerGain, lordGain, symbol: symbols[0] });

      // Resolve UI box positions from UIScene
      const uiScene = this.scene.get('UIScene');
      const playerBox = uiScene ? uiScene.getPlayerBoxCenter() : { x: 267, y: 60 };
      const lordBox = uiScene ? uiScene.getLordBoxCenter() : { x: 800, y: 60 };

      this.winAnim.play(
        this,
        this.slotMachine.getCenterX(),
        this.slotMachine.getCenterY(),
        playerBox,
        lordBox,
        symbols[0],
        () => {
          GameState.playerFunds += playerGain;
          GameState.lordFunds += lordGain;
          this.game.events.emit('funds-updated');
          this.lordVial.animateUpdate(GameState.lordFunds, lordBox.x, 115, () => {
            this._handleStageChange(this._computeStage());
            GameState.spinning = false;
            this.game.events.emit('spin-complete');
          });
        }
      );
    } else {
      this.game.events.emit('loss', { sinAdded: GameState.spinCost });

      const uiScene = this.scene.get('UIScene');
      const sinBox = uiScene ? uiScene.getSinBoxCenter() : { x: 1333, y: 60 };

      this.lossAnim.play(
        uiScene || this,
        this.slotMachine.getCenterX(),
        this.slotMachine.getCenterY(),
        sinBox,
        () => {
          GameState.sinTotal += GameState.spinCost;
          this.game.events.emit('funds-updated');
          this.sinVial.animateUpdate(GameState.sinTotal, sinBox.x, 115, () => {
            this._handleStageChange(this._computeStage());
            GameState.spinning = false;
            this.game.events.emit('spin-complete');
          });
        }
      );
    }
  }

  // ── Stage video helpers ───────────────────────────────────────────────────

  /** Compute which stage the Reckoning is currently in based on lord vs sin. */
  _computeStage() {
    const diff = GameState.lordFunds - GameState.sinTotal;
    if (diff >= 200) return 1;
    if (diff > -200) return 2;
    if (diff > -350) return 3;
    if (diff > -500) return 4;
    if (diff > -650) return 5;
    return 6;
  }

  /**
   * Switch the panel video.
   * loop=true  → loops indefinitely (no onComplete needed).
   * loop=false → plays once; calls onComplete when finished (if provided).
   */
  _setVideo(key, loop, onComplete) {
    if (this._activeVideo) {
      this._activeVideo.stop();
      this._activeVideo.destroy();
      this._activeVideo = null;
    }
    const vid = this.add.video(this._vidX, this._vidY, key);
    //vid.setDisplaySize(this._vidW, this._vidH);
    this._activeVideo = vid;
    vid.play(loop);
    if (!loop && onComplete) {
      vid.once('complete', () => {
        if (this._activeVideo === vid) onComplete();
      });
    }
  }

  /**
   * Play a sequence of one-shot videos in order, then call onComplete.
   * keys = array of video keys to play in sequence.
   */
  _playSequence(keys, onComplete) {
    if (keys.length === 0) {
      if (onComplete) onComplete();
      return;
    }
    const [first, ...rest] = keys;
    this._setVideo(first, false, () => this._playSequence(rest, onComplete));
  }

  /**
   * Called after each spin resolves. Calculates needed transitions and
   * plays them in sequence before resuming the looping stage video.
   */
  _handleStageChange(newStage) {
    if (this._gameOver) return;
    if (newStage === this._currentStage) return;

    const oldStage = this._currentStage;
    this._currentStage = newStage;

    this._switchMusic(this._getMusicKey(newStage));

    const pad = n => String(n).padStart(2, '0');
    const direction = newStage > oldStage ? 1 : -1;
    const transitions = [];
    for (let s = oldStage; s !== newStage; s += direction) {
      transitions.push(`stage-${pad(s)}-${pad(s + direction)}`);
    }

    this._playSequence(transitions, () => {
      if (!this._gameOver) this._setVideo(`stage-${pad(newStage)}`, true);
    });
  }

  /** Map a stage number to its music track key. */
  _getMusicKey(stage) {
    if (stage <= 2) return 'music-01-02';
    if (stage <= 4) return 'music-03-04';
    return 'music-05-06';
  }

  /** Crossfade from the current music track to newKey (no-op if already playing). */
  _switchMusic(newKey) {
    if (newKey === this._currentMusicKey) return;
    this._currentMusicKey = newKey;

    // Fade out and destroy the outgoing track
    if (this._musicSound) {
      const outgoing = this._musicSound;
      this.tweens.add({
        targets: outgoing,
        volume: 0,
        duration: 1000,
        onComplete: () => { outgoing.stop(); outgoing.destroy(); },
      });
    }

    // Fade in the incoming track from silence
    this._musicSound = this.sound.add(newKey, { loop: true, volume: 0 });
    this._musicSound.play();
    this.tweens.add({ targets: this._musicSound, volume: 1, duration: 1000 });
  }
}
