import Phaser from "phaser";
import { BaseGameScene } from "../../../shared/BaseGameScene.js";
import { setupExemploAPI } from "./hooks/setupExemploAPI.js";
import { validationSolution } from "./validation/validators.js";
import { gameConfig } from "./config/config.js";
import { Assets, Constantes } from "./ui/constants.js";
import { montarGrade, criarAlvo, criarJogador } from "./ui/layout.js";

export class ExemploScene extends BaseGameScene {
  constructor() {
    super("ExemploScene");
    this.jogadorLogico = { col: 0, row: 0 };
    this.jogadorSprite = null;
    this.alvoSprite = null;
    this._gridGraphics = null;
    this.executionStopped = false;
  }

  preload() {
    this.preloadGlobalAssets();
    // Carrega o logo via URL pública — assets em /public não precisam de import de módulo
    this.load.image(Assets.CHAVES.LOGO, Assets.PATHS.LOGO);
  }

  create() {
    this.validatorFunc = (historico) =>
      validationSolution(historico, this.configFase, gameConfig, this);

    // Registra a API do interpreter e os handlers de run/reset via BaseGameScene
    this.setupStandardController(
      () => setupExemploAPI(this, { animationSpeed: 200 }),
      this.validatorFunc
    );

    this.montarFase();
  }

  onBeforeRun() {
    this.isRunning = true;
    this.historico = [];
    this.executionStopped = false;
  }

  onReset() {
    this.isRunning = false;
    this.executionStopped = true;
    this.montarFase();
  }

  async onSuccess() {
    this.isRunning = false;
    return new Promise((resolve) => {
      this.tweens.add({
        targets: this.jogadorSprite,
        scaleX: 1.6,
        scaleY: 1.6,
        duration: 180,
        yoyo: true,
        repeat: 2,
        ease: "Back.easeOut",
        onComplete: resolve,
      });
    });
  }

  async onFailure() {
    this.isRunning = false;
    return new Promise((resolve) => {
      this.tweens.add({
        targets: this.jogadorSprite,
        x: "+=6",
        yoyo: true,
        repeat: 8,
        duration: 40,
        onComplete: resolve,
      });
    });
  }

  montarFase() {
    if (this._gridGraphics) this._gridGraphics.destroy();
    if (this.alvoSprite) this.alvoSprite.destroy();
    if (this.jogadorSprite) this.jogadorSprite.destroy();

    const cfg = this.configFase;
    const cols = cfg?.cols || Constantes.COLS;
    const rows = cfg?.rows || Constantes.ROWS;
    const inicio = cfg?.jogadorInicio || { col: 0, row: 0 };
    const alvo = cfg?.alvo || { col: 4, row: 4 };

    this._gridGraphics = montarGrade(this, cols, rows);
    this.alvoSprite = criarAlvo(this, alvo.col, alvo.row);
    this.jogadorLogico = { col: inicio.col, row: inicio.row };
    this.jogadorSprite = criarJogador(this, inicio.col, inicio.row);
    this.executionStopped = false;
  }

  // --- API exposta ao js-interpreter via setupExemploAPI ---

  moverDireita() {
    if (this.executionStopped) return Promise.resolve();

    const novaCol = this.jogadorLogico.col + 1;
    if (novaCol >= (this.configFase?.cols || Constantes.COLS)) {
      return this._falharSaida();
    }

    this.jogadorLogico.col = novaCol;
    this.historico.push({ tipo: "mover", direcao: "DIREITA", col: novaCol, row: this.jogadorLogico.row });
    return this._animarJogador(() => this._checarAlvo());
  }

  moverBaixo() {
    if (this.executionStopped) return Promise.resolve();

    const novaRow = this.jogadorLogico.row + 1;
    if (novaRow >= (this.configFase?.rows || Constantes.ROWS)) {
      return this._falharSaida();
    }

    this.jogadorLogico.row = novaRow;
    this.historico.push({ tipo: "mover", direcao: "BAIXO", col: this.jogadorLogico.col, row: novaRow });
    return this._animarJogador(() => this._checarAlvo());
  }

  // Para o interpreter e agenda handleFailure quando o jogador sai da grade
  _falharSaida() {
    this.executionStopped = true;
    this.gameInterpreter.stopInternal();
    this.time.delayedCall(100, () =>
      this.handleFailure(this.gameConfig?.mensagens?.saiu || "Saiu da tela!")
    );
    return Promise.resolve();
  }

  // Anima o sprite até a posição lógica atual; executa onComplete ao término do tween
  _animarJogador(onComplete) {
    const { CELL_SIZE } = Constantes;
    return new Promise((resolve) => {
      this.tweens.add({
        targets: this.jogadorSprite,
        x: this.jogadorLogico.col * CELL_SIZE + CELL_SIZE / 2,
        y: this.jogadorLogico.row * CELL_SIZE + CELL_SIZE / 2,
        duration: 150,
        ease: "Power1",
        onComplete: () => {
          if (onComplete) onComplete();
          resolve();
        },
      });
    });
  }

  // Verifica se o jogador atingiu o alvo após cada movimento bem-sucedido
  _checarAlvo() {
    if (this.executionStopped) return;
    const alvo = this.configFase?.alvo || { col: 4, row: 4 };
    if (this.jogadorLogico.col !== alvo.col || this.jogadorLogico.row !== alvo.row) return;

    this.executionStopped = true;
    // Para o interpreter sem marcar como parado pelo usuário — validação ainda ocorre
    this.gameInterpreter.stopInternal();
    this.time.delayedCall(300, () => {
      if (this.validatorFunc) this.handleValidation(this.validatorFunc);
    });
  }
}

/**
 * Factory para criar a configuração Phaser do jogo Exemplo.
 * Injeta configFase e gameConfig no registry antes do boot da cena.
 */
export const createGame = (elementoPai, configFaseAtual) => {
  const scene = new ExemploScene();
  const { CELL_SIZE, COLS, ROWS } = Constantes;
  const cols = configFaseAtual?.cols || COLS;
  const rows = configFaseAtual?.rows || ROWS;

  return {
    type: Phaser.AUTO,
    width: cols * CELL_SIZE,
    height: rows * CELL_SIZE,
    backgroundColor: "#1a1a2e",
    parent: elementoPai,
    scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH },
    scene,
    callbacks: {
      preBoot: (game) => {
        game.registry.set("configFase", configFaseAtual);
        game.registry.set("gameConfig", gameConfig);
      },
    },
  };
};
